Skip to content
Developer docs
Menu

Reference

Errors

Every error your app can receive, and what to do about each one.

Errors reach your app in four ways: as a page SSO shows the person, as parameters on your redirect URI, as a JSON body from a server-to-server call, or as a 401 from an endpoint that takes a bearer token.

Errors SSO shows the person

SSO never redirects a request it can't trust. These problems show an error page at sso.aldelo.com, and your app gets no callback:

  • the client_id is unknown, or the app is suspended;
  • the redirect_uri isn't one of your registered URIs;
  • response_type isn't code, or PKCE is missing or doesn't use S256;
  • scope is empty or asks for a scope your app isn't registered for;
  • state is shorter than 8 bytes, or nonce is outside 8 to 512 bytes;
  • prompt, max_age or acr_values is malformed.

The page shows a reference code. Send it to developer@aldelo.com and we can find the exact reason; for example, a bad nonce is recorded as nonce_invalid.

The same applies to /logout: a missing, expired or foreign id_token_hint, or an unregistered post_logout_redirect_uri, shows an error page. If the person declines to share their details with your app, the sign-in also ends on an SSO page.

Errors returned to your app

Once SSO has checked your app and redirect URI, later problems come back to your redirect URI as error and error_description, with your state:

HTTP
GET https://app.example.com/callback?error=access_denied&error_description=organization_access_denied&state=af0ifjsldkj-state
Errors on your redirect URI
errorerror_descriptionWhyWhat to do
login_requiredThe Authorization Server requires End-User authentication.You sent prompt=none, and the person has no SSO session recent enough for your request.Start an interactive sign-in.
interaction_requiredorganization_selection_requiredYou sent prompt=none to a multi-organization app, and the person has to choose an organization.Start an interactive sign-in. See Organizations.
access_deniedorganization_access_deniedThe person isn't an active member of the organization your app needs, or of any organization your multi-organization app serves.Ask them to get access from their organization's administrator.
access_deniedstrong authentication required; no second factor enrolledYou required urn:aldelo:sso:acr:mfa, and the person hasn't set up a second factor.Ask them to add a passkey or an authenticator app to their Aldelo account.
access_deniedstrong authentication required; no second factor enrolledYou required urn:aldelo:sso:acr:pwd of a person who signed in by text message, and they haven't set up a second factor either.Ask them to add a passkey or an authenticator app, or to sign in with a password instead.
invalid_requestNames the valueAn acr_values entry isn't supported.Send only values listed in the discovery document's acr_values_supported.

Match these error_description values as whole strings; don't parse them.

Token endpoint errors

POST /oauth2/token answers problems as JSON in the OAuth 2.0 shape, for example:

JSON
{
  "error": "invalid_grant",
  "error_description": "A description for developers."
}
Token endpoint errors
StatuserrorMeaning
400invalid_requestThe body is malformed, or the code has expired.
400invalid_grantThe code is unknown, already used or revoked, the PKCE verifier doesn't match, or the person's access changed since they signed in.
400unsupported_grant_typeOnly authorization_code is supported.
401invalid_clientThe client_id is unknown, or the client secret is wrong or missing.
429(JSON envelope)Too many requests: the endpoint allows 5 requests per 60 seconds per client and IP address.
500server_errorThe rate limiter itself failed. Rare; treat it like any other server error.
503temporarily_unavailableTry again shortly.

Never retry a code exchange

A code works once. Using it a second time fails, and also revokes the access token the first exchange issued.

Bearer token errors

/userinfo and /api/v1/me/memberships answer every token problem the same way, whether the token is missing, malformed, expired or revoked, the app is suspended, or the app session has ended:

HTTP
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer error="invalid_token"
Content-Type: application/json;charset=UTF-8

{"error":"invalid_token"}

Sign the person in again to get a new token.

/oauth2/introspect and /oauth2/revoke both authenticate the caller the same way the token endpoint does: your own client credentials, a client secret, in the Authorization header or as form fields. A public app — a browser or mobile client, which has none — cannot call either.

Both share the same failure shapes: 401 on a client-authentication failure, 400 on a missing token parameter, 429 on the rate limit (5 requests per 60 seconds per client and IP address, the same for both), 500 on a server-side fault, and 503 temporarily_unavailable when the endpoint isn't wired. Beyond those, each endpoint never reports a token problem as an error: /oauth2/introspect answers {"active":false} for every unknown, malformed, revoked, expired, cross-owner, app-session-ended or suspended-client token, and /oauth2/revoke answers 200 for every token, active or not, whether or not anything was flipped.

JSON API errors

Endpoints under /api/v1, and the rate limits, use one JSON envelope:

JSON
{
  "error": {
    "code": "RATE_LIMITED",
    "message": "too many requests",
    "correlation_id": "req_00000000-0000-0000-0000-000000000000",
    "timestamp": "2026-01-01T00:00:00Z"
  }
}

Every response carries an X-Correlation-ID header. Send your own X-Correlation-ID (up to 128 bytes) to trace a request across your services and ours, and quote it when you contact us.