Amazon Cognito联邦对接Amazon Connect调用getFederationToken返回用户未找到
我们尝试使用Amazon Cognito的托管登录页,实现用户在Amazon Connect实例上的身份验证。我们有一个使用Amazon Connect Streams库的Web应用,希望在初始化前先完成用户的Connect登录。
我们的实现思路是:通过Cognito登录流程生成一组临时凭证,用于调用Connect API的getFederationToken方法,随后用该接口返回的令牌完成用户的Connect登录。
现有配置详情
- Connect已配置为使用SAML进行身份验证
- Cognito和Connect两端的用户均使用邮箱地址作为用户名
- Cognito用户池已配置应用客户端,设置了对应的读写属性、允许的流程和作用域,托管登录页验证完成后会跳转至我们的Web应用,跳转后可获取到Id Token
- Cognito身份池的已认证角色(我们认为该角色会在Cognito认证流程完成后被代入)已配置正确的信任关系和权限,允许其针对Connect实例调用
connect:GetFederationToken方法,身份池的身份提供商已设置为对应的Cognito用户池
当前使用的代码(ID已脱敏)
// 从跳转参数中提取Id token var IdToken = hashObj.id_token; // 初始化Amazon Cognito凭证提供器 AWS.config.region = 'eu-west-2'; AWS.config.credentials = new AWS.CognitoIdentityCredentials({ IdentityPoolId: 'eu-west-2:00000000-0000-0000-0000-000000000000', Logins: { 'cognito-idp.eu-west-2.amazonaws.com/eu-west-2_abcdefg': IdToken } }); var connect = new AWS.Connect(); var params = { InstanceId: '00000000-0000-0000-0000-000000000000' /* 必填参数 */ }; // 尝试用上面构造的凭证从Connect获取联邦令牌 connect.getFederationToken(params, function (err, data) { if (err) { console.log(err); } // 发生错误 else { console.log(data); } });
遇到的问题
调用联邦接口返回用户未找到的结果。本质是系统无法将完成Cognito认证流程的用户与Connect中的用户匹配,我们已经多次核对两端用户名完全一致。
已尝试的解决方案
- 调整身份池和用户池的属性配置
- 将凭证对象中的
RoleSessionName设置为多个不同值 - 通过Pre Token Generation Lambda向Id Token中添加自定义声明
请问我们遗漏了什么配置?看起来只差一小步就能完成适配。
核心问题是getFederationToken接口默认使用调用凭证的RoleSessionName匹配Connect用户,而Cognito身份池生成的临时凭证默认RoleSessionName为Cognito身份ID,并非两端统一的邮箱用户名,因此无法匹配成功。需要做以下三处修改:
1. 调用getFederationToken时显式传入UserId参数
从Id Token的email属性中提取用户邮箱,作为UserId参数传入接口,该值会被用来匹配Connect中的用户名,示例参数配置如下:
// 先从Id Token中解析出email属性,可用jwt-decode等库解析 const decodedToken = jwt_decode(IdToken); var params = { InstanceId: '00000000-0000-0000-0000-000000000000', UserId: decodedToken.email // 传入和Connect端一致的邮箱用户名 };
2. 等待Cognito凭证刷新完成后再调用接口
CognitoIdentityCredentials初始化后是异步获取临时凭证的,需要监听凭证刷新完成的回调,避免用未生效的匿名凭证调用接口:
AWS.config.credentials.get(function(err) { if (err) { console.log("凭证获取失败", err); return; } // 凭证获取成功后再调用Connect接口 connect.getFederationToken(params, function (err, data) { if (err) console.log(err); else console.log(data); }); });
3. 校验身份池角色的权限配置
确认Cognito已认证角色的权限策略中,connect:GetFederationToken的资源匹配规则包含对应Connect实例ARN,且信任策略允许Cognito身份池代入该角色。
完成以上修改后即可正常匹配到Connect用户,完成登录流程。
内容的提问来源于stack exchange,提问作者twilson1

