When using the Google provider I want to be able to authenticate with a backend server and for this I need to send the ID token to that API and get back the access token. Further info about this flow can be found here.
This extra request I plan to do in the JWT callback, but in there I cannot access ID token. Only accessToken is given back in token.account.
This is what I get in the JWT callback:
token (first argument):
{
user: {
name: <name>,
email: <email>,
image: <image>
},
account: {
provider: 'google',
type: 'oauth',
id: <id>,
refreshToken: undefined,
accessToken: <accessToken>,
accessTokenExpires: null
},
isNewUser: undefined
}
profile (second argument):
{
id: <id>,
email: <email>,
verified_email: true,
name: <name>,
given_name: <given_name>,
family_name: <family_name>,
picture: <picture>,
locale: 'en'
}
Yeah Google is unusual and this has come up before, we should really cover this in the docs.
tl;dr Google only returns a RefreshToken on first sign in and should to be used with a database. You can force it to issue a new one every time using access_type=offline and prompt=consent but that is intended for mobile and desktop applications and changes the sort of prompt a user sees when they sign in (and isn't as seamless).
More info in #269
If I were to use react-google-login library, _in the responseGoogle(response) {...} callback function, I should get back a standard JWT located at response.tokenId or res.getAuthResponse().id_token_ (from here)
That is the only thing that I need in order to send the request to the backend server. I'm not sure how RefreshToken can help me in this case.
You can try setting idToken: true as a provider option - it works on quite a few providers, but I'm not sure about Google - and then using the JWT callback (assuming you are using JSON Web Tokens) to handle saving data from the profile in your JWT to use in subsequent calls.
I did try exactly this as I saw it possible on the Okta provider, but 2 things happen:
[next-auth][error][OAUTH_CALLBACK_HANDLER_ERROR] [
Error: Missing or invalid provider account
at /home/vlad/work/node_modules/next-auth/dist/server/lib/callback-handler.js:32:15
at Generator.next (<anonymous>)
at asyncGeneratorStep (/home/vlad/work/node_modules/next-auth/dist/server/lib/callback-handler.js:20:103)
at _next (/home/vlad/work/node_modules/next-auth/dist/server/lib/callback-handler.js:22:194)
at /home/vlad/work/node_modules/next-auth/dist/server/lib/callback-handler.js:22:364
at new Promise (<anonymous>)
at /home/vlad/work/node_modules/next-auth/dist/server/lib/callback-handler.js:22:97
at /home/vlad/work/node_modules/next-auth/dist/server/lib/callback-handler.js:185:17
at /home/vlad/work/node_modules/next-auth/dist/server/routes/callback.js:91:54
at Generator.next (<anonymous>)
at asyncGeneratorStep (/home/vlad/work/node_modules/next-auth/dist/server/routes/callback.js:26:103)
at _next (/home/vlad/work/node_modules/next-auth/dist/server/routes/callback.js:28:194)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
]
The JWT callback is not reached in this case, only the signin callback
Thanks for trying that and reporting what you saw.
I think at the moment the answer is this is not possible, but it seems like a reasonable feature request.
Any update on this?
The Google provider isn't really complete without it since most front ends will be calling services that need to verify a user's id_token.
I need this too, thanks
Yeah, any updates? I also really need this.
So if I understand correctly, #837 would help here, right? Can anyone confirm this? (@vladfulgeanu @Dreched @MaryJJ @theapplefolks)
It basically sends the id_token to the jwt callback if it is provided by the IdP at sign-in.
So if I understand correctly, #837 would help here, right? Can anyone confirm this? (@vladfulgeanu @Dreched @MaryJJ @theapplefolks)
It basically sends the
id_tokento thejwtcallback if it is provided by the IdP at sign-in.
I think #837 will help. To clarify, /api/auth/session will also get id_token set from signIn?
What ends up in your session is up to you. If you want the id_token available in your session, you can look at the jwt and聽session callbacks: https://next-auth.js.org/configuration/callbacks
const getIdToken = async (refreshToken) => {
var requestOptions = {
method: 'POST',
redirect: 'follow'
};
const response = await fetch(`https://oauth2.googleapis.com/token?refresh_token=${refreshToken}&client_id=955818486406-snr4kuu25v16keu169sc1kbm6ofv7lfj.apps.googleusercontent.com&client_secret=yBPnCGw81u_OEHCRHLX8tbO4&grant_type=refresh_token&Content-Type=application/x-www-form-urlencoded`, requestOptions);
let result= await response.json();
return result.id_token;
}
@fedeberon so when using a refresh token, you will actually receive a new ID token as well? It never occurred to me, I'll check this out, thanks!
Update:
Hmm a quick search in the OIDC spec: https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokenResponse
It says
Upon successful validation of the Refresh Token, the response body is the Token Response of聽Section聽3.1.3.3聽except that it might not contain an聽id_token.
So getting an id_token is not given. 馃様
Most helpful comment
Yeah Google is unusual and this has come up before, we should really cover this in the docs.
tl;dr Google only returns a
RefreshTokenon first sign in and should to be used with a database. You can force it to issue a new one every time usingaccess_type=offlineandprompt=consentbut that is intended for mobile and desktop applications and changes the sort of prompt a user sees when they sign in (and isn't as seamless).More info in #269