id_token detected in the response, you must use client.callback() instead of client.oauthCallback()
See original GitHub issueProvider type
Custom provider
Environment
System:
OS: Windows 10 10.0.22000
CPU: (16) x64 AMD Ryzen 7 5800X 8-Core Processor
Memory: 15.52 GB / 31.95 GB
Binaries:
Node: 16.15.0 - ~\scoop\apps\nodejs-lts\current\node.EXE
Yarn: 1.22.18 - ~\Development\project\node_modules\.bin\yarn.CMD
npm: 8.5.5 - ~\scoop\apps\nodejs-lts\current\npm.CMD
Browsers:
Edge: Spartan (44.22000.120.0), Chromium (101.0.1210.39)
Internet Explorer: 11.0.22000.120
npmPackages:
next: 12.1.4 => 12.1.4
next-auth: ^4.3.1 => 4.3.1
react: 18.0.0 => 18.0.0
Reproduction URL
https://github.com/buehler/next-auth-issue-id-token
Describe the issue
When using an OIDC compliant identity provider, the custom provider configuration does not act according to the specification. If configured with idToken: false
, the provider - if compliant to the standard - will nevertheless return an id token. This because of the fact that the returned information from the user-info endpoint MUST be validated against said ID token (the sub, to be specific).
As can be seen in: https://openid.net/specs/openid-connect-core-1_0.html#TokenResponse The return value of a successful token response MUST contain an id token.
The reason is stated here: https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse
NOTE: Due to the possibility of token substitution attacks (see Section 16.11),
the UserInfo Response is not guaranteed to be about the End-User identified by the
sub (subject) element of the ID Token. The sub Claim in the UserInfo Response MUST
be verified to exactly match the sub Claim in the ID Token; if they do not match,
the UserInfo Response values MUST NOT be used.
Currently, the client.oauthCallback
function does throw an error that it has detected an id token and therefore the client.callback shall be used.
This is (in my opinion) a security issue.
How to reproduce
edit: the reproduction url contains a pre configured next-auth-example
Create a simple next auth application and use a custom provider. I used “zitadel” (zitadel.ch) as my identity provider since it is OIDC certified and adheres strongly to the specification.
Then, use the following configuration:
const provider = {
id: 'zitadel',
name: 'zitadel',
type: 'oauth',
version: '2',
wellKnown: 'https://issuer.zitadel.ch',
authorization: {
params: {
scope: 'openid email profile',
},
},
idToken: false,
checks: ['pkce', 'state'],
client: {
token_endpoint_auth_method: 'none',
},
clientId: '160657439937654201@for_next_auth_issues',
};
The configured return url is: http://localhost:3000/api/auth/callback/zitadel
(for the next app).
With this configuration, the following error is thrown:
[next-auth][error][OAUTH_CALLBACK_ERROR]
https://next-auth.js.org/errors#oauth_callback_error id_token detected in the response, you must use client.callback() instead of client.oauthCallback() {
error: {
message: 'id_token detected in the response, you must use client.callback() instead of client.oauthCallback()',
stack: 'RPError: id_token detected in the response, you must use client.callback() instead of client.oauthCallback()\n' +
' at Client.oauthCallback\n' +
' at processTicksAndRejections\n' +
' at async oAuthCallback\n' +
' at async Object.callback\n' +
' at async NextAuthHandler\n' +
' at async NextAuthNextHandler\n'
name: 'RPError'
},
providerId: 'zitadel',
message: 'id_token detected in the response, you must use client.callback() instead of client.oauthCallback()'
}
Expected behavior
First of all, the callback must not throw this error because the response is actually compliant with the OIDC standard (in https://openid.net/specs/openid-connect-core-1_0.html#TokenResponse). Additionally, the sub in the delivered ID token must be stored and when calling the user info endpoint to fetch the profile, the stored sub must be checked against the delivered sub by the endpoint. If they do not match, then it’s save to throw an error or something (as stated in https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse).
Debatably, one could argue that an error must be thrown, if NO id token is returned in the token response, since that is not compliant and does not allow the check for the sub on the user info endpoint.
Issue Analytics
- State:
- Created a year ago
- Reactions:3
- Comments:5 (1 by maintainers)
You are forcing the OAuth 2 flow with
idToken: true
, while also passing theopenid
scope. Removing that scope should resolve your issue.FYI @balazsorban44: When using the suggested settings, with the removed openid scope and idtoken: false, the following error occurs: