Next-auth: Not getting the ID token, only the access token from Okta

Created on 1 Jul 2020  路  10Comments  路  Source: nextauthjs/next-auth

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"
  ]
}

question

All 10 comments

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!)

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.

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.

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

Any updates on this?

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!

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.

I think #837 would do what you need.

I think #837 would do what you need.

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

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,
      }),
    ]
Was this page helpful?
0 / 5 - 0 ratings

Related issues

ghoshnirmalya picture ghoshnirmalya  路  3Comments

ryanditjia picture ryanditjia  路  3Comments

eatrocks picture eatrocks  路  3Comments

iaincollins picture iaincollins  路  3Comments

iaincollins picture iaincollins  路  3Comments