auth

package
v1.66.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 20, 2026 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Overview

Package auth provides authentication support for the platform.

Index

Constants

This section is empty.

Variables

View Source
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

func GetToken(ctx context.Context) string

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

func LooksLikeJWT(s string) bool

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

func ValidateClaims(claims map[string]any, required []string) error

ValidateClaims validates required claims are present.

func WithToken

func WithToken(ctx context.Context, token string) context.Context

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.

func (*APIKey) IsExpired added in v1.49.0

func (k *APIKey) IsExpired() bool

IsExpired returns true if the key has an expiration date that has passed.

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.

func (*APIKeyExtractor) Extract

func (*APIKeyExtractor) Extract(ctx context.Context) (string, error)

Extract extracts an API key from the context.

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.

func (*BearerTokenExtractor) Extract

func (*BearerTokenExtractor) Extract(ctx context.Context) (string, error)

Extract extracts a bearer token from the context.

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

type TokenExtractor interface {
	Extract(ctx context.Context) (string, error)
}

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL