AWS Cognito:生成令牌并在使用 amazon-cognito-identity-js SDK 刷新后

Posted

技术标签:

【中文标题】AWS Cognito:生成令牌并在使用 amazon-cognito-identity-js SDK 刷新后【英文标题】:AWS Cognito: Generate token and after refresh it with amazon-cognito-identity-js SDK 【发布时间】:2022-01-02 09:45:37 【问题描述】:

我正在使用 amazon-cognito-identity-js 实现 node.js 后端。

我想创建一个登录(用户名、密码)和 refreshToken(token) API。

这是我的代码:

import  AuthenticationDetails, CognitoUser, CognitoUserPool, CognitoRefreshToken  from "amazon-cognito-identity-js"


   
public loginWithAmazonCognitoIdentity (username: string, password: string)
        
        var authenticationData = 
        Username : username,
        Password : password,
    ;
    var authenticationDetails = new AuthenticationDetails(authenticationData);
    var poolData =  UserPoolId : 'eu-north-1_xxxxxx',
        ClientId : '3al0l3mhcxxxxxqgnp789987'
    ;
    var userPool = new CognitoUserPool(poolData);
    var userData = 
        Username : username,
        Pool : userPool
    ;
    var cognitoUser = new CognitoUser(userData);
    const user = cognitoUser.authenticateUser(authenticationDetails, 
        onSuccess: function (result) 
            var accessToken = result.getAccessToken().getJwtToken();
            console.log("token: " + accessToken);
            var refresh = result.getRefreshToken().getToken();
            console.log("RefreshToken: " + refresh);
        ,

        onFailure: function(err) 
            console.error(err);
        ,

    );


此函数返回一个 accessToken 和一个 refreshToken 而没有错误。

在这之后,我实现了这个功能:

public refreshToken(refreshToken)
    var poolData =  UserPoolId : 'eu-north-1_xxxxxx',
            ClientId : '3al0l3mhcxxxxxqgnp789987'
            ;
            var userPool = new CognitoUserPool(poolData);
    
            var userData = 
                Username : 'lacucudi',
                Pool : userPool
            ;
            var cognitoUser  = new  CognitoUser(userData);
            var token = new CognitoRefreshToken( RefreshToken: refreshToken )
            cognitoUser.refreshSession(token, (err, session) =>  if (err) console.log(err) else console.log('session: ' + JSON.stringify(session)) );

但传递之前检索到的 refreshToken 它会返回:

NotAuthorizedException:无效的刷新令牌。

谁能告诉我这 2 个 api 的正确后端实现是什么?

【问题讨论】:

可能是 Username、UserPoolId、ClientId 或 refreshToken 无效。你用了回调样式,但是我没有看到你函数的回调函数参数(例如:loginWithAmazonCognitoIdentity),请问如何在函数外使用“结果”? Username 和 UserPoolId 与上面的登录函数相同,返回一个 id 令牌,access_token 和 refresh_token 填充 复制并粘贴您的刷新令牌到 jwt.io ,应该会出现令牌有效负载的内容。 @hoangdv 错误消息返回,因为在 Cognito 设置中启用了设备跟踪选项 【参考方案1】:

我是这样解决的:

    import Amplify,  Auth  from "aws-amplify";
    import 
        AdminCreateUserCommand,
        AdminSetUserPasswordCommand,
        AuthFlowType,
        CognitoIdentityProviderClient,
        CognitoIdentityProviderClientConfig,
        GetUserCommand,
        InitiateAuthCommand,
        MessageActionType,
        RevokeTokenCommand,
     from "@aws-sdk/client-cognito-identity-provider";

    public async login(username: string, password: string): Promise<AuthTokens> 
            if (!username || !password) 
                throw new HttpException(400, "Please provide both username and password");
            
    
            Amplify.configure( Auth: config.auth );
    
            const user = await Auth.signIn(username, password);
    
            if (!user.signInUserSession) 
                throw new HttpException(500, `Could not authenticate user $username`);
            
    
            const 
                signInUserSession: 
                    accessToken:  jwtToken: access_token ,
                    idToken:  jwtToken: id_token ,
                    refreshToken:  token: refresh_token ,
                ,
             = user;
    
            return 
                id_token,
                access_token,
                refresh_token,
            ;
        


public async refresh(refresh_token: string): Promise<AuthTokens> 
        if (!refresh_token) 
            throw new HttpException(400, "Please provide a refresh token");
        

        const refreshTokenAuth = new InitiateAuthCommand(
            ClientId: config.auth.userPoolWebClientId,
            AuthFlow: AuthFlowType.REFRESH_TOKEN_AUTH,
            AuthParameters: 
                REFRESH_TOKEN: refresh_token,
            ,
        );
        const response = await this.client.send(refreshTokenAuth);

        const 
            AuthenticationResult:  AccessToken, IdToken ,
         = response;

        return 
            refresh_token,
            access_token: AccessToken,
            id_token: IdToken,
        ;
    


public async logout(refreshToken: string): Promise<boolean> 
        if (!refreshToken) 
            throw new HttpException(400, "Please provide a refresh token");
        
        try 
            const command = new RevokeTokenCommand(
                ClientId: config.auth.userPoolWebClientId,
                Token: refreshToken,
            );
            const response = await this.client.send(command);
            const  httpStatusCode  = response.$metadata;
            return httpStatusCode == 200 ?? true;
         catch (e) 
            logger.error(e);
            throw new HttpException(500, e);
        
    

我使用 aws-amplify 进行登录,使用 aws-sdk/client-cognito-identity-provider 进行其他操作。

NotAuthorizedException:无效的刷新令牌

返回错误消息,因为在 Cognito 设置中启用了设备跟踪选项。

AWS 提供的服务提供错误的错误消息和很少的文档是不可思议的

【讨论】:

以上是关于AWS Cognito:生成令牌并在使用 amazon-cognito-identity-js SDK 刷新后的主要内容,如果未能解决你的问题,请参考以下文章

如何配置 AWS 用户 cognito 身份验证流程以在 Java sdk 后端生成身份令牌、访问令牌?

通过 Cognito 生成的授权令牌识别 AWS Lambda 中的用户

无效的登录令牌。缺少必需的声明:访问 AWS Cognito AssumeRoleWithWebIdentity 时的 aud

AWS Cognito:将自定义声明/属性添加到 JWT 访问令牌

AWS Cognito - 使用 JWT 与 cognito.getUser 开发工具包验证令牌

AWS cognito 快速将令牌交换为凭证