You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS Cognito:自定义UI实现设备记忆MFA但AccessToken缺失Scope问题

解决AWS Cognito登录的设备记忆与Scope缺失问题

一、自定义UI的Scope缺失修复

1. 检查用户池客户端配置

首先确认你的Cognito用户池应用客户端已开启所需的OAuth范围:

  • 登录AWS控制台,进入目标用户池 → 应用客户端 → 选择你的客户端 → 应用客户端设置
  • 在允许的OAuth范围中勾选openid、profile、email、phone以及aws.cognito.signin.user.admin
  • 保存配置

2. 在认证请求中明确指定Scope

使用amazon-cognito-identity-js时,需要在认证流程中主动请求完整的Scope,而不是依赖默认值。以下是两种常见实现方式:

方式1:使用initiateAuth方法(推荐,支持多种认证流)

import { CognitoIdentityProviderClient, InitiateAuthCommand } from "@aws-sdk/client-cognito-identity-provider";

const client = new CognitoIdentityProviderClient({ region: "YOUR_REGION" });

const params = {
  AuthFlow: "USER_PASSWORD_AUTH", // 根据你的认证流程调整,如USER_SRP_AUTH
  ClientId: "YOUR_APP_CLIENT_ID",
  AuthParameters: {
    USERNAME: "user@example.com",
    PASSWORD: "your_password",
    Scope: "openid profile email phone aws.cognito.signin.user.admin"
  }
};

const command = new InitiateAuthCommand(params);
const response = await client.send(command);

// 从response中获取包含完整Scope的access_token、id_token等

方式2:基于CognitoUser对象获取Session

如果使用传统的CognitoUser登录流程,确保在获取会话时触发完整Scope的请求:

import { CognitoUserPool, CognitoUser, AuthenticationDetails } from "amazon-cognito-identity-js";

const poolData = {
  UserPoolId: "YOUR_USER_POOL_ID",
  ClientId: "YOUR_APP_CLIENT_ID"
};
const userPool = new CognitoUserPool(poolData);
const userData = { Username: "user@example.com", Pool: userPool };
const cognitoUser = new CognitoUser(userData);

const authDetails = new AuthenticationDetails({
  Username: "user@example.com",
  Password: "your_password"
});

cognitoUser.authenticateUser(authDetails, {
  onSuccess: (session) => {
    // 这里的session包含的token会带有配置的完整Scope
    const accessToken = session.getAccessToken().getJwtToken();
    console.log(accessToken);
  },
  onFailure: (err) => {
    console.error(err);
  },
  // 处理MFA挑战(如果有)
  mfaRequired: (codeDeliveryDetails) => {
    const verificationCode = prompt("请输入验证码");
    cognitoUser.sendMFACode(verificationCode, {
      onSuccess: (session) => {
        // 验证成功后记忆设备
        cognitoUser.setDeviceStatusRemembered((err) => {
          if (err) console.error(err);
        });
      }
    });
  }
});

二、Hosted UI的设备记忆实现

虽然Hosted UI原生不支持设备记忆,但可以通过前端后续调用Cognito API补全该功能:

  1. Hosted UI登录成功后,从回调URL中提取id_token、access_token、refresh_token
  2. 用这些Token初始化CognitoUser会话,并调用设备记忆接口:
import { CognitoUserPool, CognitoUser, CognitoUserSession, CognitoIdToken, CognitoAccessToken, CognitoRefreshToken } from "amazon-cognito-identity-js";

const poolData = { UserPoolId: "YOUR_USER_POOL_ID", ClientId: "YOUR_APP_CLIENT_ID" };
const userPool = new CognitoUserPool(poolData);

// 从Hosted UI回调URL中解析出Token
const urlParams = new URLSearchParams(window.location.search);
const idToken = urlParams.get("id_token");
const accessToken = urlParams.get("access_token");
const refreshToken = urlParams.get("refresh_token");
const username = urlParams.get("username"); // 或从id_token解析

const userData = { Username: username, Pool: userPool };
const cognitoUser = new CognitoUser(userData);

// 构造会话对象
const session = new CognitoUserSession({
  IdToken: new CognitoIdToken({ IdToken: idToken }),
  AccessToken: new CognitoAccessToken({ AccessToken: accessToken }),
  RefreshToken: new CognitoRefreshToken({ RefreshToken: refreshToken })
});

cognitoUser.setSignInUserSession(session);

// 记忆当前设备
cognitoUser.setDeviceStatusRemembered((err) => {
  if (err) {
    console.error("记忆设备失败:", err);
  } else {
    console.log("设备已成功记忆,下次登录将跳过MFA");
  }
});

完成后,用户下次通过Hosted UI登录时,Cognito会识别已记忆的设备,自动跳过MFA验证。

三、统一两种登录方式的效果

  • 自定义UI:通过配置正确的Scope和设备记忆代码,实现"完整Scope Token + 跳过MFA"
  • Hosted UI:依赖原生的完整Scope Token(已配置),通过前端补调用设备记忆API实现跳过MFA

这样两种登录方式都能满足你的需求:用户无需每次输入验证码,且获取到的Token包含所有必要的Scope。

内容的提问来源于stack exchange,提问作者smile

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 16:31:15