Documentation
¶
Overview ¶
Package auth authenticates requests arriving at the proxy.
An Authenticator decides whether a caller may proceed, and StreamServerInterceptor applies one to every inbound stream, rejecting a caller before the stream is routed and stripping the credential headers it consumed so they never reach an upstream.
Module selects the authenticator from configuration: a fixed static token, OIDC/JWKS verification, or an extension server that decides on the proxy's behalf. Authentication is opt-in, so an absent auth block admits every request, but a block that selects nothing usable is an error rather than a silent return to admitting everyone.
A refused caller is told only a generic status. The reason travels alongside it for the proxy's log, so a rejection is diagnosable without telling the caller which part of its credential failed.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var Module = fx.Options(fx.Provide(func(cfg *config.Config, conns api.Connections) (Authenticator, error) { ac := cfg.Auth if ac == nil { return &defaultAuthenticator{}, nil } selected := 0 for _, set := range []bool{ac.External != nil, ac.StaticToken != nil, ac.JWKS != nil} { if set { selected++ } } if selected != 1 { return nil, errors.New("auth: exactly one of external, staticToken, or jwks must be configured") } switch { case ac.External != nil: cc, ok := conns[ac.External.Name] if !ok { return nil, fmt.Errorf("auth: external authentication names unknown extension server %q", ac.External.Name) } return api.NewAuth(cc, ac.External.CredentialHeaders), nil case ac.StaticToken != nil: return NewStaticTokenAuthenticator( ac.StaticToken.Token, ac.StaticToken.Header, ac.StaticToken.Scheme, ) default: return NewJWKSAuthenticator( ac.JWKS.URL, ac.JWKS.Audiences, ac.JWKS.Issuer, ac.JWKS.Header, ac.JWKS.Scheme, ) } }))
Module provides the inbound Authenticator selected by configuration: a static token, OIDC/JWKS, or an extension server that decides on the proxy's behalf, when exactly one is configured. With no auth block it provides a default authenticator that admits every request (authentication is opt-in); a block that selects none or several is a configuration error, so an invalid block fails closed rather than admitting traffic. The server adapts the Authenticator into a stream interceptor via StreamServerInterceptor.
The external variant needs a connection to the extension server that answers for it, which is why the selection depends on the configured extension server connections. Naming one that is not configured fails here rather than on the first request, since an authenticator with nowhere to ask would reject every caller.
Functions ¶
func StreamServerInterceptor ¶
func StreamServerInterceptor(a Authenticator, log logger.Logger) grpc.StreamServerInterceptor
StreamServerInterceptor adapts an Authenticator to a gRPC stream server interceptor, logging each rejection's detailed reason (never the token) via log. a must be non-nil; callers get one from the auth module, where the unconfigured case is the admit-all default. A nil log falls back to the default logger.
Types ¶
type Authenticator ¶
type Authenticator interface {
Authenticate(ctx context.Context, md metadata.MD) error
SecureHeaders() []string
}
Authenticator authenticates an inbound request from its metadata. It returns nil to allow the request, or a gRPC status error to reject it. SecureHeaders reports the metadata headers the authenticator consumes, so the proxy can strip the caller's credentials before forwarding upstream; it returns nil when the authenticator consumes no header. An authenticator may name more than one because it need not own the header it reads: an external one is told which headers its server consumes.
type JWKSAuthenticator ¶
type JWKSAuthenticator struct {
// contains filtered or unexported fields
}
JWKSAuthenticator verifies an inbound JWT's signature against a JWKS keyset and checks its standard claims.
func NewJWKSAuthenticator ¶
func NewJWKSAuthenticator(rawURL string, audiences []string, issuer, header, scheme string) (*JWKSAuthenticator, error)
NewJWKSAuthenticator builds a JWKSAuthenticator that resolves signing keys from the JWKS at rawURL.
keyfunc.NewDefaultOverrideCtx performs its first key fetch synchronously (see github.com/MicahParks/jwkset's NewStorageFromHTTP), so calling it directly here would block construction for up to its HTTP timeout if the IdP is unreachable. To keep construction non-blocking, the fetch is kicked off in a background goroutine (via deferredKeyfunc); until it completes, Authenticate reports codes.Unavailable (fail closed, retryable) instead of blocking startup.
rawURL is validated synchronously before the goroutine is started, so a malformed configuration (bad scheme/host, not a transient IdP outage) fails construction immediately instead of surfacing as a permanent codes.Unavailable for every future request.
func (*JWKSAuthenticator) Authenticate ¶
Authenticate verifies the JWT carried in md: signature via the JWKS keyset, expiry, and (when configured) issuer and audience.
func (*JWKSAuthenticator) SecureHeaders ¶ added in v0.4.0
func (a *JWKSAuthenticator) SecureHeaders() []string
SecureHeaders reports the single metadata header this authenticator consumes, so StreamServerInterceptor can strip it before forwarding upstream.
type StaticTokenAuthenticator ¶
type StaticTokenAuthenticator struct {
// contains filtered or unexported fields
}
StaticTokenAuthenticator authenticates a request by comparing the bearer token in its metadata against a fixed configured value.
func NewStaticTokenAuthenticator ¶
func NewStaticTokenAuthenticator(token, header, scheme string) (*StaticTokenAuthenticator, error)
NewStaticTokenAuthenticator builds a StaticTokenAuthenticator. header and scheme default to "authorization" and "Bearer" when blank. A blank token is an error.
func (*StaticTokenAuthenticator) Authenticate ¶
Authenticate compares the extracted token against the configured value in constant time.
func (*StaticTokenAuthenticator) SecureHeaders ¶ added in v0.4.0
func (a *StaticTokenAuthenticator) SecureHeaders() []string
SecureHeaders reports the single metadata header this authenticator consumes, so StreamServerInterceptor can strip it before forwarding upstream.