Undefined refresh token

Hello,

I can’t get a refresh token. It returns undefined.

Thank you!

import NextAuth from 'next-auth'
import OktaProvider from 'next-auth/providers/okta'
import axios from 'axios'


/**
 * Takes a token, and returns a new token with updated
 * `accessToken` and `accessTokenExpires`. If an error occurs,
 * returns the old token and an error property
 */
async function refreshAccessToken(token) {
  try {
    const OKTA_ISSUER = process.env.OKTA_ISSUER
    const url = new URL(`${OKTA_ISSUER}/v1/token`)
    url.searchParams.set('client_id', process.env.OKTA_CLIENT_ID)
    url.searchParams.set('client_secret', process.env.OKTA_CLIENT_SECRET)
    url.searchParams.set('grant_type', 'refresh_token')
    url.searchParams.set('refresh_token', token.refreshToken)

    const response = await fetch(url, {
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Cache-Control': 'no-cache',
        'Authorization': `Bearer ${token.id}`
      },
      method: 'POST'
    })

    const refreshedTokens = await response.json()

    if (!response.ok) {
      throw refreshedTokens
    }

    return {
      ...token,
      accessToken: refreshedTokens.access_token,
      accessTokenExpires: Date.now() + refreshedTokens.expires_at * 1000,
      refreshToken: refreshedTokens.refresh_token ?? token.refreshToken // Fall back to old refresh token
    }
  } catch (error) {
    console.log(error)

    return {
      ...token,
      error: 'RefreshAccessTokenError'
    }
  }
}

export const authOptions ={
  // Configure one or more authentication providers
  providers: [
    OktaProvider({
      clientId: process.env.OKTA_CLIENT_ID,
      clientSecret: process.env.OKTA_CLIENT_SECRET,
      issuer: process.env.OKTA_ISSUER
    })
    // ...add more providers here
  ],
  callbacks: {
    async session({ session, token }) {
      session.id = token.id
      session.user = token.user
      // Add header to axios.
      axios.defaults.headers.common.Authorization = `Bearer ${token.id}`
      return session
    },
    async jwt({ token, user, account }) {
      // Initial sign in
      if (account && user) {
        token.id = account.id_token 
        return {
          id: account.id_token,
          accessToken: account.access_token,
          accessTokenExpires: Date.now() + account.expires_at * 1000,
          refreshToken: account.refresh_token,
          user
        }
      }
      
      // Return previous token if the access token has not expired yet
      if (Date.now() < token.accessTokenExpires) {
        return token
      }

      // Access token has expired, try to update it
      return refreshAccessToken(token)
    }
  },
  jwt: {
    encryption: false
  }
}

export default NextAuth(authOptions)

Should I need to pass the scope parameters as params to get refresh token?

scope=offline_access openid profile

Yup, you need to add the offline_access scope to your /authorize request to get a refresh token back, but also double check that the app is configured to support the “Refresh token” grant type, otherwise you won’t get one back even if you request it.

1 Like

Thank you @andrea I have already done that and I am now able to get refresh tokens.

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.