我能够成功检索自定义身份验证提供商(开发人员身份验证)的身份令牌。这是使用 Cognito devauth 演示 servlet 实现的。
此令牌将返回到运行 AWS JS SDK 的浏览器。当我调用 getCredentialsForIdentiy 时,我收到“无效登录令牌”错误。
POST https://cognito-identity.us-west-2.amazonaws.com/ 400 (Bad Request)
app.js:150 Error: Invalid login token. Not a Cognito token.
at constructor.a (aws-sdk-2.58.0.min.js:41)
at constructor.callListeners (aws-sdk-2.58.0.min.js:41)
at constructor.emit (aws-sdk-2.58.0.min.js:41)
at constructor.emitEvent (aws-sdk-2.58.0.min.js:41)
at constructor.e (aws-sdk-2.58.0.min.js:41)
at i.runTo (aws-sdk-2.58.0.min.js:43)
at aws-sdk-2.58.0.min.js:43
at constructor.<anonymous> (aws-sdk-2.58.0.min.js:41)
at constructor.<anonymous> (aws-sdk-2.58.0.min.js:41)
at constructor.callListeners (aws-sdk-2.58.0.min.js:41) "NotAuthorizedException: Invalid login token. Not a Cognito token.
at constructor.a (https://sdk.amazonaws.com/js/aws-sdk-2.58.0.min.js:41:615)
at constructor.callListeners (https://sdk.amazonaws.com/js/aws-sdk-2.58.0.min.js:41:30513)
at constructor.emit (https://sdk.amazonaws.com/js/aws-sdk-2.58.0.min.js:41:30224)
at constructor.emitEvent (https://sdk.amazonaws.com/js/aws-sdk-2.58.0.min.js:41:16590)
at constructor.e (https://sdk.amazonaws.com/js/aws-sdk-2.58.0.min.js:41:12285)
at i.runTo (https://sdk.amazonaws.com/js/aws-sdk-2.58.0.min.js:43:7277)
at https://sdk.amazonaws.com/js/aws-sdk-2.58.0.min.js:43:7482
at constructor.<anonymous> (https://sdk.amazonaws.com/js/aws-sdk-2.58.0.min.js:41:12495)
at constructor.<anonymous> (https://sdk.amazonaws.com/js/aws-sdk-2.58.0.min.js:41:16645)
at constructor.callListeners (https://sdk.amazonaws.com/js/aws-sdk-2.58.0.min.js:41:30619)"
我将以下参数传递给 getCredentialsForIdentity。
identityId: <returned from servlet in region:guid format>
customRoleArn: <that maps to authenticated role>
Logins: <cognito-identity.amazonaws.com = token returned by congito>
我注意到新的 congnito 身份是使用 id browser 创建的。因此,令牌与 servlet 的交互似乎是正确的。但令牌被拒绝了。
我在这里缺少什么?我该如何进一步排除故障?
编辑: 浏览器客户端:javascript sdk,版本2.58。 本质上是为 this demo 编写一个 JS 客户端。修改只是为了获取令牌作为登录调用本身的一部分。生成的令牌对应于仅具有IOT客户端访问权限的角色。 (我想知道该政策是否需要扩大)。最终,用户将根据内部 ID 存储而不是此演示进行验证。
编辑2: 我没有针对 Cognito 服务调用 getCredentialsForIdentity,而是针对 STS 调用 ShouldRoleWithWebIdentity,这有效。使用基本流程而不是增强流程此处。。真的不知道为什么增强流程不起作用,但现在将采用基本流程方法。
因此,此处的 AWS 文档要么不准确,要么记录了低效的场景。
使用 JavaScript Cognito API,我的开发者提供商返回的令牌无法与针对 Cognito API 的 GetCredentialsForIdentity 一起使用。 (这就是促使我问这个问题的原因)。
但是,我可以对 STS API 使用相同的令牌并调用 AssumeRoleWithWebIdentity ,它本质上返回与上面的 GetCredentialsForIdentity 相同的响应参数。这就是我采取的方法。
第一个链接中的基本身份验证流程文档似乎不准确。因为它列出了“获取凭据”和“承担角色”作为必需步骤,但实际上只需要一个。此外,从浏览器中,这是对 Amazon 服务的 API 调用。因此,如果有效的话,使用增强流程而不是基本流程似乎并不是一个优势。
我也遇到了同样的问题,使用的是 Javascript SDK V3,并且挣扎了很长时间!目前接受的答案对我有用 - 使用基本的身份验证流程而不是增强的。
我希望用一些当前使用 SDK V3 的读者可能会觉得有用的信息来补充上述内容:
在服务器上,使用 @aws-sdk/client-cognito-identity 中的 GetOpenIdTokenForDeveloperIdentityCommand 生成令牌并将其发送到客户端。
在客户端,我无法使用以下任何一项成功生成凭据:
使用@aws-sdk/client-sts,以下确实有效:
const { STSClient, AssumeRoleWithWebIdentityCommand } = require("@aws-sdk/client-sts")
const client = new STSClient({region: cognitoRegion})
const assumeRoleCommand = new AssumeRoleWithWebIdentityCommand({
WebIdentityToken: openIdToken, // the token your server sends to the client
RoleArn: authRoleARN, // the ARN of the role you set up on AWS Cognito / IAM
RoleSessionName: userId // See note below
})
const credentialsResponse = await client.send(assumeRoleCommand)
// the client apparently expects slightly different property names than the received credentials object
const credentials = {
accessKeyId: credentialsResponse.Credentials.AccessKeyId,
expiration: credentialsResponse.Credentials.Expiration,
secretAccessKey: credentialsResponse.Credentials.SecretAccessKey,
sessionToken: credentialsResponse.Credentials.SessionToken
}
// Example using SES, you may be using different services
const sesClient = new awsSes.SESClient({
apiVersion: "2010-12-01", // yours may be different
region: "us-east-1", // yours may be different
credentials: credentials
})
注意:AssumeRoleWithWebIdentityCommand 文档讨论了 RoleSessionName 应该使用什么。
我只能使用 Identity Pool APIs 获取临时凭证(无 STS)。我假设您拥有 Cognito 用户池中的 idToken:
import {
CognitoIdentityClient,
GetCredentialsForIdentityCommand,
GetIdCommand,
GetOpenIdTokenCommand,
} from '@aws-sdk/client-cognito-identity';
async function getAwsCredentialsFromIdentityPool(cognitoUserPoolIdToken: string) {
const identityClient = new CognitoIdentityClient({region: 'us-west-1'});
const getIdCommand = new GetIdCommand({
// TODO: Enter your own account and identity pool ids
AccountId: '012345678901',
IdentityPoolId: 'us-west-1:e201dc59-9193-4577-94ee-d1133fbe31fa',
Logins: {
// TODO: Enter your own user pool id
'cognito-idp.us-west-1.amazonaws.com/us-west-1_123456789': cognitoUserPoolIdToken,
},
});
const getIdCommandOutput = await identityClient.send(getIdCommand);
const getOpenIdTokenCommand = new GetOpenIdTokenCommand({
IdentityId: getIdCommandOutput.IdentityId,
Logins: {
// TODO: Enter your own user pool id
'cognito-idp.us-west-1.amazonaws.com/us-west-1_123456789': cognitoUserPoolIdToken,
},
});
const getOpenIdTokenCommandOutput = await identityClient.send(getOpenIdTokenCommand);
if (getOpenIdTokenCommandOutput.Token) {
const getCredentialsForIdentityCommand = new GetCredentialsForIdentityCommand({
IdentityId: getOpenIdTokenCommandOutput.IdentityId,
Logins: {
'cognito-identity.amazonaws.com': getOpenIdTokenCommandOutput.Token,
},
});
const getCredentialsForIdentityCommandOutput = await identityClient.send(getCredentialsForIdentityCommand);
return getCredentialsForIdentityCommandOutput.Credentials;
}
}