首页 文章

Cognito用户池:如何使用刷新令牌刷新访问令牌

提问于
浏览
21

我正在使用Cognito用户池来验证系统中的用户 . 成功的身份验证提供ID令牌(JWT),访问令牌(JWT)和刷新令牌 . 这里的文档http://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html清楚地提到刷新令牌可用于刷新访问令牌,但没有提到如何 . 我的问题是,一旦我的访问令牌过期,我如何使用存储的刷新令牌再次刷新我的访问令牌?

我搜索了javascript sdk,找不到任何方法来做同样的事情 . 我绝对错过了什么 .

此外,我通过Lambda函数考虑这一点,该函数接收访问令牌并刷新令牌并使用刷新的访问令牌进行响应 . 如果有人能对此有所启发,那将会很棒 .

谢谢

5 回答

  • 18

    以下是使用Node.js在服务器端使用JavaScript的示例 .

    const AccessToken = new CognitoAccessToken({ AccessToken: tokens.accessToken });
    const IdToken = new CognitoIdToken({ IdToken: tokens.idToken });
    const RefreshToken = new CognitoRefreshToken({ RefreshToken: tokens.refreshToken });
    
    const sessionData = {
      IdToken: IdToken,
      AccessToken: AccessToken,
      RefreshToken: RefreshToken
    };
    const userSession = new CognitoUserSession(sessionData);
    
    const userData = {
      Username: email,
      Pool: this.userPool
    };
    
    const cognitoUser = new CognitoUser(userData);
    cognitoUser.setSignInUserSession(userSession);
    
    cognitoUser.getSession(function (err, session) { // You must run this to verify that session (internally)
      if (session.isValid()) {
        // Update attributes or whatever else you want to do
      } else {
        // TODO: What to do if session is invalid?
      }
    });
    

    您可以在我的博客How to authenticate users with Tokens using Cognito中看到完整的工作示例 .

  • 20

    如果您为了您的目的而工作,您仍然可以看到它如何处理SDK source中的刷新过程:

    您可以在 refreshSession 中看到Cognito InitiateAuth endpoints 被调用 REFRESH_TOKEN_AUTHAuthFlow 值设置,而一个对象作为 AuthParameters 值传入 .

    需要配置该对象以满足用户池的需要 . 具体来说,如果您的目标App客户端ID具有关联的App客户端密钥,则可能必须传入 SECRET_HASH . 创建用于Javascript SDK的用户池客户端应用程序当前不能包含客户端密钥,因此不需要 SECRET_HASH 来连接它们 .

    另一个可能引发循环的警告是,如果您的用户池设置为记住设备,并且您没有传入 DEVICE_KEYREFRESH_TOKEN . 如果您传入 RefreshToken 而不传入 DeviceKey ,则Cognito API当前会返回"Invalid Refresh Token"错误 . 即使您传入有效的 RefreshToken ,也会返回此错误 . 上面链接的线程说明了这一点,尽管我希望AWS更新其错误处理,以便在将来不那么神秘 .

    如该线程中所述,如果您使用AdminInitiateAuth以及 ADMIN_NO_SRP_AUTH ,则您的成功身份验证响应有效内容当前不包含 NewDeviceMetadata ;这意味着当您尝试刷新令牌时,您将不会传入任何 DeviceKey .

    我的应用程序要求在Python中实现,所以这里有一个对我有用的示例:

    def refresh_token(self, username, refresh_token):
        try:
            return client.initiate_auth(
                ClientId=self.client_id,
                AuthFlow='REFRESH_TOKEN_AUTH',
                AuthParameters={
                    'REFRESH_TOKEN': refresh_token,
                    'SECRET_HASH': self.get_secret_hash(username)
                    // Note that SECRET_HASH is missing from JSDK
                    // Note also that DEVICE_KEY is missing from my example
                }
            )
        except botocore.exceptions.ClientError as e:
            return e.response
    
  • 4

    Javascript sdk在内部处理令牌的刷新 . 当您调用“getSession”获取令牌时,如果没有任何有效的缓存访问权限和ID令牌,SDK将使用刷新令牌获取新的访问权限和ID令牌 . 它调用用户身份验证,只有当刷新令牌也过期时,才需要用户提供用户名和密码 .

    此致,马赫什

  • 1

    使用amazon-cognito-identity-js浏览器SDK刷新会话;它主要是为你做的,除非你做一些不寻常的事情,否则你不需要直接处理刷新令牌 . 这是你需要知道的:

    假设您已经像这样实例化了用户池:

    const userPool = new AmazonCognitoIdentity.CognitoUserPool({
      UserPoolId: USER_POOL_ID,
      ClientId: USER_POOL_CLIENT_ID
    });
    

    要查找经过身份验证的最后一个用户名,您可以这样做:

    const cognitoUser = cognitoUserPool.getCurrentUser();
    

    如果找到一个,cognitoUser将为非null,您可以执行此操作,如果需要,将在幕后刷新您的令牌:

    cognitoUser.getSession(function(err, data) {
      if (err) {
        // Prompt the user to reauthenticate by hand...
      } else {
        const cognitoUserSession = data;
        const yourIdToken = cognitoUserSession.getIdToken().jwtToken;
        const yourAccessToken = cognitoUserSession.getAccessToken().jwtToken;
      }
    });
    

    如果您不希望这些令牌持久存储在本地存储中,您可以:

    cognitoUser.signOut();
    

    它的工作方式是,在成功验证后,浏览器将存储您的JWT令牌,包括该刷新令牌 . 默认情况下,它会将这些存储在浏览器的本地存储中,但您可以根据需要提供自己的存储对象 . 默认情况下,刷新令牌在30d内有效,但它是UserPoolClient的属性(RefreshTokenValidity),您可以更改该属性 . 当你执行上述操作时,getSession()将首先查看存储中的令牌是否存在且仍然有效;如果没有,它将尝试使用它在那里找到的任何refreshToken来验证你进入一个新的会话 .

    文档http://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html表示iOS和Android SDK会为您执行此操作,但我没有使用它们,因此无法保证 .

  • 4

    我've been struggling with this as well in Javascript. Here'是我的解决方案,它基于https://github.com/aws/amazon-cognito-identity-js但它不依赖于存储,因此如果您愿意,可以在lambda函数中使用它 . 编辑:修复代码,感谢蜡笔

    const userPool = new AWSCognito.CognitoUserPool({
      UserPoolId: <COGNITO_USER_POOL>,
      ClientId: <COGNITO_APP_ID>
    })
    
    userPool.client.makeUnauthenticatedRequest('initiateAuth', {
      ClientId: <COGNITO_APP_ID>,
      AuthFlow: 'REFRESH_TOKEN_AUTH',
      AuthParameters: {
        'REFRESH_TOKEN': <REFRESH_TOKEN> // client refresh JWT
      }
    }, (err, authResult) => {
      if (err) {
         throw err
      }
      console.log(authResult) // contains new session
    })
    

相关问题