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

The device verification page (RFC 8628 §3.3), at `{oauth_path}/device`:
where a person enters the user code a CLI or a device shows them, then
approves or denies its request on the consent page. Mount it, like
`Sake.Auth.Authorize`, inside the pipeline that requires a signed-in
person; Sake reads the person through `Sake.Auth.Subject`. It answers
404 without `device:` in the auth config.

`GET` shows the code entry form (`c:Sake.Auth.Consent.render_user_code/1`),
prefilled from `verification_uri_complete`'s `user_code`; nothing is
looked up until the person submits it. A posted code shows the
consent page, with the code on it to compare with the device's. A
code that is unknown, expired or already decided is refused with the
same message, and each signed-in person may enter five codes a minute,
which is what keeps the eight characters of a user code out of reach
of guessing. The consent page shows even when the person approved the
client before: whoever started the request may have sent the code to
someone else to approve.

Both forms carry a signed blob bound to the signed-in person, which
expires after ten minutes, and the host's CSRF token when its pipeline
runs `Plug.CSRFProtection`, as `Sake.Auth.Authorize`'s form does. The
pages refuse to be framed.

A device request may say how the person must have signed in (RFC
9470: `acr_values`, `max_age`). Once the person submits its code, a
sign-in that does not meet it (by the subject module's
`authentication/1`) is sent to `reauthenticate/2`, with the conn's
query string set to the code (`user_code=...`), so that coming back to
`request_path?query_string` shows the form with the code filled in;
the grant stays pending meanwhile. The approval records the `acr` and
`auth_time` of the person's sign-in, which the tokens carry.

---

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