HTTP API: identity
The 5 operations tagged identity, each with its parameters, its body and what it answers.
Exchange a sign-in link for a browser session
GET /signin
Spend a sign-in link, set the browser's session cookie and send it to the app.
303 rather than 200, so the link leaves the address bar. A URL holding a credential that stays on screen is one somebody bookmarks, screenshots or pastes into a chat — and although this one is already spent by the time the redirect is followed, a person cannot tell a spent secret from a live one by looking at it.
A secret in a query string is exactly what this application refuses elsewhere, and
:data:subroutine.api.security.TOKEN_PARAMETERS names the three reasons: access logs,
browser history and referrer headers. All three were measured here rather than argued about,
and the answers differ:
- Referrer: never. Every request the browser makes after signing in carries
Referer: <root>/— a redirect keeps the original referrer rather than the redirecting URL, and the document that ends up loaded is the landing page. The 303 is what makes that true, sotest_a_link_is_exchanged_for_a_cookie_and_a_redirectis what holds it. - History: no, closed by the same 303, which is why it is a 303.
Both of those are about the path that redeems, and the confirmation page is not it.
That page is a 200 carrying the link in its own URL, so it stays in the address bar and in
the history — a deliberate trade, since it does not spend the link. Its referrer is closed separately, by
:func:_ask_before_switching sending no-referrer.
- Access log: yes, in full. :mod:
subroutine.api.logskeeps it out of the one this process writes; an operator's proxy is theirs, anddocs/hosting.mdsays so.
And the confirmation below made a dead secret into a live one. Before it, the logged value was always spent by the time the line was written, because the line is written on response. A confirmation deliberately does not spend the link — so this route can now log a credential that still works, on exactly the path somebody meets when a link arrives that they did not expect. That is the reason the redaction exists rather than a note saying it did not matter.
Parameters
link(string, in query, required)
Responses
303: Successful Response422:HTTPValidationError. Validation Error
Issue a sign-in link for somebody
POST /v1/login-links
Mint a single-use sign-in link and return it, once.
This is what makes browser sign-in safe to ship at all. A self-hoster whose mail relay is misconfigured would otherwise be locked out of their own instance with no way back in, which is §12.4's recovery property applied to a login: the console has to be a way in when the ordinary path is broken.
Request body: SignInLinkRequest as application/json, required.
Responses
201:SignInLink. Successful Response422:HTTPValidationError. Validation Error
Who am I, and what may I do?
GET /v1/me
Report the caller's identity, credential and effective permissions.
Responses
200:Me. Successful Response
Sign this browser out
DELETE /v1/session
Revoke the browser session this request presented, and clear its cookie.
Refused for a caller holding an API token, rather than quietly doing nothing. A token
is revoked with subroutine token revoke, and a route that answered "signed out" to
somebody whose credential still works would be a false statement about the thing they
most need to be true.
Responses
204: Successful Response
Sign somebody out of every browser they are signed in on
POST /v1/users/{username}/signout
Revoke every live session and unspent link belonging to one account.
This is what a lost laptop needs, and revocation being a row rather than a wait is the property an opaque cookie was chosen for — a self-describing signed credential would have kept working until it expired, whatever anybody did about it.
Unspent links go too. A link is a session that has not happened yet, so stopping the sessions and leaving the links would be a control that reads as complete and is not.
Parameters
username(string, in path, required)
Responses
200:SignedOut. Successful Response422:HTTPValidationError. Validation Error