Subsystem

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:

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.

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

Responses

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

Who am I, and what may I do?

GET /v1/me

Report the caller's identity, credential and effective permissions.

Responses

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

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

Responses