如何在 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() 的类方法。正是这种方法,它执行以下操作:

    从您的存储中获取idTokenaccessTokenrefreshTokenclockDrift。 验证令牌(即 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 中处理刷新令牌服务的主要内容,如果未能解决你的问题,请参考以下文章

AWS中的加速传输功能可放大存储以进行响应

如何在 AWS 中刷新 VPC 中的 DNS 条目?

如何从 AWS cognito 授权代码获取访问和刷新令牌

什么是好的 AWS 解决方案(DB、ETL、批处理作业)来存储大量历史交易数据(每日刷新)以进行机器学习分析?

Ionic 3表单仍然警告我:“密码字段不包含在表单中”

如何检查某个表是不是正在被 AWS Redshift 上的某个程序或视图使用