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"
}