Provider logic does not correctly adhere to the specification
See original GitHub issueEnvironment
mentioned in https://github.com/nextauthjs/next-auth/issues/4543
Reproduction URL
https://github.com/nextauthjs/next-auth/issues/4543
Describe the issue
Based on https://github.com/nextauthjs/next-auth/issues/4543, next auth does not correctly act according to the specification. When using the provided configuration in the mentioned issue, the mentioned error occurs. This does not comply with the OIDC specification. It does comply with the oauth2 authorization code flow (RFC6749), but not with the OIDC spec. Since OAuth has no userinfo endpoint, the OIDC spec defines that the returned id_token (which is required) contains the correct “sub” of a user. When then querying the user info endpoint for the profile, the sub MUST be verified. Otherwise, the content of the userinfo endpoint MUST NOT be used.
Currently, next auth throws an error.
As suggested in the issue by @balazsorban44: when using idToken:false
and removing the openid
scope, the whole provider and configuration does not adhere to the OIDC spec anymore. When using the suggested config, the following error is returned (by an IDP that adheres to the spec):
[next-auth][error][OAUTH_CALLBACK_ERROR]
https://next-auth.js.org/errors#oauth_callback_error invalid_scope {message: 'invalid_scope', stack: 'Error: invalid_scope
at oAuthCallback (C:…dules\next\dist\server\base-server.js:477:37)', name: 'Error'}
How to reproduce
described in https://github.com/nextauthjs/next-auth/issues/4543
Expected behavior
Mentioned in https://github.com/nextauthjs/next-auth/issues/4543. I’d expect the behavior to be according to the specification. The lib must not throw an error when an ID token is present (when using the openid scope) and idToken: false
is set.
I would like a constructive discussion about this topic because I think in #4543, there has been a misunderstanding.
This does not only diminish the usability and versatility of this library, but also introduces a security issue. There is an attack vector by token substitution when not verifying the sub in the id token. (source: 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.)
Issue Analytics
- State:
- Created a year ago
- Reactions:5
- Comments:9 (3 by maintainers)
By setting
idToken: false
(which, granted, could be named better) a standard OAuth 2.0 flow without OpenID Connect is expected. Of course then requesting theopenid
scope and expecting pure OAuth 2.0 flow will throw because it now receives an unexpected ID Token.By setting
idToken: true
an OIDC Authorization Code flow is used. Meaning that ID Token is required to be returned and all defined checks are present. Even comparing theID Token
sub
claim with the one returned by the userinfo endpoint.All required checks are present, the exhibited client behaviours are conform to the OIDC specification. If you use an openid connect flow, then
idToken: true
must be used so that all those OpenID specific checks can be made. If that still fails, it’s because the Identity Provider is not exhibiting conform behaviours, which is what I’m seeing here (use of 1024 bit RSA keys). That goes against the very core JSON Web Algorithm definition and will also be rejected for a very good reason.Furthermore token substitution is not a vector here because Authorization Code flow is used and TLS is used during the code<>access token exchange which is also the only time the “userinfo” (which may be the OIDC userinfo_endpoint when idToken: true, but any arbitrary endpoint when idToken:false) is queried. There is place to substitute an access token anyway.
I understand your frustration but I am not seeing errors in the client-side behaviour.
The only issue I see are weak RSA 1024 bit keys which are correctly rejected.
I cannot see your code, but if the
id_token
does not contain the information you need, you could override theuserinfo
request handler as described in the docs: https://next-auth.js.org/configuration/providers/oauth#userinfo-option and make an extra request to whatever endpoint.I agree that
idToken: boolean
did not make much sense here, and I plan to remove it, as detecting the presence of theopenid
scope should probably be enough now, and we are doing it already anyway. https://github.com/nextauthjs/next-auth/pull/3514