Refresh token error reasons
When a refresh token request fails, IDMe can tell your application why with a short, fixed code called error_reason. Your application can then react correctly. For example, it can send the member to sign in again instead of retrying a token that will never work.
error_reason is off by default and is turned on separately for each integration. To turn it on, contact your IDMe account team.
Why it exists
A failed refresh returns a generic invalid_grant error. The only explanation is an English sentence in error_description, which is written for people and can change. Applications that cannot tell the causes apart often retry the same dead refresh token. That adds failed calls and leaves members stuck instead of signed back in.
error_reason adds one field to the failed refresh response. The HTTP status, error, and error_description do not change.
How it works
- Your application sends the refresh token to IDMe, as it does today.
- If the token is valid, IDMe returns new tokens. Successful responses do not change.
- If the token is not valid, IDMe returns the usual
invalid_granterror and addserror_reason, a code that names the cause. - Your application records the code and sends the member to sign in again. It does not retry the same refresh token.
Availability
error_reason is set per integration (OAuth client) and per environment. We recommend turning it on in sandbox first. Tell your account team which integration and environment you want. Turning it on or off needs no code change from you.
Response
error_reason appears only on failed POST /oauth/token requests with grant_type=refresh_token. The request does not change:
Public clients that use PKCE send no client_secret. Credentials can also be sent in an HTTP Basic Authorization header. error_reason works the same way in every case.
Values
The values are fixed codes for your code to compare. Write your handling so that a value you don’t recognize is treated as a failed refresh.
IDMe checks these in the order listed and returns the first one that applies. For example, a used refresh token presented by a different client returns refresh_token_revoked.
When the field is absent
The response has no error_reason in these cases, even when the field is turned on:
- The request has no
refresh_tokenparameter. This returnsinvalid_request. - Client authentication fails, for example because of an unknown
client_idor a wrongclient_secret. This returns HTTP 401invalid_clientbefore IDMe looks at the refresh token. - The member’s account can no longer sign in, for example because it is suspended. This returns
invalid_grantwith no reason, so the response does not reveal the account’s status. - The request uses any other grant type, such as
authorization_code. - The refresh succeeds.
Handling refresh failures
On any invalid_grant response to a refresh request, with or without error_reason, stop using that refresh token. It will not succeed. Discard it and send the member through sign-in to get a new token pair. Use error_reason to log the cause, show the right message, and find problems in your own token storage.
- Read
errorfirst, thenerror_reason. - Don’t require
error_reasonto be present. It can be absent (see When the field is absent). - Don’t parse
error_description. Its text can change, and it can be translated into the member’s language. - Don’t retry a refresh token after
invalid_grant. - Save the new refresh token after every successful refresh.
- Ignore JSON fields you don’t recognize, so that new fields never break your integration.
Testing in sandbox
Ask your account team to turn on error_reason for your sandbox integration. Sign a test member in through your normal flow to get a token pair, then run these checks against https://api.idmelabs.com.
Success, then refresh_token_revoked
Run refresh "$REFRESH_TOKEN". It returns new tokens. Run the same command again with the old token. It returns refresh_token_revoked.
If a check returns invalid_grant without error_reason, the field may not be turned on yet. Wait a few minutes and try again, then contact your account team.
FAQ
Does error_reason expose anything new about the member?
No. Each value repeats what error_description already says, in a form your code can read. IDMe never returns a reason for account-status cases such as a suspended account.
Will turning it on break our integration?
No. The HTTP status, error, and error_description don’t change. The only change is one extra JSON field, and only after you ask for it.
Does it apply to other grant types or endpoints?
No. It applies only to the refresh token grant on POST /oauth/token. Authorization code exchange, the authorization endpoint, and token revocation are unchanged.
Can we retry on any of these values?
No. All four mean the refresh token cannot be used again. Retrying only adds failed calls.