Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to get Google provider ID token and not access token #393

Closed
1 of 5 tasks
vladfulgeanu opened this issue Jul 6, 2020 · 15 comments · Fixed by #1024
Closed
1 of 5 tasks

How to get Google provider ID token and not access token #393

vladfulgeanu opened this issue Jul 6, 2020 · 15 comments · Fixed by #1024
Labels
question Ask how to do something or how something works

Comments

@vladfulgeanu
Copy link

vladfulgeanu commented Jul 6, 2020

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'
}
  • Found the documentation helpful
  • Found documentation but was incomplete
  • Could not find relevant documentation
  • Found the example project helpful
  • Did not find the example project helpful
@vladfulgeanu vladfulgeanu added the question Ask how to do something or how something works label Jul 6, 2020
@vladfulgeanu vladfulgeanu changed the title How to get Google provider token id and not access token How to get Google provider ID token and not access token Jul 6, 2020
@iaincollins
Copy link
Member

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

@vladfulgeanu
Copy link
Author

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.

@iaincollins
Copy link
Member

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.

@vladfulgeanu
Copy link
Author

I did try exactly this as I saw it possible on the Okta provider, but 2 things happen:

  • I get this error:
[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

  • I do get properties of the ID token in the signin callback (iss, sub, iat, exp...), but what I need is the exact ID token string that encodes all these. Is there a method to go from the ID token object, with the iss, sub, iat, exp properties to the ID token string, like base 64 encoding? Best thing would be to be able to access the ID token string directly though.

@iaincollins
Copy link
Member

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.

@Dreched
Copy link

Dreched commented Dec 1, 2020

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.

@MaryJJ
Copy link

MaryJJ commented Dec 2, 2020

I need this too, thanks

@theapplefolks
Copy link

Yeah, any updates? I also really need this.

@balazsorban44
Copy link
Member

balazsorban44 commented Dec 5, 2020

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.

@Dreched
Copy link

Dreched commented Dec 6, 2020

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.

I think #837 will help. To clarify, /api/auth/session will also get id_token set from signIn?

@balazsorban44
Copy link
Member

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

@fedeberon
Copy link

fedeberon commented Dec 11, 2020

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;

}

@balazsorban44
Copy link
Member

balazsorban44 commented Dec 12, 2020

@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. 😔

@github-actions
Copy link

github-actions bot commented Jan 1, 2021

🎉 This issue has been resolved in version 3.2.0-canary.10 🎉

The release is available on:

Your semantic-release bot 📦🚀

@github-actions
Copy link

github-actions bot commented Feb 1, 2021

🎉 This issue has been resolved in version 3.3.0-canary.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Ask how to do something or how something works
Projects
None yet
7 participants