Skip to main content

Authentication

Six credential types are accepted. Which one an endpoint takes is fixed per endpoint and is listed on the reference page for that group.

Credential types

CredentialPresented asAccepted by
Session cookieCookie: __session=<value>Session, people, status and project-gated endpoints
ID tokenAuthorization: Bearer <id_token>POST /auth/verify in the body, and project-gated endpoints in the header
API keyx-api-key: <key>POST /startpage/notify
OIDC access tokenAuthorization: Bearer <access_token>GET /auth/oidc/userinfo
OIDC client credentialsBasic authorisation, or client_id and client_secret in the bodyPOST /auth/oidc/token
Request signatureZITADEL-Signature: t=<unix>,v1=<hex>POST /auth/zitadel/claims

Public endpoints accept no credential and ignore any that is sent.

Obtaining a credential

CredentialHow it is obtained
ID tokenSign in at https://id.akn.me.uk. The sign-in produces an ID token for the account
Session cookieExchange an ID token at POST /auth/verify. The response sets the cookie
Custom tokenPOST /auth/otp/sign-in and the bridge callback both return a custom token, which the browser exchanges for an ID token
API keyIssued by the site operator. There is no self-service path
OIDC client credentialsRegistered by the site operator against a fixed redirect URI allowlist
Signing secretShared with the upstream identity provider by the site operator

Sessions

POST /auth/verify sets the session cookie on a successful, approved sign-in.

PropertyValue
Name__session
Lifetime14 days from issue
Domain.akn.me.uk, so every akn subdomain sends it
FlagsHttpOnly, Secure, SameSite=Lax
RenewalNone. A new cookie requires a fresh call to POST /auth/verify
RevocationPOST /auth/logout clears the cookie in the calling browser only

Two cookie formats verify successfully: the current akn ID session token and the older provider session cookie issued before the cutover. A caller does not choose which is issued.

POST /auth/session/refresh reports whether the cookie is still valid and returns the person behind it. It does not extend the lifetime.

Authorisation

Authentication proves the account. Three further checks decide access.

CheckApplies toRequirement
Account statusEvery gated endpointThe person's status is approved
Project grantProject-gated endpointsprojects contains the required name or *, or the role is admin
Admin rolePeople administrationThe role is admin

The status values a caller can encounter are pending, approved and rejected. A person who has never been reviewed is pending.

Project nameGates
startpageGET /startpage/notifications, GET /calendar/events
statusThe /status endpoints, alongside the admin role

Refused requests

ConditionStatusBody
No credential, or one that does not verify401{"error":"Unauthorized"}
Verified account with no person record403{"error":"Forbidden"}
Verified account not approved403{"error":"Forbidden","reason":"pending"}
Approved account without the project grant403{"error":"Forbidden"}
Approved account without the admin role403{"error":"Forbidden"}
Account lookup unavailable503{"error":"Authorization unavailable"}

A 503 is not an authentication failure. Retry rather than discarding the credential and signing in again.

POST /auth/verify is the exception to the table. A sign-in that authenticates but is not approved returns 200 with approved: false and a reason. See Sessions and sign-in.

Cross-origin requests

Caller originBehaviour
https://akn.me.uk, https://www.akn.me.uk, https://id.akn.me.uk, https://halcyon.akn.me.uk, https://startpage.akn.me.uk, https://thoughts.akn.me.uk, https://status.akn.me.ukAllowed, with credentials
Any origin, on /auth/oidc/ paths and the root discovery documentAllowed, without credentials
Any other originNo allow-origin header is returned. The browser blocks the response
PropertyValue
MethodsGET, POST, PATCH, DELETE, OPTIONS
Request headersContent-Type, Authorization, x-api-key
PreflightOPTIONS answers 204
Credentialed requestsSend the session cookie only from an allowed origin

A caller on an origin outside the list works server to server, where the browser policy does not apply.

Rate limits

SurfaceLimit
POST /auth/otp/sendOne code per address per 60 seconds, and five per address per hour
Email code attemptsFive attempts per code, after which the code is destroyed
Every other endpointNo limit is applied
  • Sessions and sign-in covers the endpoints that issue and end sessions.
  • Errors covers status codes and error bodies in full.
  • Diagnostics covers refused credentials and blocked origins.