Authorization for a Sake endpoint: the host app is the OAuth 2.1 authorization server, and the endpoint is the resource server.
Configure it on the Sake child (see Sake.child_spec/1) and mount the
routes with Sake.Router (Phoenix) or Sake.Auth.RouterPlug (Plug).
An endpoint whose tokens come from another authorization server is
Sake.Auth.External's instead.
The public API
These modules are for host code; every other Sake.Auth module is
Sake's own and may change in any release:
Sake.Auth— the configuration, a person's grants, pruning.Sake.Auth.Config— theauth:options.Sake.Auth.Subject— the behaviour of the host's subject module.Sake.Auth.ConsentandSake.Auth.Consent.Default— the consent and error pages.Sake.Auth.Store,Sake.Auth.Store.ETS,Sake.Auth.Store.EctoandSake.Auth.Migration— where clients, codes, pushed authorization requests, device grants, tokens and consents live;Sake.Auth.Code,Sake.Auth.PushedRequestandSake.Auth.DeviceGrantare the code, the pushed request and the device grant a store keeps.Sake.Auth.External— an endpoint on another authorization server.Sake.Auth.TokenRecord— the token of a request, inctx.token.Sake.Auth.ClientandSake.Auth.Clients— the registered clients.Sake.Auth.TrustedIssuer— the issuers of JWT grants.Sake.Auth.Challenge— aWWW-Authenticatechallenge.Sake.Auth.WellKnown,Sake.Auth.Authorize,Sake.Auth.DeviceVerificationandSake.Auth.RouterPlug— the endpoints a Plug host mounts itself.Sake.Client.Auth,Sake.Client.Auth.Browser,Sake.Client.Auth.Headless,Sake.Client.Auth.DeviceandSake.Client.Auth.Store— the client'sauth:options.
Calls run one way: the rest of Sake calls these modules (and the
functions marked @doc false that say who calls them), and nothing in
Sake.Auth or Sake.Client.Auth calls the rest of Sake.
Cores and adapters
For contributors: each endpoint is a core and an adapter, both under
lib/sake/auth/. The core is pure functions over the configuration and
plain data (a parameter map, header values, a principal); it may use
the store, and it never sees a Plug.Conn. The adapter is a thin plug
that parses the request, reads the signed-in person with
Sake.Auth.Subject.from_conn/1 where one is involved, calls the
core, and renders JSON, a redirect or the consent page.
- Authorization:
authorization_request.exvalidates a request (parameters a later endpoint adds go in itsextra), andgrant.exdecides once the person is known and issues the code;Sake.Auth.Authorizeis the adapter, and keeps the consent form's signed request and CSRF token. - Tokens:
token_grants.ex, whoseexchange/4has one clause per grant type;token.exis the adapter. - Pushed authorization requests (RFC 9126):
par.exvalidates and stores a pushed request as an authorization request, and takes it back for the authorize endpoint;pushed_authorization.ex(the client's push) is the adapter, andSake.Auth.Authorizetakes arequest_uri. - Device authorization (RFC 8628):
device.exstarts a device grant and takes the person's decision throughgrant.ex;device_authorization.ex(the client's request) andSake.Auth.DeviceVerification(the page where the person enters the user code) are the adapters, and the token endpoint's device code clause issues the tokens. - Revocation and registration:
revocation.exandregistration.ex;revoke.exanddcr.exare the adapters. - Metadata:
metadata.ex, a base map and a list of contributors, one per feature;Sake.Auth.WellKnownis the adapter. - Access tokens:
bearer.exchecks a request described as a map;authenticate/2in this module is its adapter. - How the person signed in (RFC 9470):
authentication.exholds the context (acr,auth_time), an authorization request'sacr_valuesandmax_age, and the check of one against the other, for the authorization server's adapters (which askSake.Auth.Subject.authentication/1and callSake.Auth.Subject.reauthenticate/2) and for the components'authentication:requirements alike. - OpenID Connect:
signing_keys.exreadssigning_keys:and builds the JWK Set, whichpublic_keys.exserves at/jwks;id_token.exmakes the ID token the token endpoint's grants add foropenid;claims.exis the userinfo endpoint, checking the token throughbearer.ex, anduser_info.exits adapter, which renders a refusal as an OAuth error (RFC 6750) rather than JSON-RPC.metadata.exbuilds the OpenID Provider metadata from the authorization server's, andSake.Auth.WellKnownserves it.
A new endpoint is a core module and an adapter, a route in
Sake.Router and in Sake.Auth.RouterPlug, and a URL helper in
Sake.Auth.Config next to authorize_url/1; a new metadata field is a
contributor in metadata.ex. A test checks that no core module calls
Plug.Conn.
Summary
Functions
The active grants of a person: one entry per client, for a settings page.
Deletes expired codes, device grants and tokens, the remembered
consents older than the refresh token lifetime that no live token
family still uses, and the dynamically registered clients that, unused_client_ttl seconds
(a day by default) after registering, hold no live token, consent,
code or device grant. Schedule it (a cron job, Oban, or a periodic task).
Revokes every token of a client for a person, and forgets every consent of that client for the person.
Functions
@spec config() :: Sake.Auth.Config.t()
@spec list_grants(Sake.Auth.Config.t(), String.t()) :: [map()]
The active grants of a person: one entry per client, for a settings page.
@spec prune(Sake.Auth.Config.t()) :: :ok
Deletes expired codes, device grants and tokens, the remembered
consents older than the refresh token lifetime that no live token
family still uses, and the dynamically registered clients that, unused_client_ttl seconds
(a day by default) after registering, hold no live token, consent,
code or device grant. Schedule it (a cron job, Oban, or a periodic task).
@spec revoke_grant(Sake.Auth.Config.t(), String.t(), String.t()) :: :ok
Revokes every token of a client for a person, and forgets every consent of that client for the person.