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



我们有一个现有的应用程序使用NextAuth与Okta通信。这一切都很好,我们刚刚添加了一个需要Okta访问令牌的API,我们使用NextAuth中的JWT回调从帐户对象中获取访问令牌,并将其添加到NextAAuth会话中。

这一切都很好,我们可以从会话中获取访问令牌,并将其传递给API,一切都很顺利,API验证访问令牌,一切都好。但是,我们有时会回到会话,对API的调用失败,因为它无法验证访问令牌,因为它已过期。

我正在查看NextAuth文档中关于轮换刷新令牌的内容,我发现Okta有一个获得新刷新令牌的终点。这一切似乎都有道理,问题是,看看NextAuth中的JWT回调返回了什么,我没有得到刷新令牌,这些是Okta提供者返回的道具。我们得到了一个访问令牌和一个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
}

您可以添加如下范围的

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

首先,谢谢!我使用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属性的更多信息。

最新更新