# `Sake.Auth.Authorize`
[🔗](https://github.com/hattoriai/sake/blob/v0.4.3/lib/sake/auth/authorize.ex#L1)

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

# `issue_code`

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

---

*Consult [api-reference.md](api-reference.md) for complete listing*
