Documentation
¶
Index ¶
- func AccessRequestFromContext(ctx context.Context) fosite.AccessRequester
- func HasScope(ctx context.Context, scope string) bool
- func LoggerFromContext(ctx context.Context) *slog.Logger
- func ScopesFromContext(ctx context.Context) []string
- func UserIDFromContext(ctx context.Context) string
- func WithAccessRequest(ctx context.Context, ar fosite.AccessRequester) context.Context
- type API
- type AuthorizeInput
- type AuthorizeOutput
- type Client
- func (c *Client) GetAudience() fosite.Arguments
- func (c *Client) GetGrantTypes() fosite.Arguments
- func (c *Client) GetHashedSecret() []byte
- func (c *Client) GetID() string
- func (c *Client) GetRedirectURIs() []string
- func (c *Client) GetResponseTypes() fosite.Arguments
- func (c *Client) GetScopes() fosite.Arguments
- func (c *Client) IsPublic() bool
- type Config
- type ConsentFunc
- type IntrospectInput
- type IntrospectOutput
- type IntrospectResponse
- type JWK
- type JWKS
- type JWKSOutput
- type OAuthError
- type OpenIDConfigOutput
- type OpenIDConfiguration
- type Option
- type Provider
- type RevokeInput
- type RevokeOutput
- type Storage
- func (s *Storage) ClientAssertionJWTValid(ctx context.Context, jti string) error
- func (s *Storage) CreateAccessTokenSession(ctx context.Context, signature string, request fosite.Requester) error
- func (s *Storage) CreateAuthorizeCodeSession(ctx context.Context, code string, request fosite.Requester) error
- func (s *Storage) CreatePKCERequestSession(ctx context.Context, signature string, request fosite.Requester) error
- func (s *Storage) CreateRefreshTokenSession(ctx context.Context, signature string, accessSignature string, ...) error
- func (s *Storage) DeleteAccessTokenSession(ctx context.Context, signature string) error
- func (s *Storage) DeletePKCERequestSession(ctx context.Context, signature string) error
- func (s *Storage) DeleteRefreshTokenSession(ctx context.Context, signature string) error
- func (s *Storage) GetAccessTokenSession(ctx context.Context, signature string, session fosite.Session) (fosite.Requester, error)
- func (s *Storage) GetAuthorizeCodeSession(ctx context.Context, code string, session fosite.Session) (fosite.Requester, error)
- func (s *Storage) GetClient(ctx context.Context, clientID string) (fosite.Client, error)
- func (s *Storage) GetPKCERequestSession(ctx context.Context, signature string, session fosite.Session) (fosite.Requester, error)
- func (s *Storage) GetRefreshTokenSession(ctx context.Context, signature string, session fosite.Session) (fosite.Requester, error)
- func (s *Storage) InvalidateAuthorizeCodeSession(ctx context.Context, code string) error
- func (s *Storage) RevokeAccessToken(ctx context.Context, requestID string) error
- func (s *Storage) RevokeRefreshToken(ctx context.Context, requestID string) error
- func (s *Storage) RotateRefreshToken(ctx context.Context, requestID string, refreshTokenSignature string) error
- func (s *Storage) SetClientAssertionJWT(ctx context.Context, jti string, exp time.Time) error
- type TokenInput
- type TokenOutput
- type TokenResponse
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AccessRequestFromContext ¶
func AccessRequestFromContext(ctx context.Context) fosite.AccessRequester
AccessRequestFromContext extracts the access request from context.
func LoggerFromContext ¶
LoggerFromContext returns the logger from context, or slog.Default() if not set.
func ScopesFromContext ¶
ScopesFromContext extracts the granted scopes from the access request in context.
func UserIDFromContext ¶
UserIDFromContext extracts the user ID (subject) from the access request in context.
func WithAccessRequest ¶
WithAccessRequest adds the access request to the context.
Types ¶
type API ¶
type API struct {
// contains filtered or unexported fields
}
API provides HTTP handlers for OAuth 2.0 endpoints using Huma/Chi. It uses a hybrid approach: discovery endpoints use Huma for full typed handling, while Fosite-integrated endpoints use Chi handlers directly.
func (*API) Middleware ¶
Middleware provides OAuth token validation middleware.
type AuthorizeInput ¶
type AuthorizeInput struct {
ResponseType string `query:"response_type" required:"true" enum:"code,token" doc:"OAuth 2.0 response type"`
ClientID string `query:"client_id" required:"true" doc:"Client identifier"`
RedirectURI string `query:"redirect_uri" doc:"URI to redirect after authorization"`
Scope string `query:"scope" doc:"Space-separated list of requested scopes"`
State string `query:"state" doc:"Opaque value for CSRF protection"`
CodeChallenge string `query:"code_challenge" doc:"PKCE code challenge"`
CodeChallengeMethod string `query:"code_challenge_method" enum:"S256,plain" doc:"PKCE code challenge method"`
Nonce string `query:"nonce" doc:"OpenID Connect nonce for replay protection"`
}
AuthorizeInput represents the OAuth 2.0 authorization request parameters.
type AuthorizeOutput ¶
type AuthorizeOutput struct {
Location string `header:"Location" doc:"Redirect URI with authorization code or token"`
}
AuthorizeOutput represents the authorization response (redirect).
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client implements fosite.Client backed by Ent OAuthApp.
func (*Client) GetAudience ¶
GetAudience returns the audience for this client.
func (*Client) GetGrantTypes ¶
GetGrantTypes returns the allowed grant types.
func (*Client) GetHashedSecret ¶
GetHashedSecret returns nothing - we use custom validation.
func (*Client) GetRedirectURIs ¶
GetRedirectURIs returns the registered redirect URIs.
func (*Client) GetResponseTypes ¶
GetResponseTypes returns the allowed response types.
type Config ¶
type Config struct {
// Issuer is the OAuth/OIDC issuer URL
Issuer string
// AccessTokenLifespan is the duration access tokens are valid
AccessTokenLifespan time.Duration
// RefreshTokenLifespan is the duration refresh tokens are valid
RefreshTokenLifespan time.Duration
// AuthCodeLifespan is the duration authorization codes are valid
AuthCodeLifespan time.Duration
// PrivateKey is the RSA private key for signing tokens
// If nil, a key will be generated
PrivateKey *rsa.PrivateKey
// HashSecret is the secret used for HMAC operations
HashSecret []byte
}
Config holds OAuth 2.0 server configuration.
func DefaultConfig ¶
DefaultConfig returns a default OAuth configuration.
type ConsentFunc ¶ added in v0.14.0
type ConsentFunc func(ctx context.Context, userID string, client fosite.Client, scopes []string) (bool, error)
ConsentFunc reports whether userID has consented to client receiving scopes. It is consulted for clients that are not first-party.
type IntrospectInput ¶
type IntrospectInput struct {
Token string `form:"token" required:"true" doc:"The token to introspect"`
TokenTypeHint string `form:"token_type_hint" enum:"access_token,refresh_token" doc:"Hint about the token type"`
// Client authentication
Authorization string `header:"Authorization" doc:"Basic authentication header (client_id:client_secret)"`
}
IntrospectInput represents the token introspection request.
type IntrospectOutput ¶
type IntrospectOutput struct {
Body IntrospectResponse
}
IntrospectOutput wraps the introspection response.
type IntrospectResponse ¶
type IntrospectResponse struct {
Active bool `json:"active" doc:"Whether the token is active"`
Scope string `json:"scope,omitempty" doc:"Scopes associated with the token"`
ClientID string `json:"client_id,omitempty" doc:"Client that requested the token"`
Username string `json:"username,omitempty" doc:"Resource owner username"`
TokenType string `json:"token_type,omitempty" doc:"Token type"`
Exp int64 `json:"exp,omitempty" doc:"Token expiration timestamp"`
Iat int64 `json:"iat,omitempty" doc:"Token issue timestamp"`
Nbf int64 `json:"nbf,omitempty" doc:"Token not-before timestamp"`
Sub string `json:"sub,omitempty" doc:"Subject (user ID)"`
Aud string `json:"aud,omitempty" doc:"Intended audience"`
Iss string `json:"iss,omitempty" doc:"Token issuer"`
Jti string `json:"jti,omitempty" doc:"JWT ID"`
}
IntrospectResponse represents the token introspection response.
type JWK ¶
type JWK struct {
Kty string `json:"kty" doc:"Key type (e.g., RSA, EC)"`
Use string `json:"use,omitempty" doc:"Key use (sig for signature, enc for encryption)"`
Kid string `json:"kid,omitempty" doc:"Key ID"`
Alg string `json:"alg,omitempty" doc:"Algorithm"`
N string `json:"n,omitempty" doc:"RSA modulus"`
E string `json:"e,omitempty" doc:"RSA exponent"`
}
JWK represents a JSON Web Key.
type JWKS ¶
type JWKS struct {
Keys []JWK `json:"keys" doc:"Array of JSON Web Keys"`
}
JWKS represents a JSON Web Key Set.
type JWKSOutput ¶
type JWKSOutput struct {
Body JWKS
}
JWKSOutput is the response for the JWKS endpoint.
type OAuthError ¶
type OAuthError struct {
Error string `json:"error" doc:"Error code"`
ErrorDescription string `json:"error_description,omitempty" doc:"Human-readable error description"`
ErrorURI string `json:"error_uri,omitempty" doc:"URI with more information about the error"`
}
OAuthError represents an OAuth 2.0 error response.
type OpenIDConfigOutput ¶
type OpenIDConfigOutput struct {
Body OpenIDConfiguration
}
OpenIDConfigOutput is the response for the OpenID Configuration endpoint.
type OpenIDConfiguration ¶
type OpenIDConfiguration struct {
Issuer string `json:"issuer" doc:"OAuth 2.0 Issuer Identifier"`
AuthorizationEndpoint string `json:"authorization_endpoint" doc:"URL of the authorization endpoint"`
TokenEndpoint string `json:"token_endpoint" doc:"URL of the token endpoint"`
IntrospectionEndpoint string `json:"introspection_endpoint" doc:"URL of the introspection endpoint"`
RevocationEndpoint string `json:"revocation_endpoint" doc:"URL of the revocation endpoint"`
JWKSURI string `json:"jwks_uri" doc:"URL of the JSON Web Key Set document"`
ResponseTypesSupported []string `json:"response_types_supported" doc:"List of supported response types"`
GrantTypesSupported []string `json:"grant_types_supported" doc:"List of supported grant types"`
TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported" doc:"List of supported token endpoint authentication methods"`
CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported" doc:"List of supported PKCE code challenge methods"`
}
OpenIDConfiguration represents the OpenID Connect discovery document.
type Option ¶
type Option func(*API)
Option configures an API.
func WithConsent ¶ added in v0.14.0
func WithConsent(consent ConsentFunc) Option
WithConsent sets how consent is checked for clients that are not first-party. Without it such clients are refused with access_denied; first-party clients never need consent.
func WithLogger ¶
WithLogger sets the logger for the API. If not set, slog.Default() is used.
func WithLoginURL ¶ added in v0.14.0
WithLoginURL sets where unauthenticated users are sent; the original authorization request is passed back in the redirect query parameter. Without it, an unauthenticated authorization request is answered with login_required.
func WithTrustedUserIDHeader ¶ added in v0.14.0
func WithTrustedUserIDHeader(header string, gate systemauth.RequestGate) Option
WithTrustedUserIDHeader authenticates users from a header written by a gateway that has already authenticated them (a backend-for-frontend). Only requests the gate admits are believed; see systemauth.TrustedProxyNetworks and systemauth.TrustAllRequests. A nil gate or an empty header trusts nothing.
func WithUserAuthenticator ¶ added in v0.14.0
WithUserAuthenticator sets how the authorization endpoint learns who the user is: it returns the authenticated user's ID for the request, or "" when there is none, for example by validating a session cookie. Until one is set, the authorization endpoint refuses every request with server_error rather than guess.
type Provider ¶
type Provider struct {
// contains filtered or unexported fields
}
Provider wraps Fosite and provides OAuth 2.0/OIDC functionality.
func NewProvider ¶
NewProvider creates a new OAuth provider.
func (*Provider) OAuth2Provider ¶
func (p *Provider) OAuth2Provider() fosite.OAuth2Provider
OAuth2Provider returns the underlying Fosite provider.
type RevokeInput ¶
type RevokeInput struct {
Token string `form:"token" required:"true" doc:"The token to revoke"`
TokenTypeHint string `form:"token_type_hint" enum:"access_token,refresh_token" doc:"Hint about the token type"`
// Client authentication
Authorization string `header:"Authorization" doc:"Basic authentication header (client_id:client_secret)"`
}
RevokeInput represents the token revocation request.
type RevokeOutput ¶
type RevokeOutput struct{}
RevokeOutput represents the token revocation response (empty on success).
type Storage ¶
type Storage struct {
// contains filtered or unexported fields
}
Storage implements the Fosite storage interfaces using Ent.
Clients are this package's Client. Authorization codes, tokens, PKCE, and revocation are delegated to SystemAuth's storage over the same tables, which stores each grant's full request and session, so a code exchange keeps the subject, the PKCE challenge, and the redirect URI it was issued with, and refresh-token reuse revokes the token family.
func NewStorage ¶
NewStorage creates a new Fosite storage backed by Ent.
func (*Storage) ClientAssertionJWTValid ¶ added in v0.14.0
ClientAssertionJWTValid reports fosite.ErrJTIKnown for a client-assertion JWT ID that is already used.
func (*Storage) CreateAccessTokenSession ¶
func (s *Storage) CreateAccessTokenSession(ctx context.Context, signature string, request fosite.Requester) error
CreateAccessTokenSession stores an access token with its request.
func (*Storage) CreateAuthorizeCodeSession ¶
func (s *Storage) CreateAuthorizeCodeSession(ctx context.Context, code string, request fosite.Requester) error
CreateAuthorizeCodeSession stores an authorization code with its request.
func (*Storage) CreatePKCERequestSession ¶
func (s *Storage) CreatePKCERequestSession(ctx context.Context, signature string, request fosite.Requester) error
CreatePKCERequestSession records a code's PKCE challenge.
func (*Storage) CreateRefreshTokenSession ¶
func (s *Storage) CreateRefreshTokenSession(ctx context.Context, signature string, accessSignature string, request fosite.Requester) error
CreateRefreshTokenSession stores a refresh token, on the paired access token's row when there is one.
func (*Storage) DeleteAccessTokenSession ¶
DeleteAccessTokenSession removes an access token session.
func (*Storage) DeletePKCERequestSession ¶
DeletePKCERequestSession is a no-op: the challenge lives on the authorization code, which the code exchange invalidates.
func (*Storage) DeleteRefreshTokenSession ¶
DeleteRefreshTokenSession revokes a refresh token.
func (*Storage) GetAccessTokenSession ¶
func (s *Storage) GetAccessTokenSession(ctx context.Context, signature string, session fosite.Session) (fosite.Requester, error)
GetAccessTokenSession restores the request an access token was issued for.
func (*Storage) GetAuthorizeCodeSession ¶
func (s *Storage) GetAuthorizeCodeSession(ctx context.Context, code string, session fosite.Session) (fosite.Requester, error)
GetAuthorizeCodeSession restores the request an authorization code was issued for. A code already exchanged returns the request with fosite.ErrInvalidatedAuthorizeCode, so Fosite revokes its tokens.
func (*Storage) GetPKCERequestSession ¶
func (s *Storage) GetPKCERequestSession(ctx context.Context, signature string, session fosite.Session) (fosite.Requester, error)
GetPKCERequestSession restores a code's request with its PKCE challenge.
func (*Storage) GetRefreshTokenSession ¶
func (s *Storage) GetRefreshTokenSession(ctx context.Context, signature string, session fosite.Session) (fosite.Requester, error)
GetRefreshTokenSession restores the request a refresh token was issued for. A rotated refresh token returns the request with fosite.ErrInactiveToken, so Fosite revokes the whole token family.
func (*Storage) InvalidateAuthorizeCodeSession ¶
InvalidateAuthorizeCodeSession marks an authorization code as used.
func (*Storage) RevokeAccessToken ¶
RevokeAccessToken revokes every token of the family identified by the Fosite request ID.
func (*Storage) RevokeRefreshToken ¶
RevokeRefreshToken revokes every token of the family identified by the Fosite request ID.
type TokenInput ¶
type TokenInput struct {
GrantType string `form:"grant_type" required:"true" enum:"authorization_code,refresh_token,client_credentials" doc:"OAuth 2.0 grant type"`
Code string `form:"code" doc:"Authorization code (for authorization_code grant)"`
RedirectURI string `form:"redirect_uri" doc:"Redirect URI (must match authorization request)"`
ClientID string `form:"client_id" doc:"Client identifier (if not using Basic auth)"`
ClientSecret string `form:"client_secret" doc:"Client secret (if not using Basic auth)"`
RefreshToken string `form:"refresh_token" doc:"Refresh token (for refresh_token grant)"`
Scope string `form:"scope" doc:"Requested scopes (for refresh_token or client_credentials)"`
CodeVerifier string `form:"code_verifier" doc:"PKCE code verifier"`
// Basic auth credentials (alternative to form-based client auth)
Authorization string `header:"Authorization" doc:"Basic authentication header (client_id:client_secret)"`
}
TokenInput represents the OAuth 2.0 token request parameters. Field names follow OAuth 2.0 specification (RFC 6749).
type TokenOutput ¶
type TokenOutput struct {
Body TokenResponse
}
TokenOutput wraps the token response.
type TokenResponse ¶
type TokenResponse struct {
AccessToken string `json:"access_token" doc:"The access token"`
TokenType string `json:"token_type" doc:"Token type (typically 'Bearer')"`
ExpiresIn int `json:"expires_in,omitempty" doc:"Token lifetime in seconds"`
RefreshToken string `json:"refresh_token,omitempty" doc:"Refresh token for obtaining new access tokens"`
Scope string `json:"scope,omitempty" doc:"Granted scopes (may differ from requested)"`
IDToken string `json:"id_token,omitempty" doc:"OpenID Connect ID token"`
}
TokenResponse represents the OAuth 2.0 token response. Field names follow OAuth 2.0 specification (RFC 6749).