Skip to content

Commit

Permalink
Deduplicate JWT header authenticator code
Browse files Browse the repository at this point in the history
  • Loading branch information
moroten committed Feb 4, 2025
1 parent 7339d98 commit d87ffa4
Show file tree
Hide file tree
Showing 7 changed files with 28 additions and 79 deletions.
1 change: 0 additions & 1 deletion pkg/grpc/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ go_library(
"deduplicating_client_factory.go",
"deny_authenticator.go",
"jmespath_extractor.go",
"jwt_authenticator.go",
"lazy_client_dialer.go",
"metadata_adding_interceptor.go",
"metadata_extracting_and_forwarding_interceptor.go",
Expand Down
12 changes: 6 additions & 6 deletions pkg/grpc/authenticator.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,15 @@ func NewAuthenticatorFromConfiguration(policy *configuration.AuthenticationPolic
if err != nil {
return nil, false, false, util.StatusWrap(err, "Failed to create authorization header parser for JWT authentication policy")
}
return NewJWTAuthenticator(authorizationHeaderParser), false, false, nil
return NewRequestHeadersAuthenticator(authorizationHeaderParser, []string{jwt.AuthorizationHeaderName}), false, false, nil
case *configuration.AuthenticationPolicy_PeerCredentialsJmespathExpression:
metadataExtractor, err := jmespath.Compile(policyKind.PeerCredentialsJmespathExpression)
if err != nil {
return nil, false, false, util.StatusWrap(err, "Failed to compile peer credentials metadata extraction JMESPath expression")
}
return NewPeerCredentialsAuthenticator(metadataExtractor), true, false, nil
case *configuration.AuthenticationPolicy_Remote:
authenticator, err := NewRequestHeadersAuthenticatorFromConfiguration(policyKind.Remote.Backend, grpcClientFactory)
authenticator, err := NewRemoteRequestHeadersAuthenticatorFromConfiguration(policyKind.Remote.Backend, grpcClientFactory)
if err != nil {
return nil, false, false, err
}
Expand All @@ -109,10 +109,10 @@ func NewAuthenticatorFromConfiguration(policy *configuration.AuthenticationPolic
}
}

// NewRequestHeadersAuthenticatorFromConfiguration creates an Authenticator that
// forwards authentication requests to a remote gRPC service. This is a
// convenient way to integrate custom authentication processes.
func NewRequestHeadersAuthenticatorFromConfiguration(configuration *configuration.RemoteAuthenticationPolicy, grpcClientFactory ClientFactory) (auth.RequestHeadersAuthenticator, error) {
// NewRemoteRequestHeadersAuthenticatorFromConfiguration creates an
// Authenticator that forwards authentication requests to a remote gRPC service.
// This is a convenient way to integrate custom authentication processes.
func NewRemoteRequestHeadersAuthenticatorFromConfiguration(configuration *configuration.RemoteAuthenticationPolicy, grpcClientFactory ClientFactory) (auth.RequestHeadersAuthenticator, error) {
grpcClient, err := grpcClientFactory.NewClientFromConfiguration(configuration.Endpoint)
if err != nil {
return nil, util.StatusWrap(err, "Failed to create authenticator RPC client")
Expand Down
37 changes: 0 additions & 37 deletions pkg/grpc/jwt_authenticator.go

This file was deleted.

1 change: 0 additions & 1 deletion pkg/http/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ go_library(
"configuration.go",
"deny_authenticator.go",
"header_adding_round_tripper.go",
"jwt_authenticator.go",
"metrics_handler.go",
"metrics_round_tripper.go",
"oidc_authenticator.go",
Expand Down
8 changes: 6 additions & 2 deletions pkg/http/authenticator.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@ func NewAuthenticatorFromConfiguration(policy *configuration.AuthenticationPolic
if err != nil {
return nil, util.StatusWrap(err, "Failed to create authorization header parser for JWT authentication policy")
}
return NewJWTAuthenticator(authorizationHeaderParser), nil
authenticator, err := NewRequestHeadersAuthenticator(authorizationHeaderParser, []string{jwt.AuthorizationHeaderName})
if err != nil {
return nil, util.StatusWrap(err, "Failed to create request headers authenticator for JWT authentication policy")
}
return authenticator, nil
case *configuration.AuthenticationPolicy_Oidc:
// Select a name and encryption key for the session
// state cookie. Even though the configuration has a
Expand Down Expand Up @@ -126,7 +130,7 @@ func NewAuthenticatorFromConfiguration(policy *configuration.AuthenticationPolic
}
return NewAcceptHeaderAuthenticator(base, policyKind.AcceptHeader.MediaTypes), nil
case *configuration.AuthenticationPolicy_Remote:
backend, err := grpc.NewRequestHeadersAuthenticatorFromConfiguration(policyKind.Remote.Backend, grpcClientFactory)
backend, err := grpc.NewRemoteRequestHeadersAuthenticatorFromConfiguration(policyKind.Remote.Backend, grpcClientFactory)
if err != nil {
return nil, err
}
Expand Down
32 changes: 0 additions & 32 deletions pkg/http/jwt_authenticator.go

This file was deleted.

16 changes: 16 additions & 0 deletions pkg/jwt/authorization_header_parser.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package jwt

import (
"context"
"encoding/base64"
"encoding/json"
"log"
Expand All @@ -13,8 +14,14 @@ import (
"github.com/buildbarn/bb-storage/pkg/clock"
"github.com/buildbarn/bb-storage/pkg/eviction"
"github.com/jmespath/go-jmespath"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

// AuthorizationHeaderName is the name of the HTTP header that contains
// the JSON Web Token.
const AuthorizationHeaderName = "Authorization"

// Pattern of authorization headers from which to extract a JSON Web Token.
var jwtHeaderPattern = regexp.MustCompile("^Bearer\\s+(([-_a-zA-Z0-9]+)\\.([-_a-zA-Z0-9]+))\\.([-_a-zA-Z0-9]+)$")

Expand Down Expand Up @@ -83,6 +90,15 @@ func jsonNumberAsTimestamp(n *json.Number) (time.Time, error) {
return time.Unix(int64(i), int64(frac*1e9)), nil
}

// Authenticate is the implementation of RequestHeadersAuthenticator.Authenticate.
func (a *AuthorizationHeaderParser) Authenticate(ctx context.Context, headers map[string][]string) (*auth.AuthenticationMetadata, error) {
metadata, ok := a.ParseAuthorizationHeaders(headers[AuthorizationHeaderName])
if !ok {
return nil, status.Error(codes.Unauthenticated, "No valid authorization header containing a bearer token provided")
}
return metadata, nil
}

func (a *AuthorizationHeaderParser) parseSingleAuthorizationHeader(header string, now time.Time) response {
match := jwtHeaderPattern.FindStringSubmatch(header)
if match == nil {
Expand Down

0 comments on commit d87ffa4

Please sign in to comment.