Common Problems
Spec-compliant OAuth 2.0 and OpenID Connect is hard. Let's take a look how to resolve certain issues.
First Aid
There are three things you can do to quickly debug any issue:
- Check the logs. Ory Hydra has extensive logging and you will find the issue most likely in the logs. Here is an example log
line for a client that requested a redirect URL that didn't match the whitelisted redirect URLS:
time="2018-08-07T16:01:16Z" level=error msg="An error occurred" description="The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed" error=invalid_request hint="The \"redirect_uri\" parameter doesn't match any of the OAuth 2.0 Client's pre-registered redirect urls."
- Check the URL because of two reasons:
- Ory Hydra sends
error_hint
,error
,error_description
,error_debug
in the URL. You will find the cause of the error most likely in there. - You are maybe in the wrong URL. Make sure the host and port and path is correct. This happens often when you're just starting out and experimenting.
- Ory Hydra sends
- Set environment variable
OAUTH2_EXPOSE_INTERNAL_ERRORS=true
. Don't do this in production, it's possible, though unlikely, that important data leaks with this. If set to true, Ory Hydra will set theerror_debug
query parameter if debug information is available. - If you're just starting out and experimenting your docker set up doesn't work at all:
- Stop all containers
- Remove them (unless you have something important running)
- Retry. This can help a lot if you are new to this!
OpenID Connect ID Token missing
If you expect an OAuth 2.0 ID Token but aren't receiving one, this can have multiple reasons:
- You are using the
client_credentials
grant which can't return an ID token. - You forgot to request the
openid
scope when calling/oauth2/auth?response_type=code
(Authorize Code Flow - correct would be/oauth2/auth?response_type=code&scope=openid
) or theid_token
response type when calling/oauth2/auth?response_type=token
(Implicit/Hybrid flow - correct would be/oauth2/auth?response_type=token+id_token&scope=openid
or any other combination such asresponse_type=id_token
,response_type=token+code+id_token
). - You forgot to include
nonce
when calling/oauth2/auth?response_type=id_token
or any combination ofid_token
(token+id_token
,token+code+id_token
etc.)nonce
is a value sent by the client application and included as a claim in the returnedid_token
. Thenonce
claim can then be verified by the client application to mitigate any replay attacks. Optional for Authoize Code Flow, but mandatory for Implicit/Hybrid flow. Correct request would be -/oauth2/auth?response_type=id_token&nonce=some-value
. You can read more aboutnonce
here OpenId Connect Core. - Your consent app didn't send
granted_scope: ["openid"]
or when accepting the consent request. - The OAuth 2.0 Client making the request isn't allowed to request the scope
openid
.
OAuth 2.0 Refresh Token is missing
If you expect an OAuth 2.0 Refresh Token but aren't receiving one, this can have multiple reasons:
- You are using an implicit or hybrid flow. These flows never return a refresh token!
- You are using the
client_credentials
grant which can't return a refresh token. - You forgot to request the
offline
oroffline_access
scope when calling/oauth2/auth
. - You consent app didn't send
granted_scope: ["offline"]
orgranted_scope: ["offline_access"]
when accepting the consent request. - The OAuth 2.0 Client making the request isn't allowed to grant type
refresh_token
.
OAuth 2.0 Authorize Code Flow fails
The most likely cause is misconfiguration, summarized in the next sections.
Refresh Token Flow fails
Refresh tokens can become invalid if abuse is detected, but coding issues may also trigger this scenario, for example if a client makes multiple requests.
Some common examples:
- Replay of authorization code grant.
- Replay of refresh token grant.
Wrong or misconfigured OAuth 2.0 Client
You are using the wrong OAuth 2.0 Client or the OAuth 2.0 Client has a broken configuration. To check that you're using the right client, run:
hydra clients get --endpoint http://ory-hydra <the-client-id>
The result shows you the whole client (excluding its secret). Check that the values are correct. Example:
{
"client_id": "my-client",
"grant_types": [
"authorization_code"
],
"jwks": {},
"redirect_uris": [
"http://127.0.0.1:5556/callback"
],
"response_types": [
"code"
],
"scope": "openid offline",
"subject_type": "pairwise",
"token_endpoint_auth_method": "client_secret_basic",
"userinfo_signed_response_alg": "none"
}
Redirect URL isn't whitelisted
A likely cause of your request failing is that you are using the wrong redirect URL. Assuming your OAuth 2.0 URL looks like
http://ory-hydra/oauth2/auth?client_id=my-client&...&redirect_uri=http://my-url/callback
The redirect URL http://my-url/callback
must be whitelisted in your client configuration. The URLs must match. URL
http://my-url/callback
and http://my-url/callback?foo=bar
are different URLs!
To see the whitelisted redirect_uris, check the client:
hydra clients get --endpoint http://ory-hydra <the-client-id>
{
// ...
"redirect_uris": [
"http://127.0.0.1:5556/callback"
],
// ...
}
Here you see that http://my-url/callback
isn't in the list, which is why the request fails.
oauth2/token endpoint fails for jwks based client
When trying to get an access token for a client registered with "token_endpoint_auth_method": "private_key_jwt"
it's possible
that the provided jwt has expired.
The response body that's sent to the client is like below
{
"error": "error",
"error_description": "The error is unrecognizable Token is expired"
}
The debug error messages isn't provided to avoid divulging more information to a malicious client.
However if you need more information in response (for debugging) , you can enable the following environment variables in hydra server :
OAUTH2_EXPOSE_INTERNAL_ERRORS=true;
OAUTH2_INCLUDE_LEGACY_ERROR_FIELDS=true
This configuration are documented here.
Now you will be able to see the error_debug field in the response like below :
{
"error": "error",
"error_description": "The error is unrecognizable",
"status_code": 500,
"error_debug": "Token is expired"
}