The authorization endpoint: GET validates the request and shows the
consent page (or redirects at once when consent is remembered); POST
records the decision. Mount it inside the pipeline that requires a
signed-in person; Sake reads the person through Sake.Auth.Subject.
After it resolves the resource (the endpoint URL the token is for), it
asks the subject module's optional authorize_resource?/2 whether this
person may authorize a client for it; a false answer sends the client
access_denied. A remembered consent is kept per person, client and
resource.
The consent form is protected in two layers. The hidden request field
is a signed blob bound to the signed-in person, and it expires after ten
minutes: a form posted by anyone else, or later, is refused. When the
host's pipeline runs Plug.CSRFProtection (protect_from_forgery in
Phoenix), the form also carries the CSRF token and the host's plug
checks it. A Plug-only host without CSRF middleware sends an empty
_csrf_token field and relies on the signed blob alone.
The consent and error pages refuse to be framed (x-frame-options: DENY and content-security-policy: frame-ancestors 'none').
With par: (RFC 9126), a request with a request_uri is the pushed
request it names, taken once: its client_id must be the client that
pushed it, and every other parameter of the query is ignored. A
request_uri that is unknown, expired, already used or another
client's gets an error page. When pushed requests are required (par: [required: true], or a client registered with
require_pushed_authorization_requests), any other request is sent
back with invalid_request. The consent form carries the request
itself, so approving or denying needs the request_uri no more; a
reload of the page after it was taken shows the error page.
A request may say how the person must have signed in (RFC 9470):
acr_values (space-separated, any one will do) and max_age (in
seconds), sent directly or pushed. Before anything is decided, the
subject module's authentication/1 says how the signed-in person did;
when that does not meet the request, its reauthenticate/2 sends them
to sign in again and back to this URL (a pushed request is kept for
the return, until it expires), or, without it, an error page says so.
The code carries the acr and auth_time of the approval into the
tokens. See Sake.Auth.Subject.
Summary
Functions
Issues a code for request (a map with client_id, redirect_uri,
code_challenge, scopes, resource) and subject_id; returns the plain
code. authentication, %{acr: acr, auth_time: datetime}, is how
the person signed in, which the code's tokens carry (RFC 9470).
Functions
@spec issue_code(Sake.Auth.Config.t(), map(), String.t(), map()) :: String.t()
Issues a code for request (a map with client_id, redirect_uri,
code_challenge, scopes, resource) and subject_id; returns the plain
code. authentication, %{acr: acr, auth_time: datetime}, is how
the person signed in, which the code's tokens carry (RFC 9470).