Documentation
¶
Overview ¶
Package auth provides authentication support for the platform.
Index ¶
- Variables
- func GetToken(ctx context.Context) string
- func LooksLikeJWT(s string) bool
- func ValidateClaims(claims map[string]any, required []string) error
- func WithToken(ctx context.Context, token string) context.Context
- func WithUserContext(ctx context.Context, uc *UserContext) context.Context
- type APIKey
- type APIKeyAuthenticator
- func (a *APIKeyAuthenticator) AddHashedKey(key APIKey)
- func (a *APIKeyAuthenticator) AddKey(key APIKey)
- func (a *APIKeyAuthenticator) Authenticate(ctx context.Context) (*middleware.UserInfo, error)
- func (a *APIKeyAuthenticator) GenerateKey(def APIKey) (string, error)
- func (a *APIKeyAuthenticator) ListKeys() []APIKeySummary
- func (a *APIKeyAuthenticator) RemoveByName(name string) bool
- func (a *APIKeyAuthenticator) RemoveKey(keyValue string)
- type APIKeyConfig
- type APIKeyExtractor
- type APIKeySummary
- type BearerTokenExtractor
- type ChainedAuthConfig
- type ChainedAuthenticator
- type ClaimsExtractor
- type OAuthJWTAuthenticator
- type OAuthJWTConfig
- type OIDCAuthenticator
- type OIDCConfig
- type TokenExtractor
- type UserContext
Constants ¶
This section is empty.
Variables ¶
var ErrNotAJWT = errors.New("not a JWT")
ErrNotAJWT is the sentinel returned by JWT-based authenticators when the supplied credential does not have the structural shape of a JWT (three non-empty dot-separated segments). It is a fallthrough signal, not a security event: the chained authenticator recognizes it and silently advances to the next authenticator without logging.
Functions ¶
func GetToken ¶
GetToken retrieves a token from the context. Delegates to middleware.GetToken so that both packages share the same context key.
func LooksLikeJWT ¶ added in v1.64.0
LooksLikeJWT returns true when s has the structural shape of a JWT (three non-empty dot-separated segments). This is a cheap pre-check used by JWT-based authenticators to short-circuit non-JWT credentials (e.g. API keys) without invoking the JWT library or surfacing a low-level parse error to operators.
func ValidateClaims ¶
ValidateClaims validates required claims are present.
func WithToken ¶
WithToken adds a token to the context. Delegates to middleware.WithToken so that both packages share the same context key.
func WithUserContext ¶
func WithUserContext(ctx context.Context, uc *UserContext) context.Context
WithUserContext adds user context to the context.
Types ¶
type APIKey ¶
type APIKey struct {
Key string // The API key value (plaintext; used for file-loaded keys)
KeyHash string // bcrypt hash of the key value (used for DB-loaded keys)
Name string // Display name for the key
Email string // Email address for this key (optional; defaults to name@apikey.local)
Description string // Human-readable description of what this key is for
Roles []string // Roles assigned to this key
ExpiresAt *time.Time // Optional expiration time (nil = never expires)
}
APIKey represents an API key entry.
type APIKeyAuthenticator ¶
type APIKeyAuthenticator struct {
// contains filtered or unexported fields
}
APIKeyAuthenticator authenticates using API keys. File-loaded keys (plaintext) are stored in fileKeys for O(1) lookup. DB-loaded keys (bcrypt hashed) are stored in hashedKeys as a slice, checked via bcrypt only when no file key matches — limiting DoS surface.
func NewAPIKeyAuthenticator ¶
func NewAPIKeyAuthenticator(cfg APIKeyConfig) *APIKeyAuthenticator
NewAPIKeyAuthenticator creates a new API key authenticator.
func (*APIKeyAuthenticator) AddHashedKey ¶ added in v1.49.0
func (a *APIKeyAuthenticator) AddHashedKey(key APIKey)
AddHashedKey adds a bcrypt-hashed API key at runtime. The Key (plaintext) field is cleared to prevent accidental exposure. These keys are stored in a separate slice and authenticated via bcrypt.
func (*APIKeyAuthenticator) AddKey ¶
func (a *APIKeyAuthenticator) AddKey(key APIKey)
AddKey adds a plaintext API key at runtime. The KeyHash field is ignored to prevent accidental misuse; use AddHashedKey for bcrypt-hashed keys.
func (*APIKeyAuthenticator) Authenticate ¶
func (a *APIKeyAuthenticator) Authenticate(ctx context.Context) (*middleware.UserInfo, error)
Authenticate validates the API key and returns user info. It first checks file keys via constant-time compare (fast O(1) path), then falls back to bcrypt comparison against hashed keys (slow path).
func (*APIKeyAuthenticator) GenerateKey ¶ added in v0.17.0
func (a *APIKeyAuthenticator) GenerateKey(def APIKey) (string, error)
GenerateKey creates a new API key with server-generated value. Returns the key value (shown only once) or an error if the name is duplicate.
func (*APIKeyAuthenticator) ListKeys ¶ added in v0.17.0
func (a *APIKeyAuthenticator) ListKeys() []APIKeySummary
ListKeys returns summaries of all registered keys (never exposes key values). Keys that exist in both file config and the database are deduplicated and reported with Source "both".
func (*APIKeyAuthenticator) RemoveByName ¶ added in v0.17.0
func (a *APIKeyAuthenticator) RemoveByName(name string) bool
RemoveByName removes an API key by its display name. Searches both file keys and hashed keys. Returns true if a key was found and removed.
func (*APIKeyAuthenticator) RemoveKey ¶
func (a *APIKeyAuthenticator) RemoveKey(keyValue string)
RemoveKey removes a plaintext API key by its value.
type APIKeyConfig ¶
type APIKeyConfig struct {
Keys []APIKey
}
APIKeyConfig holds API key configuration.
type APIKeyExtractor ¶
type APIKeyExtractor struct {
HeaderName string // e.g., "X-API-Key"
QueryParam string // e.g., "api_key"
}
APIKeyExtractor extracts API keys from headers or query params.
type APIKeySummary ¶ added in v0.17.0
type APIKeySummary struct {
Name string `json:"name" example:"ci-pipeline"`
Email string `json:"email,omitempty" example:"ci@example.com"`
Description string `json:"description,omitempty" example:"CI/CD pipeline integration"`
Roles []string `json:"roles" example:"analyst"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
Expired bool `json:"expired,omitempty" example:"false"`
Source string `json:"source,omitempty" example:"database"` // "file", "database", or "both"
}
APIKeySummary is a safe representation of a key (never exposes the key value).
type BearerTokenExtractor ¶
type BearerTokenExtractor struct {
HeaderName string // Default: "Authorization"
}
BearerTokenExtractor extracts Bearer tokens from Authorization header.
type ChainedAuthConfig ¶
type ChainedAuthConfig struct {
AllowAnonymous bool
}
ChainedAuthConfig configures the chained authenticator.
type ChainedAuthenticator ¶
type ChainedAuthenticator struct {
// contains filtered or unexported fields
}
ChainedAuthenticator tries multiple authenticators in order.
func NewChainedAuthenticator ¶
func NewChainedAuthenticator(cfg ChainedAuthConfig, authenticators ...middleware.Authenticator) *ChainedAuthenticator
NewChainedAuthenticator creates a new chained authenticator.
func (*ChainedAuthenticator) Authenticate ¶
func (c *ChainedAuthenticator) Authenticate(ctx context.Context) (*middleware.UserInfo, error)
Authenticate tries each authenticator in order.
An authenticator returning ErrNotAJWT is a structural fallthrough (e.g. JWT authenticator handed an API key) and is NOT logged: it is the chain's normal "this authenticator can't handle this credential type, try the next one" path. Real verification failures (bad signature, wrong issuer, expired token, no matching API key) are logged at DEBUG with correlation context.
lastErr tracks the most recent real (non-sentinel) error so a failed-everywhere chain surfaces a meaningful reason instead of the noisy ErrNotAJWT sentinel.
type ClaimsExtractor ¶
type ClaimsExtractor struct {
// RoleClaimPath is the dot-separated path to roles in claims.
// e.g., "realm_access.roles" or "roles"
RoleClaimPath string
// RolePrefix filters roles to those starting with this prefix.
RolePrefix string
// GroupClaimPath is the dot-separated path to groups in claims.
GroupClaimPath string
// EmailClaimPath is the path to the email claim.
EmailClaimPath string
// NameClaimPath is the path to the name claim.
NameClaimPath string
// SubjectClaimPath is the path to the subject claim.
SubjectClaimPath string
}
ClaimsExtractor extracts values from JWT claims.
func DefaultClaimsExtractor ¶
func DefaultClaimsExtractor() *ClaimsExtractor
DefaultClaimsExtractor returns an extractor with common defaults.
func (*ClaimsExtractor) Extract ¶
func (e *ClaimsExtractor) Extract(claims map[string]any) (*UserContext, error)
Extract extracts user context from claims.
type OAuthJWTAuthenticator ¶ added in v0.4.0
type OAuthJWTAuthenticator struct {
// contains filtered or unexported fields
}
OAuthJWTAuthenticator validates JWT access tokens issued by our OAuth server.
func NewOAuthJWTAuthenticator ¶ added in v0.4.0
func NewOAuthJWTAuthenticator(cfg OAuthJWTConfig) (*OAuthJWTAuthenticator, error)
NewOAuthJWTAuthenticator creates a new OAuth JWT authenticator.
func (*OAuthJWTAuthenticator) Authenticate ¶ added in v0.4.0
func (a *OAuthJWTAuthenticator) Authenticate(ctx context.Context) (*middleware.UserInfo, error)
Authenticate validates the JWT token and returns user info.
type OAuthJWTConfig ¶ added in v0.4.0
type OAuthJWTConfig struct {
// Issuer is the expected issuer claim in the JWT.
Issuer string
// SigningKey is the HMAC key used to verify JWT signatures.
SigningKey []byte
// RoleClaimPath is the path to roles within the nested "claims" object.
// e.g., "realm_access.roles" extracts claims["claims"]["realm_access"]["roles"]
RoleClaimPath string
// RolePrefix filters roles to those with this prefix.
RolePrefix string
}
OAuthJWTConfig configures the OAuth JWT authenticator.
type OIDCAuthenticator ¶
type OIDCAuthenticator struct {
// contains filtered or unexported fields
}
OIDCAuthenticator authenticates using OIDC tokens.
func NewOIDCAuthenticator ¶
func NewOIDCAuthenticator(cfg OIDCConfig) (*OIDCAuthenticator, error)
NewOIDCAuthenticator creates a new OIDC authenticator.
func (*OIDCAuthenticator) Authenticate ¶
func (a *OIDCAuthenticator) Authenticate(ctx context.Context) (*middleware.UserInfo, error)
Authenticate validates the token and returns user info.
func (*OIDCAuthenticator) FetchJWKS ¶
func (a *OIDCAuthenticator) FetchJWKS(ctx context.Context) error
FetchJWKS fetches the JWKS from the issuer and parses RSA public keys.
func (*OIDCAuthenticator) RefreshJWKS ¶ added in v0.2.0
func (a *OIDCAuthenticator) RefreshJWKS(ctx context.Context) error
RefreshJWKS refreshes the JWKS cache. Call this periodically or when keys expire.
type OIDCConfig ¶
type OIDCConfig struct {
// Issuer is the OIDC issuer URL.
Issuer string
// ClientID is the OAuth client ID.
ClientID string
// Audience is the expected audience claim.
Audience string
// RoleClaimPath is the path to roles in claims.
RoleClaimPath string
// RolePrefix filters roles to those with this prefix.
RolePrefix string
// ClockSkewSeconds is the allowed clock skew for time-based claims (default: 30).
ClockSkewSeconds int
// MaxTokenAge is the maximum allowed age of a token based on iat claim (0 = no limit).
MaxTokenAge time.Duration
// SkipIssuerVerification skips issuer verification (for testing).
SkipIssuerVerification bool
// SkipSignatureVerification skips JWT signature verification (for testing only).
// WARNING: Never enable in production - allows forged tokens.
SkipSignatureVerification bool
}
OIDCConfig configures OIDC authentication.
type TokenExtractor ¶
TokenExtractor extracts tokens from various sources.
type UserContext ¶
type UserContext struct {
UserID string `json:"user_id"`
Email string `json:"email,omitempty"`
Name string `json:"name,omitempty"`
Roles []string `json:"roles,omitempty"`
Groups []string `json:"groups,omitempty"`
Claims map[string]any `json:"claims,omitempty"`
AuthType string `json:"auth_type"` // "oidc", "apikey"
TokenType string `json:"token_type,omitempty"`
}
UserContext holds authenticated user information.
func GetUserContext ¶
func GetUserContext(ctx context.Context) *UserContext
GetUserContext retrieves user context from the context.
func (*UserContext) HasAnyRole ¶
func (uc *UserContext) HasAnyRole(roles ...string) bool
HasAnyRole checks if the user has any of the specified roles.
func (*UserContext) HasRole ¶
func (uc *UserContext) HasRole(role string) bool
HasRole checks if the user has a specific role.
func (*UserContext) InGroup ¶
func (uc *UserContext) InGroup(group string) bool
InGroup checks if the user is in a specific group.