apiauth

package
v0.0.73 Latest Latest
Warning

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

Go to latest
Published: Apr 17, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GetAuthTypeFromAPIContext

func GetAuthTypeFromAPIContext(ctx context.Context) string

GetAuthTypeFromAPIContext retrieves the auth type ("jwt" or "api_key") from context

func GetCustomClaimsFromContext

func GetCustomClaimsFromContext(ctx context.Context) map[string]any

GetCustomClaimsFromContext retrieves the custom (non-standard) JWT claims from context. Returns nil if no custom claims are present (e.g., API key auth or no token).

func GetScopesFromAPIContext

func GetScopesFromAPIContext(ctx context.Context) []string

GetScopesFromAPIContext retrieves the granted scopes from the API middleware context

func GetUserIDFromAPIContext

func GetUserIDFromAPIContext(ctx context.Context) string

GetUserIDFromAPIContext retrieves the user ID from the API middleware context

func NewASMetadataHandler added in v0.0.56

func NewASMetadataHandler(meta *ASServerMetadata) http.Handler

NewASMetadataHandler returns an http.Handler that serves Authorization Server metadata JSON at GET /.well-known/openid-configuration.

The handler:

  • Responds to GET only (405 for other methods)
  • Sets Content-Type: application/json
  • Sets Cache-Control: public, max-age=<CacheMaxAge>
  • Pre-serializes the response (metadata is static)

func NewProtectedResourceHandler added in v0.0.55

func NewProtectedResourceHandler(meta *ProtectedResourceMetadata) http.Handler

NewProtectedResourceHandler returns an http.Handler that serves the Protected Resource Metadata JSON at GET /.well-known/oauth-protected-resource.

The handler:

  • Responds to GET only (405 for other methods)
  • Sets Content-Type: application/json
  • Sets Cache-Control: public, max-age=<CacheMaxAge>
  • Serializes the metadata as JSON with omitempty on optional fields

Types

type APIAuth

type APIAuth struct {
	// Stores
	RefreshTokenStore core.RefreshTokenStore
	APIKeyStore       core.APIKeyStore

	// JWT configuration
	JWTSecretKey  string // Secret key for signing JWTs (HMAC)
	JWTIssuer     string // Issuer claim (e.g., "myapp")
	JWTAudience   string // Audience claim (e.g., "api")
	JWTSigningAlg string // Signing algorithm (defaults to HS256)

	// Asymmetric JWT keys (optional — when set, these take precedence over JWTSecretKey)
	JWTSigningKey any // crypto.PrivateKey (*rsa.PrivateKey or *ecdsa.PrivateKey) for signing
	JWTVerifyKey  any // crypto.PublicKey (*rsa.PublicKey or *ecdsa.PublicKey) for verification

	// Token configuration
	AccessTokenExpiry  time.Duration // Defaults to 15 minutes
	RefreshTokenExpiry time.Duration // Defaults to 7 days

	// Callbacks
	ValidateCredentials core.CredentialsValidator                         // Validates username/password
	GetUserScopes       core.GetUserScopesFunc                            // Returns allowed scopes for a user
	OnLoginSuccess      func(userID string, r *http.Request)              // Optional: for logging/analytics
	OnLoginFailure      func(username string, r *http.Request, err error) // Optional: for logging/analytics

	// CustomClaimsFunc is called during token creation to inject additional claims
	// into the JWT (e.g., client_id, max_rooms for relay-scoped tokens).
	// Standard claims (sub, iss, aud, exp, iat, type, scopes) cannot be overridden.
	// If nil, no custom claims are added (backwards-compatible).
	CustomClaimsFunc func(userID string, scopes []string) (map[string]any, error)

	// ClientKeyStore provides client credential lookup for the client_credentials
	// grant type (RFC 6749 §4.4). When set, the token endpoint accepts
	// grant_type=client_credentials and authenticates clients via KeyStore.
	// When nil, client_credentials requests return unsupported_grant_type.
	ClientKeyStore keys.KeyLookup

	// Rate limiting (optional)
	RateLimiter core.RateLimiter

	// Blacklist enables immediate access token revocation. When set,
	// ValidateAccessToken checks the blacklist after signature verification.
	// Tokens include a jti (JWT ID) claim for blacklist lookup.
	// If nil, tokens are validated by signature + expiry only (stateless).
	Blacklist core.TokenBlacklist
}

APIAuth handles API token-based authentication

func (*APIAuth) CreateAccessToken

func (a *APIAuth) CreateAccessToken(userID string, scopes []string) (string, int64, error)

CreateAccessToken creates a signed JWT access token. If CustomClaimsFunc is set, its returned claims are merged into the token (standard claims cannot be overridden).

func (*APIAuth) HandleAPIKeys

func (a *APIAuth) HandleAPIKeys(w http.ResponseWriter, r *http.Request)

HandleAPIKeys handles API key management (GET=list, POST=create) Requires authentication (userID must be in request context)

func (*APIAuth) HandleListSessions

func (a *APIAuth) HandleListSessions(w http.ResponseWriter, r *http.Request)

HandleListSessions handles GET /api/sessions - lists active sessions for the user Requires authentication (userID must be in request context)

func (*APIAuth) HandleLogout

func (a *APIAuth) HandleLogout(w http.ResponseWriter, r *http.Request)

HandleLogout handles POST /api/logout - revokes a refresh token

func (*APIAuth) HandleLogoutAll

func (a *APIAuth) HandleLogoutAll(w http.ResponseWriter, r *http.Request)

HandleLogoutAll handles POST /api/logout-all - revokes all refresh tokens for the user Requires authentication (userID must be in request context)

func (*APIAuth) HandleRevokeAPIKey

func (a *APIAuth) HandleRevokeAPIKey(w http.ResponseWriter, r *http.Request)

HandleRevokeAPIKey handles DELETE /api/keys/:id - revokes an API key Requires authentication (userID must be in request context)

func (*APIAuth) ServeHTTP

func (a *APIAuth) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP handles the /api/token endpoint. It accepts both application/x-www-form-urlencoded (RFC 6749 standard) and application/json request bodies.

See: https://www.rfc-editor.org/rfc/rfc6749#section-4.4.2

func (*APIAuth) ValidateAccessToken

func (a *APIAuth) ValidateAccessToken(tokenString string) (userID string, scopes []string, err error)

ValidateAccessToken validates a JWT access token and returns the claims

func (*APIAuth) ValidateAccessTokenFull

func (a *APIAuth) ValidateAccessTokenFull(tokenString string) (userID string, scopes []string, customClaims map[string]any, err error)

ValidateAccessTokenFull validates a JWT access token and returns the standard claims plus any custom claims (non-standard keys) as a separate map.

func (*APIAuth) VerifyTokenFunc

func (a *APIAuth) VerifyTokenFunc() func(tokenString string) (userID string, token any, err error)

VerifyTokenFunc returns a function that can be used as Middleware.VerifyToken. This allows the Middleware to validate Bearer tokens using the APIAuth's JWT configuration.

type APIMiddleware

type APIMiddleware struct {
	// JWT validation (uses same config as APIAuth)
	JWTSecretKey  string
	JWTIssuer     string
	JWTAudience   string
	JWTSigningAlg string

	// KeyStore for multi-tenant JWT validation. When set, the middleware uses
	// GetKeyByKid (for tokens with kid header) or GetKey (for client_id claim).
	// When nil, falls back to JWTSecretKey (single-tenant, backwards-compatible).
	KeyStore keys.KeyLookup

	// API key validation (optional)
	APIKeyStore core.APIKeyStore

	// Token header configuration
	AuthHeader string // Defaults to "Authorization"

	// TokenQueryParam is the query parameter name to check for a token as fallback
	// when the Authorization header is missing (e.g., "token" for ?token=...).
	// Empty string disables query param extraction (default).
	TokenQueryParam string

	// Error handling
	OnAuthError func(w http.ResponseWriter, r *http.Request, err error)

	// Blacklist enables immediate access token revocation. When set,
	// validateJWT checks the blacklist after signature verification.
	// If nil, no revocation check (stateless validation only).
	Blacklist core.TokenBlacklist

	// Introspection enables token validation via a remote introspection
	// endpoint (RFC 7662) as an alternative to local JWT/JWKS validation.
	// When set, tokens that fail local validation are sent to the
	// introspection endpoint. When local validation is not configured
	// (no JWTSecretKey, no KeyStore), introspection is the only validation path.
	// If nil, only local validation is used.
	Introspection *IntrospectionValidator
}

APIMiddleware provides middleware for validating API tokens

func (*APIMiddleware) Optional

func (m *APIMiddleware) Optional(next http.Handler) http.Handler

Optional middleware allows requests without auth but sets user info if present

func (*APIMiddleware) RequireScopes

func (m *APIMiddleware) RequireScopes(requiredScopes ...string) func(http.Handler) http.Handler

RequireScopes middleware ensures the authenticated user has all required scopes

func (*APIMiddleware) ValidateToken

func (m *APIMiddleware) ValidateToken(next http.Handler) http.Handler

ValidateToken middleware validates Bearer tokens (JWT or API key) and sets user info in context

type ASServerMetadata added in v0.0.56

type ASServerMetadata struct {
	// Required
	Issuer        string `json:"issuer"`
	TokenEndpoint string `json:"token_endpoint"`

	// Recommended
	JWKSURI string `json:"jwks_uri,omitempty"`

	// Optional endpoints
	AuthorizationEndpoint string `json:"authorization_endpoint,omitempty"`
	IntrospectionEndpoint string `json:"introspection_endpoint,omitempty"`
	RevocationEndpoint    string `json:"revocation_endpoint,omitempty"`
	RegistrationEndpoint  string `json:"registration_endpoint,omitempty"`
	UserinfoEndpoint      string `json:"userinfo_endpoint,omitempty"`

	// Supported features
	ScopesSupported               []string `json:"scopes_supported,omitempty"`
	ResponseTypesSupported        []string `json:"response_types_supported,omitempty"`
	GrantTypesSupported           []string `json:"grant_types_supported,omitempty"`
	TokenEndpointAuthMethods      []string `json:"token_endpoint_auth_methods_supported,omitempty"`
	CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported,omitempty"`
	SubjectTypesSupported         []string `json:"subject_types_supported,omitempty"`

	// CacheMaxAge controls the Cache-Control max-age in seconds.
	// Defaults to 3600 (1 hour). Not serialized to JSON.
	CacheMaxAge int `json:"-"`
}

ASServerMetadata describes an OAuth 2.0 Authorization Server per RFC 8414 and OpenID Connect Discovery 1.0 §4. The auth server serves this at GET /.well-known/openid-configuration so OIDC-aware clients can auto-discover endpoints.

This is metadata-only — serving this does NOT make the server a full OIDC provider. It simply advertises what endpoints exist (token, JWKS, introspection, etc.) so standard client libraries can discover them.

See: https://www.rfc-editor.org/rfc/rfc8414#section-2

type IntrospectionHandler added in v0.0.56

type IntrospectionHandler struct {
	// Auth is the APIAuth instance used to validate tokens.
	// Must have JWTSecretKey (or JWTVerifyKey) configured.
	Auth *APIAuth

	// ClientKeyStore authenticates callers of the introspection endpoint.
	// Resource servers must present valid client_id + client_secret via
	// HTTP Basic auth. If nil, all callers are rejected.
	ClientKeyStore keys.KeyLookup
}

IntrospectionHandler implements OAuth 2.0 Token Introspection (RFC 7662). Resource servers POST tokens to this endpoint to check validity, as an alternative to local JWT validation via JWKS.

The handler:

  • Accepts POST with application/x-www-form-urlencoded body (token=...)
  • Authenticates the caller via ClientKeyStore (Basic auth)
  • Validates the token using APIAuth.ValidateAccessTokenFull
  • Checks the token blacklist if configured on APIAuth
  • Returns {"active": true, ...claims} for valid tokens
  • Returns {"active": false} for ANY invalid token (never reveals why)

See: https://www.rfc-editor.org/rfc/rfc7662

func (*IntrospectionHandler) ServeHTTP added in v0.0.56

func (h *IntrospectionHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP handles POST /oauth/introspect per RFC 7662.

type IntrospectionResult added in v0.0.62

type IntrospectionResult struct {
	Active    bool   `json:"active"`
	Sub       string `json:"sub,omitempty"`
	Scope     string `json:"scope,omitempty"`
	ClientID  string `json:"client_id,omitempty"`
	TokenType string `json:"token_type,omitempty"`
	Exp       int64  `json:"exp,omitempty"`
	Iat       int64  `json:"iat,omitempty"`
	Iss       string `json:"iss,omitempty"`
	Jti       string `json:"jti,omitempty"`
	Aud       any    `json:"aud,omitempty"`
}

IntrospectionResult holds the parsed introspection response.

type IntrospectionValidator added in v0.0.62

type IntrospectionValidator struct {
	// IntrospectionURL is the auth server's introspection endpoint.
	// Required.
	IntrospectionURL string

	// ClientID and ClientSecret authenticate this resource server to the
	// introspection endpoint via HTTP Basic auth (client_secret_basic).
	// Required.
	ClientID     string
	ClientSecret string

	// HTTPClient is used for introspection requests. If nil, uses
	// http.DefaultClient.
	HTTPClient *http.Client

	// CacheTTL enables response caching. If > 0, introspection responses
	// are cached for this duration. A revoked token may remain "active"
	// in the cache for up to CacheTTL after revocation.
	// Default: 0 (no caching).
	CacheTTL time.Duration
	// contains filtered or unexported fields
}

IntrospectionValidator validates tokens by calling a remote introspection endpoint (RFC 7662), as an alternative to local JWT validation via JWKS.

Use this when:

  • The resource server can't access the KeyStore or JWKS endpoint
  • Centralized blacklist checking is needed
  • Opaque (non-JWT) tokens need validation

The validator authenticates to the introspection endpoint using client credentials (client_secret_basic).

Optional response caching reduces load on the auth server. Cache entries expire after CacheTTL (default: no cache).

See: https://www.rfc-editor.org/rfc/rfc7662

func (*IntrospectionValidator) Validate added in v0.0.62

func (v *IntrospectionValidator) Validate(token string) (*IntrospectionResult, error)

Validate calls the introspection endpoint to check if a token is active. Returns the introspection result with parsed claims, or an error if the introspection request itself failed (network error, auth failure, etc.).

An inactive token is NOT an error — it returns IntrospectionResult{Active: false}. Only transport/auth failures return errors.

func (*IntrospectionValidator) ValidateForMiddleware added in v0.0.62

func (v *IntrospectionValidator) ValidateForMiddleware(token string) (userID string, scopes []string, authType string, customClaims map[string]any, err error)

ValidateForMiddleware validates a token and returns the fields that APIMiddleware.validateRequest needs: userID, scopes, authType, customClaims. Returns an error if the token is inactive or introspection fails.

type ProtectedResourceMetadata added in v0.0.55

type ProtectedResourceMetadata struct {
	// Resource is the resource server's identifier (its base URL).
	// REQUIRED per RFC 9728 §3.
	Resource string `json:"resource"`

	// AuthorizationServers lists the authorization servers that the resource
	// server trusts to issue tokens. REQUIRED per RFC 9728 §3.
	AuthorizationServers []string `json:"authorization_servers"`

	// ScopesSupported lists the OAuth 2.0 scopes that this resource server
	// understands. Optional.
	ScopesSupported []string `json:"scopes_supported,omitempty"`

	// TokenFormatsSupported lists the token formats accepted (e.g., "jwt").
	// Optional.
	TokenFormatsSupported []string `json:"token_formats_supported,omitempty"`

	// SigningAlgsSupported lists the JWS signing algorithms the resource server
	// supports for validating tokens (e.g., "RS256", "ES256", "HS256").
	// Optional.
	SigningAlgsSupported []string `json:"resource_signing_alg_values_supported,omitempty"`

	// DocumentationURI points to human-readable documentation for the resource
	// server's API. Optional.
	DocumentationURI string `json:"resource_documentation,omitempty"`

	// IntrospectionEndpoint is the URL of the token introspection endpoint
	// (RFC 7662) that can be used to validate tokens for this resource.
	// Optional — included when the resource server supports introspection.
	IntrospectionEndpoint string `json:"introspection_endpoint,omitempty"`

	// CacheMaxAge controls the Cache-Control max-age header in seconds.
	// Defaults to 3600 (1 hour) if zero. Not serialized to JSON.
	CacheMaxAge int `json:"-"`
}

ProtectedResourceMetadata describes an OAuth 2.0 Protected Resource per RFC 9728. Resource servers serve this at GET /.well-known/oauth-protected-resource so clients can auto-discover which authorization servers are trusted, what scopes are supported, what token formats are accepted, and which signing algorithms are used.

Required fields: Resource and AuthorizationServers. All other fields are optional and omitted from JSON when empty.

See: https://www.rfc-editor.org/rfc/rfc9728

Jump to

Keyboard shortcuts

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