如何在 AWS amplify-js 中处理刷新令牌服务
Posted
技术标签:
【中文标题】如何在 AWS amplify-js 中处理刷新令牌服务【英文标题】:how handle refresh token service in AWS amplify-js 【发布时间】:2019-04-21 20:31:33 【问题描述】:在我的 react 项目中,我使用 AWS Cognito 用户池进行用户管理,对于用户身份验证,我使用 AWS Cognito idToken。 90 分钟后会话将过期,然后我需要用新的 idToken 刷新。如何使用 amplify-js 在 AWS Cognito 中处理刷新令牌服务。我试过Auth.currentSession()
我会每1小时打电话一次,但它对我不起作用。
【问题讨论】:
【参考方案1】:致电Auth.currentSession()
应该可以解决您的问题。 Amplify-js 将刷新逻辑从您身上抽象出来。
在后台currentSession()
获取CognitoUser
对象,并调用其名为getSession()
的类方法。正是这种方法,它执行以下操作:
-
从您的存储中获取
idToken
、accessToken
、refreshToken
和clockDrift
。
验证令牌(即 idToken 和 accessToken)以查看它们是否已过期。
如果令牌有效,则返回当前会话。
如果令牌已过期,请调用 CognitoUser
类的 refreshSession()
方法,该方法与 AWS 身份提供程序通信以生成一组新令牌。
你现在要做的就是:
-
确保定期致电
Auth.currentSession()
请始终致电 Auth.currentSession()
以获取您发出的每个 http 请求的令牌。
你可以使用这样的包装器:
const getAccessJwtToken = async () =>
// Auth.currentSession() checks if token is expired and refreshes with Cognito if needed automatically
const session = await Auth.currentSession();
return session.getAccessToken().getJwtToken();
;
最后,这个github 讨论还介绍了一种非常好的手动刷新令牌的方法,并介绍了您应该探索该选项的用例。
【讨论】:
我认为应该是 getIdToken() 因为 getAccessToken() 对我们不起作用。【参考方案2】:经过长时间的努力,我找到了更新 AWS Cognito 刷新令牌的解决方案,为此我使用了amazon-cognito-identity-js
const AmazonCognitoIdentity = require('amazon-cognito-identity-js');
const CognitoUserPool = AmazonCognitoIdentity.CognitoUserPool;
componentWillReceiveProps(nextProps)
let getIdToken = localStorage.getItem('idToken');
if(getIdToken !== null)
let newDateTime = new Date().getTime()/1000;
const newTime = Math.trunc(newDateTime);
const splitToken = getIdToken.split(".");
const decodeToken = atob(splitToken[1]);
const tokenObj = JSON.parse(decodeToken);
const newTimeMin = ((newTime) + (5 * 60)); //adding 5min faster from current time
//console.log(newTimeMin, tokenObj.exp)
if(newTimeMin > tokenObj.exp)
this.tokenRefresh();
console.log('token updated');
更新令牌方法
tokenRefresh()
const poolData =
UserPoolId : // Your user pool id here,
ClientId : // Your client id here
;
const userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
const cognitoUser = userPool.getCurrentUser();
cognitoUser.getSession((err, session) =>
const refresh_token = session.getRefreshToken();
cognitoUser.refreshSession(refresh_token, (refErr, refSession) =>
if (refErr)
throw refErr;
else
//this provide new accessToken, IdToken, refreshToken
// you can add you code here once you get new accessToken, IdToken, refreshToken
);
)
【讨论】:
【参考方案3】:只要会话处于活动状态(即用户正在进行 api 调用等),Amplify 就会自动保持会话新鲜。
如果您想强制会话保持活跃,即使他们没有积极使用您的 API,那么最简单的做法是定期调用 Auth.currentAuthenticatedUser()
。
【讨论】:
感谢您的重播,对于自动更新,我需要在我的用户池设置中启用任何选项吗?我尝试使用amazon-cognito-identity-js
来做到这一点,但这对我也不起作用
否 - 如果访问令牌超时(一小时后发生),Amplify 会自动尝试刷新。请注意,您在 Cognito 用户池控制台(常规设置 > 应用程序客户端 > 刷新令牌过期(天))中配置 刷新令牌到期 - 这是用户无需执行的最长时间重新登录。
Amplify 已经修复了这个问题,Auth.currentAuthenticatedUser()
不会自动刷新会话(可能是因为这是一个昂贵的调用)。您将需要执行类似于@techie18 解决方案的操作来手动强制刷新(即不要等待 1 小时)。基本上,您必须获取当前会话的刷新令牌,然后将其传递给 refreshSession
。
您对此有多大把握,考虑到文档中的这一点:aws-amplify.github.io/docs/js/…“使用 AWS Amplify 进行身份验证时,您无需手动刷新 Amazon Cognito 令牌。令牌会自动刷新必要时到图书馆。”代码中的这个条件:github.com/aws-amplify/amplify-js/blob/master/packages/auth/src/…
免责声明:不是放大专家,但必须使用 refreshSession。我们的应用程序中有一个自定义用例,我们需要强制刷新令牌,以便应用程序的状态知道后端的变化。我们依靠调用 currentAuthenticatedUser
直到几天前才刷新令牌,但是由于 accessToken jwt 保持不变,这种情况不再发生。只有当我们使用 refreshSession 时它才再次起作用。此外,不清楚“必要时”是什么意思。【参考方案4】:
这会给你一个 AccessToken 和一个 idToken。
fetch("https://cognito-idp.<cognito-user-pool-region>.amazonaws.com/",
headers:
"X-Amz-Target": "AWSCognitoIdentityProviderService.InitiateAuth",
"Content-Type": "application/x-amz-json-1.1",
,
mode: 'cors',
cache: 'no-cache',
method: 'POST',
body: JSON.stringify(
ClientId: "<cognito-user-pool-client-id>",
AuthFlow: 'REFRESH_TOKEN_AUTH',
AuthParameters:
REFRESH_TOKEN: "<cognito-refresh-toke>",
//SECRET_HASH: "your_secret", // In case you have configured client secret
),
).then((res) =>
return res.json(); // this will give jwt id and access tokens
);
【讨论】:
【参考方案5】:我使用了 'amazon-cognito-identity-js' 并在令牌每次过期时刷新它,它解决了我的问题,这里是棘手的 getJwtToken 部分的代码 sn-p:
getJwtToken()
if (!this.activeUser)
return null;
const signInUserSession = this.activeUser.getSignInUserSession();
const idToken = signInUserSession ? signInUserSession.getIdToken() : null;
if (!idToken || idToken.getExpiration() * 1000 <= Date.now())
if (!signInUserSession.isValid())
const refreshToken = signInUserSession.getRefreshToken();
return new Promise((resolve) =>
this.activeUser.refreshSession(refreshToken, (err, session) =>
if (err)
resolve(this.logout());
this.activeUser.setSignInUserSession(session);
resolve(session.getIdToken().getJwtToken());
)
);
return Promise.resolve(idToken.getJwtToken());
return Promise.resolve(idToken.getJwtToken());
【讨论】:
你必须添加所有代码,你有这个变量“this.activeUser”不是代码的一部分,你没有解释如何解决这个问题。以上是关于如何在 AWS amplify-js 中处理刷新令牌服务的主要内容,如果未能解决你的问题,请参考以下文章