Documentation
¶
Index ¶
- func GetAuthTypeFromAPIContext(ctx context.Context) string
- func GetAuthorizationDetailsFromContext(ctx context.Context) []core.AuthorizationDetail
- func GetCustomClaimsFromContext(ctx context.Context) map[string]any
- func GetScopesFromAPIContext(ctx context.Context) []string
- func GetUserIDFromAPIContext(ctx context.Context) string
- func MountProtectedResource(mux *http.ServeMux, meta *ProtectedResourceMetadata, proxyASMetadata bool, ...)
- func NewASMetadataHandler(meta *ASServerMetadata) http.Handler
- func NewProtectedResourceHandler(meta *ProtectedResourceMetadata) http.Handler
- type APIAuth
- func (a *APIAuth) CreateAccessToken(userID string, scopes []string, authzDetails []core.AuthorizationDetail) (string, int64, error)
- func (a *APIAuth) HandleAPIKeys(w http.ResponseWriter, r *http.Request)
- func (a *APIAuth) HandleListSessions(w http.ResponseWriter, r *http.Request)
- func (a *APIAuth) HandleLogout(w http.ResponseWriter, r *http.Request)
- func (a *APIAuth) HandleLogoutAll(w http.ResponseWriter, r *http.Request)
- func (a *APIAuth) HandleRevokeAPIKey(w http.ResponseWriter, r *http.Request)
- func (a *APIAuth) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (a *APIAuth) ValidateAccessToken(tokenString string) (userID string, scopes []string, err error)
- func (a *APIAuth) ValidateAccessTokenFull(tokenString string) (userID string, scopes []string, customClaims map[string]any, err error)
- func (a *APIAuth) VerifyTokenFunc() func(tokenString string) (userID string, token any, err error)
- type APIMiddleware
- func (m *APIMiddleware) Optional(next http.Handler) http.Handler
- func (m *APIMiddleware) RequireAuthorizationDetails(requiredTypes ...string) func(http.Handler) http.Handler
- func (m *APIMiddleware) RequireScopes(requiredScopes ...string) func(http.Handler) http.Handler
- func (m *APIMiddleware) ValidateToken(next http.Handler) http.Handler
- type ASMetadataProxy
- type ASServerMetadata
- type AuthHooks
- type ClientAuthenticator
- type ClientHooks
- type Hooks
- type IntrospectionHandler
- type IntrospectionResult
- type IntrospectionValidator
- type JWTIssuerConfig
- type JWTValidatorConfig
- type OneAuth
- type OneAuthConfig
- type ProtectedResourceMetadata
- type RevocationHandler
- type SecurityHooks
- type TokenHooks
- type TokenInfo
- type TokenIntrospector
- type TokenIssuer
- type TokenRevoker
- type TokenRevokerConfig
- type TokenValidator
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GetAuthTypeFromAPIContext ¶
GetAuthTypeFromAPIContext retrieves the auth type ("jwt" or "api_key") from context
func GetAuthorizationDetailsFromContext ¶ added in v0.0.76
func GetAuthorizationDetailsFromContext(ctx context.Context) []core.AuthorizationDetail
GetAuthorizationDetailsFromContext retrieves the RFC 9396 authorization_details from context. Returns nil if no authorization details are present (e.g., API key auth or token without RAR).
func GetCustomClaimsFromContext ¶
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 ¶
GetScopesFromAPIContext retrieves the granted scopes from the API middleware context
func GetUserIDFromAPIContext ¶
GetUserIDFromAPIContext retrieves the user ID from the API middleware context
func MountProtectedResource ¶ added in v0.0.75
func MountProtectedResource(mux *http.ServeMux, meta *ProtectedResourceMetadata, proxyASMetadata bool, pathPrefix ...string)
MountProtectedResource mounts the PRM endpoint on the given mux and optionally proxies AS metadata at the RFC 8414 well-known path. This ensures that clients which only try RFC 8414 discovery (and don't fall back to OIDC discovery) can find the AS metadata via the resource server.
Spec references:
- RFC 9728 §3: PRM at /.well-known/oauth-protected-resource https://www.rfc-editor.org/rfc/rfc9728#section-3
- RFC 8414 §3: AS metadata at /.well-known/oauth-authorization-server https://www.rfc-editor.org/rfc/rfc8414#section-3
- MCP Auth (2025-11-25): clients discover AS via PRM → RFC 8414 https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization
When proxyASMetadata is true, for each URL in AuthorizationServers:
- Fetches the AS's OIDC discovery document (with RFC 8414 fallback)
- Caches and serves it at /.well-known/oauth-authorization-server on the resource server
- Also serves path-based RFC 8414 (e.g., /.well-known/oauth-authorization-server/realms/foo)
This bridges OIDC-only providers (Keycloak, Auth0) that don't natively serve RFC 8414 metadata.
Usage:
MountProtectedResource(mux, meta, true) // PRM at: /.well-known/oauth-protected-resource // AS metadata at: /.well-known/oauth-authorization-server (proxied)
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, authzDetails []core.AuthorizationDetail) (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). authzDetails is an optional RFC 9396 authorization_details array embedded in the JWT.
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.
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 ¶
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) RequireAuthorizationDetails ¶ added in v0.0.76
func (m *APIMiddleware) RequireAuthorizationDetails(requiredTypes ...string) func(http.Handler) http.Handler
RequireAuthorizationDetails middleware ensures the token contains authorization_details matching all required types. For each required type, there must be at least one authorization_details entry with that type.
func (*APIMiddleware) RequireScopes ¶
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 ASMetadataProxy ¶ added in v0.0.75
type ASMetadataProxy struct {
// contains filtered or unexported fields
}
ASMetadataProxy fetches AS metadata from an authorization server's OIDC discovery endpoint and serves it at the RFC 8414 well-known path. This bridges the gap for OIDC-only providers (like Keycloak) that don't serve RFC 8414 metadata natively.
Background:
- RFC 8414 §3 defines AS metadata at /.well-known/oauth-authorization-server https://www.rfc-editor.org/rfc/rfc8414#section-3
- OIDC Discovery §4 defines it at /.well-known/openid-configuration https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig
- RFC 9728 §3 (PRM) lists authorization_servers — clients then need to discover the AS's endpoints via RFC 8414 or OIDC https://www.rfc-editor.org/rfc/rfc9728#section-3
- MCP Auth spec (2025-11-25) requires clients to discover AS via RFC 8414 with OIDC fallback. Some clients (VS Code) only try RFC 8414. https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization
The proxy:
- Fetches lazily on first request (not at construction time)
- Caches the response with a configurable TTL (default 1 hour)
- Tries RFC 8414 first, then OIDC discovery (same fallback as client.DiscoverAS)
- Serves GET only (405 for other methods)
func NewASMetadataProxy ¶ added in v0.0.75
func NewASMetadataProxy(issuerURL string, cacheTTL time.Duration) *ASMetadataProxy
NewASMetadataProxy creates a proxy that fetches AS metadata from the given issuer URL. The proxy tries both RFC 8414 and OIDC discovery paths.
func (*ASMetadataProxy) ServeHTTP ¶ added in v0.0.75
func (p *ASMetadataProxy) ServeHTTP(w http.ResponseWriter, r *http.Request)
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
AuthorizationDetailsTypesSupported []string `json:"authorization_details_types_supported,omitempty"` // RFC 9396
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.
type AuthHooks ¶ added in v0.0.77
type AuthHooks struct {
// OnLoginSuccess fires after a user successfully authenticates
// (password grant, auth code exchange).
OnLoginSuccess func(userID string)
// OnLoginFailure fires after a failed authentication attempt.
OnLoginFailure func(username string, err error)
// OnScopeStepUp fires when additional scopes are requested and granted.
// from is the original scope set, to is the expanded set.
OnScopeStepUp func(subject string, from, to []string)
}
AuthHooks fires on authentication events.
type ClientAuthenticator ¶ added in v0.0.77
type ClientAuthenticator interface {
// AuthenticateClient verifies the client_id and client_secret.
AuthenticateClient(clientID, clientSecret string) error
}
ClientAuthenticator verifies client credentials. Used by transport bindings to authenticate callers of protected endpoints (introspection, revocation, DCR).
func NewClientAuthenticator ¶ added in v0.0.77
func NewClientAuthenticator(kl keys.KeyLookup) ClientAuthenticator
NewClientAuthenticator creates a ClientAuthenticator backed by a KeyLookup.
type ClientHooks ¶ added in v0.0.77
type ClientHooks struct {
// OnRegistered fires after a new client is registered (DCR or proprietary).
// method is "dcr" or "register".
OnRegistered func(clientID, method string)
// OnDeleted fires after a client is deleted.
OnDeleted func(clientID string)
// OnKeyRotated fires after a client's signing key is rotated.
OnKeyRotated func(clientID string)
}
ClientHooks fires on client management events.
type Hooks ¶ added in v0.0.77
type Hooks struct {
Token TokenHooks
Auth AuthHooks
Client ClientHooks
Security SecurityHooks
}
Hooks provides lifecycle callbacks for OneAuth operations. Grouped by concern — each implementation receives only its relevant group. All callbacks are optional — nil callbacks are no-ops.
Configure all hooks in one place on OneAuth.Hooks. Callers set only what they need:
oa := NewOneAuth(OneAuthConfig{
Hooks: Hooks{
Token: TokenHooks{
OnRevoked: func(token, hint string) { audit.Log("revoked", token) },
},
},
})
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 JWTIssuerConfig ¶ added in v0.0.77
type JWTIssuerConfig struct {
SigningKey any
SigningAlg string
Issuer string
Audience string
AccessExpiry time.Duration
ClientKeyLookup keys.KeyLookup // for client_credentials authentication
Hooks TokenHooks
}
JWTIssuerConfig configures a jwtIssuer.
type JWTValidatorConfig ¶ added in v0.0.77
type JWTValidatorConfig struct {
KeyLookup keys.KeyLookup
Blacklist core.TokenBlacklist
Issuer string
Audience string
Hooks SecurityHooks
}
JWTValidatorConfig configures a jwtValidator.
type OneAuth ¶ added in v0.0.77
type OneAuth struct {
// Core operation interfaces — each has minimal dependencies.
Issuer TokenIssuer
Validator TokenValidator
Introspector TokenIntrospector
Revoker TokenRevoker
Authenticator ClientAuthenticator
// Shared state — available for transport bindings that need direct access.
KeyStore keys.KeyStorage
Blacklist core.TokenBlacklist
RefreshStore core.RefreshTokenStore
// Hooks — lifecycle callbacks grouped by concern.
Hooks Hooks
}
OneAuth is the transport-independent core of the authentication system. It composes focused interfaces (Option A — no god object) and wires hooks for lifecycle callbacks.
Use NewOneAuth to create an instance with all dependencies wired. Transport bindings (HTTP handlers, gRPC interceptors, MCP auth) are thin wrappers over these interfaces.
Library usage (no HTTP):
oa := apiauth.NewOneAuth(apiauth.OneAuthConfig{...})
token, _, _ := oa.Issuer.CreateAccessToken("alice", []string{"read"}, nil)
info, _ := oa.Validator.ValidateToken(token)
result, _ := oa.Introspector.Introspect(token)
oa.Revoker.Revoke(token, "access_token")
See: https://github.com/panyam/oneauth/issues/110
func NewOneAuth ¶ added in v0.0.77
func NewOneAuth(cfg OneAuthConfig) *OneAuth
NewOneAuth creates a fully wired OneAuth instance. All implementations receive only the interfaces they need.
type OneAuthConfig ¶ added in v0.0.77
type OneAuthConfig struct {
// Key management
KeyStore keys.KeyStorage // required — stores client keys
// Signing configuration
SigningKey any // []byte for HS256, *rsa.PrivateKey for RS256, etc.
SigningAlg string // "HS256", "RS256", "ES256" — default "HS256"
// JWT configuration
Issuer string // JWT iss claim
Audience string // JWT aud claim (optional)
AccessExpiry time.Duration // default 15 minutes
// Token lifecycle
Blacklist core.TokenBlacklist // for access token revocation (optional)
RefreshStore core.RefreshTokenStore // for refresh token management (optional)
// Hooks — lifecycle callbacks
Hooks Hooks
}
OneAuthConfig holds the dependencies for creating a OneAuth instance.
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.
type RevocationHandler ¶ added in v0.0.77
type RevocationHandler struct {
// Auth is the APIAuth instance used to parse and validate access tokens.
Auth *APIAuth
// ClientKeyStore authenticates callers of the revocation endpoint.
// Clients must present valid client_id + client_secret via HTTP Basic auth
// or as form parameters (client_secret_post). If nil, all callers are rejected.
ClientKeyStore keys.KeyLookup
}
RevocationHandler implements OAuth 2.0 Token Revocation (RFC 7009). Clients POST a token to this endpoint to notify the AS that the token is no longer needed. The AS revokes it so that subsequent introspection or validation attempts fail.
The handler:
- Accepts POST with application/x-www-form-urlencoded body (token=...&token_type_hint=...)
- Authenticates the caller via ClientKeyStore (Basic auth or client_secret_post)
- Revokes access tokens via the Blacklist (jti-based)
- Revokes refresh tokens via the RefreshTokenStore
- Always returns 200 OK — never reveals whether the token existed (RFC 7009 §2.2)
See: https://www.rfc-editor.org/rfc/rfc7009
func (*RevocationHandler) ServeHTTP ¶ added in v0.0.77
func (h *RevocationHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP handles POST /oauth/revoke per RFC 7009.
type SecurityHooks ¶ added in v0.0.77
type SecurityHooks struct {
// OnTokenRejected fires when a token fails validation.
// reason describes why (expired, bad signature, revoked, etc.).
OnTokenRejected func(reason string)
// OnBlacklistHit fires when a revoked token is presented.
// This indicates token reuse after revocation — potential theft.
OnBlacklistHit func(jti string)
// OnAlgorithmMismatch fires when a token's alg header doesn't match
// the stored key's algorithm. This is the CVE-2015-9235 attack vector.
OnAlgorithmMismatch func(expected, got string)
}
SecurityHooks fires on security-relevant events. Use these for alerting, audit logging, and intrusion detection.
type TokenHooks ¶ added in v0.0.77
type TokenHooks struct {
// OnIssued fires after an access token is successfully created.
// subject is the token's sub claim, grantType is the OAuth grant used.
OnIssued func(subject, grantType string)
// OnRefreshed fires after a refresh token is rotated and a new access token issued.
OnRefreshed func(subject string)
// OnRevoked fires after a token is successfully revoked.
// hint is the token_type_hint ("access_token", "refresh_token", or "").
OnRevoked func(token, hint string)
}
TokenHooks fires on token lifecycle events.
type TokenInfo ¶ added in v0.0.77
type TokenInfo struct {
// UserID is the subject (sub claim) — a user ID or client_id.
UserID string
// Scopes are the granted scopes from the token.
Scopes []string
// AuthorizationDetails are the RFC 9396 authorization_details from the token.
// Nil if the token has no authorization_details.
AuthorizationDetails []core.AuthorizationDetail
// CustomClaims are non-standard JWT claims (everything not in standardClaims).
CustomClaims map[string]any
// AuthType is "jwt" or "api_key".
AuthType string
}
TokenInfo holds the validated claims extracted from a token. Returned by TokenValidator.ValidateToken.
type TokenIntrospector ¶ added in v0.0.77
type TokenIntrospector interface {
// Introspect checks a token's validity and returns its claims.
// Returns {Active: false} for any invalid token (never reveals why).
Introspect(token string) (*IntrospectionResult, error)
}
TokenIntrospector inspects tokens per RFC 7662.
func NewTokenIntrospector ¶ added in v0.0.77
func NewTokenIntrospector(v TokenValidator) TokenIntrospector
NewTokenIntrospector creates a TokenIntrospector backed by a TokenValidator.
type TokenIssuer ¶ added in v0.0.77
type TokenIssuer interface {
// CreateAccessToken mints a JWT with the given subject, scopes, and
// optional RFC 9396 authorization_details.
// Returns the signed token string and expiry in seconds.
CreateAccessToken(subject string, scopes []string, details []core.AuthorizationDetail) (token string, expiresIn int64, err error)
// ClientCredentials performs the full client_credentials grant:
// authenticates the client, validates scopes/details, and returns a token response.
ClientCredentials(clientID, clientSecret string, scopes []string, details []core.AuthorizationDetail) (*core.TokenPair, error)
}
TokenIssuer creates signed access tokens.
func NewJWTIssuer ¶ added in v0.0.77
func NewJWTIssuer(cfg JWTIssuerConfig) TokenIssuer
NewJWTIssuer creates a TokenIssuer that signs JWTs.
type TokenRevoker ¶ added in v0.0.77
type TokenRevoker interface {
// Revoke invalidates a token. The tokenTypeHint ("access_token" or
// "refresh_token") guides which store to check first. Empty hint
// tries both.
Revoke(token, tokenTypeHint string) error
}
TokenRevoker revokes tokens per RFC 7009.
func NewTokenRevoker ¶ added in v0.0.77
func NewTokenRevoker(cfg TokenRevokerConfig) TokenRevoker
NewTokenRevoker creates a TokenRevoker.
type TokenRevokerConfig ¶ added in v0.0.77
type TokenRevokerConfig struct {
Blacklist core.TokenBlacklist
RefreshStore core.RefreshTokenStore
Hooks TokenHooks
}
TokenRevokerConfig configures a tokenRevoker.
type TokenValidator ¶ added in v0.0.77
type TokenValidator interface {
// ValidateToken parses and validates a token string (JWT signature,
// expiry, issuer, audience, blacklist). Returns the token's claims.
ValidateToken(token string) (*TokenInfo, error)
// CheckScopes validates a token and verifies it contains all required scopes.
// Returns an error if the token is invalid or scopes are insufficient.
CheckScopes(token string, required []string) error
// CheckAuthorizationDetails validates a token and verifies it contains
// authorization_details entries for all required types (RFC 9396).
CheckAuthorizationDetails(token string, requiredTypes []string) error
}
TokenValidator validates tokens and checks authorization.
func NewJWTValidator ¶ added in v0.0.77
func NewJWTValidator(cfg JWTValidatorConfig) TokenValidator
NewJWTValidator creates a TokenValidator that validates JWTs locally.