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

Not getting the ID token, only the access token from Okta #378

Closed
eatrocks opened this issue Jul 1, 2020 · 13 comments · Fixed by #1024
Closed

Not getting the ID token, only the access token from Okta #378

eatrocks opened this issue Jul 1, 2020 · 13 comments · Fixed by #1024
Labels
question Ask how to do something or how something works

Comments

@eatrocks
Copy link

eatrocks commented Jul 1, 2020

Should I be able to get the ID token when using Okta?

I have a working project using Okta. I am requesting the following scopes in my [...nextauth].js file...
scope: "openid profile email offline_access"

The Okta docs indicate the id_token is included in the response from /v1/token if the "openid" scope was requested.

console output of "message" in session Event...

{
  session: {
    user: {
      name: 'Bruce',
      email: 'bruce@redacted',
      image: null
    },
    expires: '2020-07-30T21:12:10.158Z'
  },
  jwt: {
    user: { name: 'Bruce', email: 'bruce@redacted' },
    account: {
      provider: 'okta',
      type: 'oauth',
      id: '00ubk926sxN1qb8ZW4x6',
      refreshToken: 'IjQMrKDYYgtuIIxssqrnT_ZuHEYHNZXY_uyZIOjOp7U',
      accessToken: 'redacted',
      accessTokenExpires: null
    }
  }
}

The access token decodes to

{
  "ver": 1,
  "jti": "AT.l1a5pxB-uVn5FpbUGG_Mo0OUF7ySZQNu361JKsnu5qE.m/3Vy0DhG5LJKBRVs/SLm18+v8jnsNOC1iTxwTJLCUo=",
  "iss": "https://dev-726851.okta.com",
  "aud": "https://dev-726851.okta.com",
  "sub": "bruce@redacted",
  "iat": 1593551529,
  "exp": 1593555129,
  "cid": "0oac1u4f77TZisppR4x6",
  "uid": "00ubk926sxN1qb8ZW4x6",
  "scp": [
    "openid",
    "profile",
    "email",
    "offline_access"
  ]
}

@eatrocks eatrocks added the question Ask how to do something or how something works label Jul 1, 2020
@iaincollins
Copy link
Member

iaincollins commented Jul 3, 2020

The name and email fields should be mapped to the user object, if they are present (it looks like that is working).

The only way to access additional properties is if using JSON Web Tokens (in the JWT callback) or from the Sign In callback.

If you are using JWT sessions you should be able access the full profile object on sign in via the JWT callback, you can copy objects over from the profile to the JWT to persist them when it the callback is invoked on sign in.

If you are using database sessions, then you should be able to grab the profile in the Sign In callback, but you'd have to write some code to handle care of saving it to a database table somewhere, as it's not persisted by default.

(It is possible to use custom models to persist the info in a database with NextAuth.js but we don't have a guide for that yet!)

@erik617
Copy link

erik617 commented Sep 4, 2020

Hello, I was curious if there is a reason why the id_token isn't exposed directly? It would be nice to be able to pass it around to other services if needed.

@iaincollins
Copy link
Member

Hi there!

Essentially we try to be as compatible with as wide range of providers as possible so the design is generally starts off by reflecting the flow of the majority of providers, and is refined as we add more providers that share similar behaviour (as there is no single spec to follow, but rather a range of specifications, including Open ID which attempts so solve that problem by codifying more of it).

Open ID token support is an example of something we implemented in a way to fit in with the majority of existing providers work, so it's sort of wrangled into the profile model used by other OAuth services.

I think we will probably move towards trying to make available as it's started to come up in discussions that folks would like to be able to pass the signed JWT that comes back from the provider to other services.

We could add another option to the callbacks and return the raw JWT response the same way we do for providers, and/or we could persist it in the database, along with other provider specific information. We could also provide an endpoint where it can be extracted from (which might in turn require a database, depending on how individual providers work).

To make a call on that I think we'll probably want to take a look at the Open ID spec and then see how providers that use it implement it in practice to find common ground.

@erik617
Copy link

erik617 commented Sep 9, 2020

@iaincollins thanks for the reply!

Personally, I like your suggestion of adding the option to the callbacks to return the raw JWT response for the id_token, which would work well for our use case and would give clients flexibility to do what they want with the token (whether pass it around, save in database, etc.)

@roErlend
Copy link

Any updates on this?

@stale
Copy link

stale bot commented Dec 5, 2020

Hi there! It looks like this issue hasn't had any activity for a while. It will be closed if no further activity occurs. If you think your issue is still relevant, feel free to comment on it to keep ot open. Thanks!

@stale stale bot added the stale Did not receive any activity for 60 days label Dec 5, 2020
@jayhoogle
Copy link

Hi @erik617, did you ever manage to expose your id_token? I'm trying to do the same thing but unable to see how I can get that raw data.

@stale stale bot removed the stale Did not receive any activity for 60 days label Dec 8, 2020
@balazsorban44
Copy link
Member

I think #837 would do what you need.

@jayhoogle
Copy link

jayhoogle commented Dec 8, 2020

I think #837 would do what you need.

@balazsorban44 You're right - it's exactly what I need!

@liuxiaofeng1981
Copy link

I also want to get the idToken using jwt callback.

callbacks: {
  jwt: async (token, user, account, profile, isNewUser) => {
    const isSignIn = !!user
    if (isSignIn) {
      console.log('================= user =============', user)
      console.log('================= account =============', account)
      console.log('================= profile =============', profile)
    } else {
      console.log('JWT callback after sign in', token)
    }
    return Promise.resolve(token)
  },
},

I can see profile contains the id. But how do I get the actual JWT idToken?

{
  at_hash: 'xxxxxxxxxxx',
  sub: '39xxx0xxx41b1-3450xxc7-xxxx1c4xxx3af',
  aud: 'xxxxxxxxxxxx',
  email_verified: true,
   event_id: 'xxxxxxxxxxxxx',
   token_use: 'id',
   auth_time: 1607926540,
   iss: 'https://cognito-idp.xxxxxx.amazonaws.com/xxxxx_dfasfaFaafe',
   'cognito:username': 'myusername',
   exp: 1607930140,
   iat: 1607926540,
   email: '[email protected]'
}

My provider setup:

providers: [
      Providers.Cognito({
        clientId: process.env.COGNITO_CLIENT_ID ?? '',
        clientSecret: process.env.COGNITO_CLIENT_SECRET ?? '',
        domain: process.env.COGNITO_DOMAIN ?? '',
        idToken: true,
      }),
    ]

@ryangittings
Copy link

+1, same issue for me too. Need access to id_token for Sign in with Apple! :)

@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
8 participants