Sake.Auth (Sake v0.4.3)

Copy Markdown View Source

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:

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.ex validates a request (parameters a later endpoint adds go in its extra), and grant.ex decides once the person is known and issues the code; Sake.Auth.Authorize is the adapter, and keeps the consent form's signed request and CSRF token.
  • Tokens: token_grants.ex, whose exchange/4 has one clause per grant type; token.ex is the adapter.
  • Pushed authorization requests (RFC 9126): par.ex validates 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, and Sake.Auth.Authorize takes a request_uri.
  • Device authorization (RFC 8628): device.ex starts a device grant and takes the person's decision through grant.ex; device_authorization.ex (the client's request) and Sake.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.ex and registration.ex; revoke.ex and dcr.ex are the adapters.
  • Metadata: metadata.ex, a base map and a list of contributors, one per feature; Sake.Auth.WellKnown is the adapter.
  • Access tokens: bearer.ex checks a request described as a map; authenticate/2 in this module is its adapter.
  • How the person signed in (RFC 9470): authentication.ex holds the context (acr, auth_time), an authorization request's acr_values and max_age, and the check of one against the other, for the authorization server's adapters (which ask Sake.Auth.Subject.authentication/1 and call Sake.Auth.Subject.reauthenticate/2) and for the components' authentication: requirements alike.
  • OpenID Connect: signing_keys.ex reads signing_keys: and builds the JWK Set, which public_keys.ex serves at /jwks; id_token.ex makes the ID token the token endpoint's grants add for openid; claims.ex is the userinfo endpoint, checking the token through bearer.ex, and user_info.ex its adapter, which renders a refusal as an OAuth error (RFC 6750) rather than JSON-RPC. metadata.ex builds the OpenID Provider metadata from the authorization server's, and Sake.Auth.WellKnown serves 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

config()

@spec config() :: Sake.Auth.Config.t()

list_grants(config, subject_id)

@spec list_grants(Sake.Auth.Config.t(), String.t()) :: [map()]

The active grants of a person: one entry per client, for a settings page.

prune(config)

@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).

revoke_grant(config, subject_id, client_id)

@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.