fosite

repository·master·Indexed 25 days ago

https://github.com/ory/fosite

An OAuth2 and OpenID Connect provider implementation for Go. It provides core logic for handling OAuth2 flows, token management, security strategies, and RFC6749 compliant error responses.

Tokens
22.8K
Snippets
54
Records
143
Agent score
80%

What's inside fosite

  1. Implement a Token Endpoint handler

    master

    A Token Endpoint handler processes incoming OAuth2 token requests. Using a fosite.OAuth2Provider, you can manage the lifecycle of an access request and response.

    In the handler:

    1. Initialize a session (e.g., &oauth2.JWTSession{} for JWTs).
    2. Call t.oauth.NewAccessRequest(ctx, r, session) to validate the request.
    3. If an error occurs, use t.oauth.WriteAccessError(w, ar, err) to return the error response.
    4. Call t.oauth.NewAccessResponse(ctx, ar) to generate the response object.
    5. Call t.oauth.WriteAccessResponse(w, ar, response) to write the final HTTP response to the client.
    type tokenHandler struct {
    	ouch oauth fosite.OAuth2Provider
    }
    
    func (t *tokenHandler) TokenHandler(w http.ResponseWriter, r *http.Request) {
    	ctx := r.Context()
    	session := &oauth2.JWTSession{}
    
    	ar, err := t.oauth.NewAccessRequest(ctx, r, session)
    	if err != nil {
    		t.oauth.WriteAccessError(w, ar, err)
    		return
    	}
    
    	response, err := t.oauth.NewAccessResponse(ctx, ar)
    	if err != nil {
    		t.oauth.WriteAccessError(w, ar, err)
    		return
    	}
    
    	t.oauth.WriteAccessResponse(w, ar, response)
    }
  2. Implement Client Credentials Grant with fosite

    master

    To implement the Client Credentials Grant (RFC 6749 Section 4.4) using fosite, you need to configure an OAuth2Provider that supports the client_credentials grant type and implement a Token Endpoint handler.

    Key steps include:

    1. Configure a JWT Strategy: Use compose.NewOAuth2JWTStrategy with an RSA key to sign JWT access tokens.
    2. Setup Storage: Use a storage implementation (e.g., storage.NewMemoryStore()) to hold client credentials.
    3. Register Clients: Ensure clients are registered with GrantTypes: []string{"client_credentials"}.
    4. Compose the Provider: Use compose.Compose with compose.OAuth2ClientCredentialsGrantFactory to enable the grant type.
    5. Implement the Token Handler: Create an HTTP handler that uses NewAccessRequest, NewAccessResponse, and WriteAccessResponse to process token requests.
    // Example of composing a provider for Client Credentials Grant
    var oauth2Provider = compose.Compose(
        config,
        storage,
        compose.NewOAuth2JWTStrategy(
            key,
            nil,
        ),
        nil,
        compose.OAuth2ClientCredentialsGrantFactory,
    )
  3. Run the Client Credentials Grant example

    master

    To run the provided example, execute the Go application and then use curl to request a token from the /token endpoint.

    1. Start the server:

    go run .

    2. Request a token:

    curl http://localhost:8080/token -d grant_type=client_credentials -d client_id=test-client -d client_secret=foobar
    $go run .
    $curl http://localhost:8080/token -d grant_type=client_credentials -d client_id=test-client -d client_secret=foobar
  4. Use JWT Bearer client authentication

    master

    To use JWT Bearer authentication (often used in OpenID Connect private_key_jwt), the request must include the following parameters:

    • client_assertion_type: must be exactly urn:ietf:params:oauth:client-assertion-type:jwt-bearer.
    • client_assertion: a signed JWT.

    Requirements for the JWT assertion:

    • The iss (issuer) and sub (subject) claims must match the client_id of the OAuth 2.0 Client.
    • The jti (JWT ID) claim must be present and must be unique (the server tracks used JTIs to prevent replay attacks).
    • The exp (expiry) claim must be valid.
    • The aud (audience) claim must match one of the authorization server's token endpoint URLs.
    • The signing algorithm (alg) must match the algorithm configured for the client (GetTokenEndpointAuthSigningAlgorithm).
  5. Configure JWT Bearer Grant settings

    master

    When using the JWT Bearer grant type, you can tune these parameters:

    • GrantTypeJWTBearerCanSkipClientAuth: If true, client authentication can be skipped when using a JWT as an assertion.
    • GrantTypeJWTBearerIDOptional: If true, the jti (JWT ID) claim is not required.
    • GrantTypeJWTBearerIssuedDateOptional: If true, the iat (issued at) claim is not required.
    • GrantTypeJWTBearerMaxDuration: The maximum allowed exp (expiration) time relative to the iat claim (Default: 24 hours).
  6. Configure PKCE Security Policies

    master

    Fosite allows you to enforce Proof Key for Code Exchange (PKCE) through these configuration options:

    • EnforcePKCE: If true, requires all clients to use PKCE for authorization code flows.
    • EnforcePKCEForPublicClients: If true, only requires public clients to use PKCE.
    • EnablePKCEPlainChallengeMethod: If true, allows the plain challenge method (Note: S256 is strongly recommended over plain).
  7. Configure Pushed Authorization Requests (PAR)

    master

    To implement or customize Pushed Authorization Requests (RFC 9126), use these settings:

    • IsPushedAuthorizeEnforced: If true, enforces PAR, meaning the /authorize endpoint must contain a request_uri and cannot accept direct parameters.
    • PushedAuthorizeRequestURIPrefix: The URI prefix for PAR request_uri (Default: urn:ietf:params:oauth:request_uri:).
    • PushedAuthorizeContextLifespan: The lifespan of the short-lived PAR context (Default: 5 minutes).
    • PushedAuthorizeEndpointHandlers: A list of handlers to execute before the PAR endpoint is served.
  8. Configure Device Authorization Grant settings

    master

    For the Device Authorization Grant (RFC 8628), configure these fields:

    • DeviceAuthTokenPollingInterval: The interval at which clients should poll for the token (Default: 5 seconds).
    • DeviceVerificationURL: The URL provided in responses for device verification.
    • UserCodeLength: The length of the user_code (Default: 8).
    • UserCodeSymbols: The set of characters used to construct the user_code (Default: randx.AlphaUpper).
  9. Configure Token Lifespans

    master

    You can control the validity duration for various OAuth2 artifacts using the following Config fields. If these are not set, the server uses its internal defaults:

    • AccessTokenLifespan: Validity of access tokens (Default: 1 hour).
    • RefreshTokenLifespan: Validity of refresh tokens (Default: 30 days; set to -1 for no expiration).
    • AuthorizeCodeLifespan: Validity of authorization codes (Default: 15 minutes).
    • IDTokenLifespan: Validity of ID tokens (Default: 1 hour).
    • VerifiableCredentialsNonceLifespan: Validity of verifiable credentials nonces (Default: 1 hour).
    • DeviceAndUserCodeLifespan: Validity of device user/device code pairs (Default: 10 minutes).
  10. Use DefaultResponseModeClient for response mode support

    master

    DefaultResponseModeClient embeds *DefaultClient and adds support for specifying allowed response modes.

    Additional Fields:

    • ResponseModes ([]ResponseModeType)
    type DefaultResponseModeClient struct {
    	*DefaultClient
    	ResponseModes []ResponseModeType `json:"response_modes"`
    }
  11. Use DefaultOpenIDConnectClient for OIDC implementations

    master

    DefaultOpenIDConnectClient embeds *DefaultClient and provides the additional fields required for the OpenIDConnectClient interface.

    Additional Fields:

    • JSONWebKeysURI (string)
    • JSONWebKeys (*jose.JSONWebKeySet)
    • TokenEndpointAuthMethod (string)
    • RequestURIs ([]string)
    • RequestObjectSigningAlgorithm (string)
    • TokenEndpointAuthSigningAlgorithm (string)
    type DefaultOpenIDConnectClient struct {
    	*DefaultClient
    	JSONWebKeysURI                    string              `json:"jwks_uri"`
    	JSONWebKeys                       *jose.JSONWebKeySet `json:"jwks"`
    	TokenEndpointAuthMethod           string              `json:"token_endpoint_auth_method"`
    	RequestURIs                       []string            `json:"request_uris"`
    	RequestObjectSigningAlgorithm     string              `json:"request_object_signing_alg"`
    	TokenEndpointAuthSigningAlgorithm string              `json:"token_endpoint_auth_signing_alg"`
    }
  12. Use DefaultClient for simple implementations

    master

    DefaultClient is a basic implementation of the Client interface that can be used for testing or simple use cases. It uses struct tags for JSON serialization.

    Fields:

    • ID (string)
    • Secret ([]byte)
    • RotatedSecrets ([][]byte)
    • RedirectURIs ([]string)
    • GrantTypes ([]string)
    • ResponseTypes ([]string)
    • Scopes ([]string)
    • Audience ([]string)
    • Public (bool)
    type DefaultClient struct {
    	ID             string   `json:"id"`
    	Secret         []byte   `json:"client_secret,omitempty"`
    	RotatedSecrets [][]byte `json:"rotated_secrets,omitempty"`
    	RedirectURIs   []string `json:"redirect_uris"`
    	GrantTypes     []string `json:"grant_types"`
    	ResponseTypes  []string `json:"response_types"`
    	Scopes         []string `json:"scopes"`
    	Audience       []string `json:"audience"`
    	Public         bool     `json:"public"`
    }