Error Reference
SingleSign returns errors in a consistent JSON format across all endpoints. This page documents every error code, what causes it, and how to fix it.
Error Response Format
All error responses follow this structure:
{
"error": "error_code",
"error_description": "A human-readable description of the error."
}
| Field | Type | Description |
|---|---|---|
error | string | A machine-readable error code (see table below). |
error_description | string | A human-readable explanation of the error. Not intended for end users — use it for debugging. |
Authorization Endpoint Errors
Errors from the /oauth/authorize endpoint are returned as query parameters on the redirect URI:
https://app.example.com/callback?error=access_denied&error_description=The+user+denied+the+request&state=abc123
Token / Introspect / Revoke Endpoint Errors
Errors from POST endpoints are returned as JSON in the response body with an appropriate HTTP status code:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "invalid_grant",
"error_description": "The authorization code has expired."
}
Error Codes
invalid_request
HTTP Status: 400
The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed.
Common Causes:
- Missing
platform_guidparameter. - Missing
redirect_uriin the token request. - Missing
grant_typein the token request. - Malformed URL encoding.
Troubleshooting:
- Verify all required parameters are present. Check the Endpoint Reference for the complete parameter list.
- Ensure parameters are properly URL-encoded.
- Check that
Content-Typeis set toapplication/x-www-form-urlencodedfor POST requests. - Make sure no parameter is included more than once.
# Check: Is platform_guid present?
curl -X POST "https://api.singlesign.com/oauth/token" \
-d "grant_type=authorization_code&code=xxx&redirect_uri=...&client_id=...&platform_guid=YOUR_GUID"
# This is required ──────────────────────────────┘
invalid_client
HTTP Status: 401
Client authentication failed. The client_id is unknown, no client authentication was provided, or the authentication method is not supported.
Common Causes:
- Wrong
client_id. - Wrong
client_secretfor confidential clients. - Sending
client_secretfor a public client (not expected). - Malformed Basic auth header.
Troubleshooting:
- Double-check your
client_idin the developer portal. - For confidential clients, verify the
client_secretis correct and hasn't been rotated. - Ensure you're using the right authentication method: Basic auth header or POST body parameters.
- Check for extra whitespace or newlines in your credentials.
# Confidential client: verify credentials work
curl -X POST "https://api.singlesign.com/oauth/token" \
-u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
-d "grant_type=authorization_code&code=xxx&redirect_uri=...&platform_guid=YOUR_GUID"
invalid_grant
HTTP Status: 400
The authorization code, refresh token, or PKCE verifier is invalid, expired, or has already been used.
Common Causes:
- The authorization code has expired (codes are valid for 10 minutes).
- The authorization code has already been exchanged (single-use).
- The
code_verifierdoes not match thecode_challengesent during authorization. - The
redirect_uriin the token request does not match the one used in the authorization request. - The refresh token has been revoked or expired.
Troubleshooting:
- Expired code: Authorization codes expire after 10 minutes. If the user took too long, redirect them to authorize again.
- Code already used: Codes are single-use. If you're retrying a failed request, the code may have already been consumed. Start a new authorization flow.
- PKCE mismatch: Ensure the
code_verifiersent to/oauth/tokenis the exact same value used to generate thecode_challengesent to/oauth/authorize. Do not regenerate it — retrieve it from storage. - Redirect URI mismatch: The
redirect_uriin the token request must be identical to the one in the authorization request.
# Common fix: Make sure code_verifier matches code_challenge
# code_challenge = BASE64URL(SHA256(code_verifier))
echo -n "YOUR_CODE_VERIFIER" | openssl dgst -sha256 -binary | base64 | tr '+/' '-_' | tr -d '='
# The output should match the code_challenge you sent to /authorize
unauthorized_client
HTTP Status: 400
The client is not authorized to use the requested grant type or scope.
Common Causes:
- A public client attempting to use
client_credentialsgrant. - Requesting a scope that is not configured for the application.
- Using a grant type not enabled for the application.
Troubleshooting:
- Check your application's settings in the developer portal.
- Verify the requested scopes match those configured for your app.
- Ensure you're using the correct grant type for your client type (
authorization_codefor user authentication).
unsupported_grant_type
HTTP Status: 400
The authorization server does not support the requested grant type.
Common Causes:
- Typo in the
grant_typeparameter. - Using
implicitorclient_credentials(not supported). - Missing the
grant_typeparameter entirely.
Troubleshooting:
- SingleSign supports two grant types:
authorization_codeandrefresh_token. - Check for typos:
grant_type=authorization_code(notauth_code,code, etc.).
# Correct grant types:
grant_type=authorization_code # For code exchange
grant_type=refresh_token # For token refresh
invalid_scope
HTTP Status: 400
The requested scope is invalid, unknown, or exceeds the scopes granted to the client.
Common Causes:
- Typo in a scope name.
- Requesting a scope not registered for your app.
- Missing the
openidscope (required for OIDC).
Troubleshooting:
- Check spelling. Valid scopes are:
openid,profile,email,phone,address,offline_access. - Ensure the scopes are registered for your app in the developer portal.
- Always include
openidas the first scope.
# Valid scope string:
scope=openid profile email
# Invalid examples:
scope=open_id profile email ← typo (open_id vs openid)
scope=profile email ← missing openid
scope=openid profile email admin ← admin is not a valid scope
access_denied
HTTP Status: 403 (or redirect with error parameter)
The resource owner (user) denied the authorization request, or the server denied the request for another reason.
Common Causes:
- The user clicked "Deny" on the consent screen.
- The user's account is suspended or restricted.
- Platform-level restrictions prevent the authorization.
Troubleshooting:
- If the user denied consent, show a friendly message and offer to try again.
- Do not automatically retry — the user made a deliberate choice.
- If this happens unexpectedly, check whether the user's account status is active.
const error = params.get("error");
if (error === "access_denied") {
showMessage(
"You declined the sign-in request. You can try again whenever you're ready."
);
}
redirect_uri_mismatch
HTTP Status: 400 (returned directly, not via redirect)
The redirect_uri provided does not match any registered redirect URI for the application.
Common Causes:
- Trailing slash mismatch (
/callbackvs/callback/). - Port mismatch (
localhost:3000vslocalhost:5173). - Scheme mismatch (
httpvshttps). - Path mismatch (
/callbackvs/auth/callback). - The URI was never registered in the developer portal.
Troubleshooting:
- Copy the exact
redirect_urifrom your authorization request. - Compare it character-by-character with the URIs in your developer portal.
- See Redirect URIs for detailed matching rules.
server_error
HTTP Status: 500
An unexpected error occurred on SingleSign's servers.
Troubleshooting:
- Retry the request after a short delay (use exponential backoff).
- If the error persists, check the SingleSign status page for outages.
- Contact support if the issue continues.
temporarily_unavailable
HTTP Status: 503
The authorization server is temporarily unable to handle the request due to maintenance or overload.
Troubleshooting:
- Retry with exponential backoff.
- Check the
Retry-Afterresponse header for the recommended wait time. - See Rate Limits for best practices.
HTTP Status Code Summary
| Status | Meaning | Common Error Codes |
|---|---|---|
| 400 | Bad Request | invalid_request, invalid_grant, invalid_scope, unauthorized_client, unsupported_grant_type |
| 401 | Unauthorized | invalid_client |
| 403 | Forbidden | access_denied |
| 429 | Too Many Requests | (rate limited — see Rate Limits) |
| 500 | Internal Server Error | server_error |
| 503 | Service Unavailable | temporarily_unavailable |
Best Practices for Error Handling
- Always check
errorbefore processing a response. Both redirect callbacks and JSON responses may contain errors. - Log
erroranderror_descriptionfor debugging, but show user-friendly messages to end users. - Don't expose
error_descriptionto users — it may contain internal details. - Implement retry logic for
server_errorandtemporarily_unavailablewith exponential backoff. - Handle
invalid_grantgracefully — redirect the user to log in again rather than showing a cryptic error.
Next Steps
- Endpoint Reference — Parameter details for all endpoints.
- Rate Limits — Handling 429 responses.
- Troubleshooting — Common issues and fixes.
Last updated: 2026-02-16
Related docs
- SingleSign Developer DocumentationLearn how to integrate SingleSign identity and authentication into your applications using OAuth 2.0 and OpenID Connect.
- the Endpoint Reference docsComplete API reference for all SingleSign OAuth 2.0 and OpenID Connect endpoints with methods, parameters, and curl examples.
- Rate LimitsPer-endpoint rate limits, 429 response format, Retry-After header, and best practices for staying within limits.
- the Troubleshooting OAuth errors docsCommon SingleSign integration errors with causes and fixes: PKCE mismatch, redirect URI errors, expired codes, invalid scopes, and CORS problems.
- free identity providerSingleSign pricing in one line: sign-in is free, with no monthly-active-user meter. See exactly what is included, and what SingleSign Mail costs for businesses.
- Identity provider alternativesIdentity provider alternatives, by the provider you are leaving: what actually has to change in your code, and what does not.
- SingleSign vs Auth0SingleSign vs Auth0 compared on the difference that matters: who owns the account. A side-by-side table, then the three cases where each one is the right call.
- Okta comparisonSingleSign vs Okta: Okta is built for workforce identity inside a company, SingleSign for consumer sign-in across applications.