Where an error shows up
Three different places, and knowing which one you are looking at narrows the cause immediately:
The first case never redirects — before we have verified that a
redirect_uri belongs to the
client, bouncing the user anywhere would make the endpoint an open redirector.
Authorization errors
Token errors
BankID hint codes
When a login fails on the BankID side, the reason appears as a hint code — on the login page, and indata.object.reason of a login.failed webhook.
Recoverable failures do not fire a webhook: the login page offers a retry inside the same session,
and notifying on every mistyped cancel would flood your endpoint.
Session API errors
The Session API returns the same error body as the rest of the sajn API: branch oncode, show
userMessage to your users, and log requestId. For the full shape, see
Errors.
A session or client from another workspace answers
404, not 403. “Exists but isn’t yours”
is itself information, so sajn doesn’t confirm it.Diagnosing by symptom
Everything works locally, fails in production
Everything works locally, fails in production
Production redirect URIs need to be registered too, and
https matches exactly. Also check
your client was switched to a production certificate — a test client will not accept real
BankIDs.The user says they logged in but nothing happened
The user says they logged in but nothing happened
Classic abandoned-browser case: they completed BankID and closed the in-app browser before the
redirect. The authentication succeeded on our side. Subscribe to
login.completed to see it.id_token signature verification fails
id_token signature verification fails
Usually a cached JWKS after a key rotation. Use a client that refetches on an unknown
kid
rather than pinning a key. Also confirm you are validating iss as exactly
https://login.sajn.se, with no trailing slash.sub changed for a user you recognise
sub changed for a user you recognise
It should not —
sub is stable per person per organization. If it changed, you are almost
certainly comparing across two different organizations, or between a test and a production
environment, which are deliberately separate identifier spaces.The login page says the link is no longer valid
The login page says the link is no longer valid
The login was already completed, or it expired (15 minutes). Start a new one — links are
single-use by design, so a leaked URL is worthless.

