feat(auth): serve the device authorization grant

A program with no browser — the desktop app — had a client for RFC 8628 and
nothing to point it at. This serves the other half: a device authorization
request that hands back a code, a page a person enters that code on, and a
token endpoint that answers the poll.

Both of the paths the client already implements are now reachable. Polling
faster than the advertised interval gets slow_down, and each warning widens
the interval so ignoring one costs more than the last; refusing gets
access_denied, so a request nobody started stops instead of being polled until
it ages out. The interval is capped, because it only ever grows and a code has
to stay pollable for the whole of its life.

The codes live in the same storage as the other short-lived grants rather than
in a table, since that is what they are. User codes are drawn from an alphabet
with no vowels and no look-alike pairs, and are accepted back in whatever case
and spacing a person retyped them in.
This commit is contained in:
Wanjohi
2026-09-05 00:02:15 +03:00
parent 1e81a8f92d
commit 2a1b7abe9a
4 changed files with 572 additions and 1 deletions

View File

@@ -7,6 +7,10 @@
"type": "module",
"sideEffects": false,
"exports": {
"./ui/code": {
"types": "./src/ui/code.tsx",
"import": "./src/ui/code.tsx"
},
"./*": {
"types": "./src/*.ts",
"import": "./src/*.ts"