Errors and troubleshooting

This page catalogs the error responses of the Truora Pass integration endpoints and the most common integration mistakes with their fixes.

The two error formats

The Truora Pass API uses two error envelopes, depending on the endpoint and grant:

Truora Pass error envelope — used by the authorization flow and by the authorization_code grant on POST /v1/oauth2/token:

Field Type Description
code integer HTTP status code
status string HTTP status text
message string Human-readable description
error_code string (optional) Machine-readable error identifier
fields array (optional) Field-level validation details

RFC 6749 error envelope — used by the refresh_token grant, the CIBA grant on POST /v1/oauth2/token, and POST /v1/oauth2/bc-authorize:

{
  "error": "invalid_grant",
  "error_description": "refresh token already used"
}

Authorization errors (authorize redirect)

When the Authorization Code flow fails after the request is accepted, Truora Pass redirects the browser back to your redirect_uri with error and error_description query parameters instead of code. With the embedded SDK, the same information arrives through the onError callback as {error, error_description, state}.

Some failures are rejected before any redirect can happen and are shown to the user inside Truora Pass instead — your application only observes that the callback never fires:

Condition What happens
redirect_uri does not exactly match a registered URI Request rejected in Truora Pass; no redirect to your application
A requested scope is not registered for your application Request rejected in Truora Pass
response_type is not code Request rejected in Truora Pass
response_mode is not empty, query, or web_message Request rejected in Truora Pass
response_mode=web_message without web_message enabled, or the embedding origin is not allow-listed Request rejected in Truora Pass
Step-up conditions: acr_not_satisfied, session_too_old, email_domain_not_allowed Handled inside the Truora Pass UI; your application sees only the eventual callback success or error

POST /v1/oauth2/tokenauthorization_code grant

Send Content-Type: application/json. Errors use the Truora Pass envelope:

HTTP status error_code Message
401 bad_credentials Invalid client credentials
400 validation_error Invalid or expired authorization code, or invalid client/redirect_uri

POST /v1/oauth2/tokenrefresh_token grant

Send Content-Type: application/json. Errors use the RFC 6749 envelope:

HTTP status error When
401 invalid_client Client authentication failed
400 invalid_grant The refresh token is invalid or expired
400 invalid_grant — “refresh token was not issued to this client” The token belongs to a different client
400 invalid_grant — “refresh token already used” Reuse detected — the entire token family is revoked
400 invalid_grant The refresh token has expired, or was invalidated by a concurrent refresh (“invalid or already used”)
400 invalid_scope The requested scope is not a subset of the originally granted scopes

See Refresh tokens for rotation and reuse-detection behavior.

POST /v1/oauth2/token — CIBA grant (polling)

Send Content-Type: application/x-www-form-urlencoded with grant_type=urn:openid:params:grant-type:ciba. Errors use the RFC 6749 envelope; all are HTTP 400 unless noted:

error When What to do
authorization_pending The user has not decided yet Keep polling, waiting interval seconds between attempts
access_denied The user declined the request Stop — the auth_req_id is consumed
expired_token The auth_req_id is unknown or expired, the request has expired, or it has already been redeemed Start a new backchannel request
invalid_grant The auth_req_id was issued to a different client Check your client_id
unsupported_grant_type The grant_type value is wrong Use urn:openid:params:grant-type:ciba
unauthorized_client Your application is not allowed to use the CIBA grant Ask your Truora contact to enable it
invalid_client (HTTP 401) Client authentication failed Check client_id / client_secret

POST /v1/oauth2/bc-authorize

Errors use the RFC 6749 envelope:

HTTP status error When
400 invalid_request A sensitive scope (documents, background) was requested without binding_message
400 invalid_request — “the resolved user has no verified phone for delivery” The user exists but has no verified phone to receive the approval link
400 unknown_user_id The login_hint does not resolve to a Truora Pass user (it must be an email)
503 notifier_unavailable The approval message could not be delivered — retry later

See the CIBA flow for the full request reference.

GET /v1/oauth2/userinfo

HTTP status Error When
401 Missing or invalid Bearer token No Authorization header, or the access token is invalid or expired
401 insufficient_scope — “Invalid token: missing scopes” The token carries no usable scopes
404 user_not_found The user behind the token no longer exists

Troubleshooting common mistakes

  1. redirect_uri mismatch. The redirect_uri in the authorization request must match a registered URI exactly (scheme, host, port, path), and the redirect_uri sent to the token endpoint must match the one used in the authorization request. Register every URI you use — see Registering your application.

  2. Expired or re-used authorization code. Authorization codes live for 10 minutes and are single-use. Exchange the code immediately after receiving it, and never retry a token exchange with the same code — a second attempt returns validation_error. If the code expired, restart the authorization flow.

  3. Scope not registered. Every scope in your authorization request must be registered for your application. Remove unregistered scopes, or add them yourself by editing your application in the Truora Pass Dashboard — see Registering your application and the Scopes reference.

  4. Wrong Content-Type on /token. The token endpoint dispatches by Content-Type: use application/json for the authorization_code and refresh_token grants, and application/x-www-form-urlencoded for the CIBA grant. Mixing them up makes the request land on the wrong grant handler.

  5. Polling faster than interval. In the CIBA flow, wait the interval (in seconds) returned by bc-authorize between polls of the token endpoint — polling faster does not speed up approval.

  6. Refresh token reuse. Refresh tokens rotate on every use: the old one is consumed and a new one is returned. Presenting an already-used refresh token is treated as reuse, and the entire token family is revoked — your application must send the user through the authorization flow again. Always persist the newest refresh_token from each response. See Refresh tokens.

  7. web_message origin not allow-listed. The embedded SDK requires your application to be registered with allows_web_message enabled and the embedding page’s origin included in allowed_web_message_origins. If either is missing, Truora Pass rejects the response_mode=web_message request.