从NextAuth Okta提供程序获取刷新令牌

zz2j4svz  于 2023-06-29  发布在  其他
关注(0)|答案(2)|浏览(126)

我们有一个现有的应用程序使用NextAuth与Okta通信。这一切都很好,我们刚刚添加了一个需要Okta访问令牌的API,我们在NextAuth中使用了JWT回调来从帐户对象中获取访问令牌,并将其添加到NextAuth会话中。
这一切工作正常,我们可以从会话中获取访问令牌并将其传递给API,一切正常,API验证访问令牌,一切正常。但是,我们有时会回到会话,对API的调用失败,因为它无法验证访问令牌,因为它已经过期。
我正在查看rotating a refresh token的NextAuth文档,我看到Okta有一个获取新刷新令牌的端点。这一切似乎都有道理,问题是,看看NextAuth中的JWT回调返回的内容,我没有得到刷新令牌,这些是Okta提供程序返回的 prop 。我们得到了一个访问令牌和一个ID令牌(它们确实包含不同的值),但我们没有得到返回的刷新令牌。
我看到关于刷新令牌的offline_access范围的引用,我们需要在对Okta提供程序的调用中设置这个吗?如果是,如何进行?否则,是否有人设法在NextAuth中使用Okta提供程序并修复了过期的访问令牌问题?

{
  token: {
    name: ...,
    email: ...,
    picture: .,
    sub: ...
  },
  user: {
    id: ..,
    name: ...,
    email: ...,
    image: undefined
  },
  account: {
    provider: 'okta',
    type: 'oauth',
    providerAccountId: ...,
    token_type: 'Bearer',
    expires_at: ...,
    access_token: ...,
    scope: ...,
    id_token: ...
  },
  profile: {
    sub: ...,
    name: ...,
    email: ...,
    ver: ...,
    iss: ...,
    aud: ...,
    iat: ...,
    exp: ...,
    jti: ...,
    amr: [ ... ],
    idp: ...,
    preferred_username: ...,
    auth_time: ...,
    at_hash: ...
  },
  isNewUser: undefined
}
1u4esq0p

1u4esq0p1#

您可以添加如下所示的范围'

OktaProvider({
  clientId: process.env.OKTA_CLIENT_ID,
  clientSecret: process.env.OKTA_CLIENT_SECRET,
  issuer: process.env.OKTA_ISSUER,
  idToken: true,
  exp: true,
  authorization: { 
    params: { 
      scope: "openid offline_access" 
    } 
  }
})
dgsult0t

dgsult0t2#

首先,谢谢!我使用Appu Rajendran提供的代码片段实现了这一点,但我想添加逻辑,我还必须将其写入jwt回调,以便在获得刷新令牌后刷新访问令牌。

async jwt({ token, account }: any) {
if (account) {
    token.accessToken = account.access_token;
    token.idToken = account.id_token;
    token.oktaId = account.providerAccountId;
    token.refreshToken = account.refresh_token;
}

var tokenParsed = JSON.parse(Buffer.from(token.idToken.split('.')[1], 'base64').toString());
const dateNowInSeconds = new Date().getTime() / 1000
const tokenIsNotExpired = dateNowInSeconds < tokenParsed.exp;
if (tokenIsNotExpired) {
    return token;
} else {
    const url = `${process.env.OKTA_DOMAIN}/v1/token`;
    const body = `grant_type=refresh_token&client_id=${process.env.OKTA_CLIENTID}&client_secret=${process.env.OKTA_CLIENTSECRET}&refresh_token=${token.refreshToken}`;
    const headers = {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Accept': 'application/json'
    };
    const response = await fetch(url, { method: 'POST', body, headers });
    const data = await response.json();
    if (data.error) {
        throw new Error("Unable to refresh token");
    }
    token.accessToken = data.access_token;
    token.idToken = data.id_token;
    token.oktaId = data.providerAccountId;
    token.refreshToken = data.refresh_token;

    return token;
}

},
我写了一篇完整的文章来解释这些步骤:https://thetombomb.com/posts/next-okta-refresh-token。本文还包括有关scope属性的更多信息。

相关问题