【问题标题】:authenticate a user using cognito aws-sdk-cpp使用 cognito aws-sdk-cpp 对用户进行身份验证
【发布时间】:2017-12-13 14:58:16
【问题描述】:

我一直在尝试使用 aws-sdk-cpp 创建用户登录。我基本上希望用户使用我的应用程序作为用户注册(这会将他们添加到 cognito 用户池 - 我有这个工作),然后登录。然后,此登录将为他们提供对帐户中特定存储桶的访问权限。我创建了一个策略,应该允许 cognito 用户使用以下内容访问存储桶。

http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_s3_cognito-bucket.html

我已经在 AWS 控制台中创建了一个用户池和一个联合身份,并在用户池中启用了 cognito 作为身份提供者,所以我认为那一边是正确的。

我已经尝试使用 SDK 将这个身份验证放在一起,使用来自身份管理的集成测试作为起点。

Aws::SDKOptions options;
Aws::InitAPI(options);
{
    const Aws::String userPool_id = "eu-west-1_xxxxxxxxx";
    const Aws::String client_id = "xxxxxxxxxxxxxxxxxxxxxxxxxx";
    const Aws::String region_id = "eu-west-1";
    const Aws::String identityPool_id = "eu-west-1:xxxxxxxxxxxxxxxxx";
    const Aws::String account_id = "xxxxxxxxxxxx";

    Aws::Client::ClientConfiguration clientConfig;
    clientConfig.region = region_id;

    std::shared_ptr<CustomPersistentCognitoIdentityProvider> persistent_provider = std::make_shared<CustomPersistentCognitoIdentityProvider>();
    persistent_provider->SetAccountId(account_id);
    persistent_provider->SetIdentityPoolId(identityPool_id);

    //Aws::Map<Aws::String, LoginAccessTokens> logins;
    //LoginAccessTokens loginAccessTokens;
    //loginAccessTokens.accessToken = LOGIN_ID;
    //logins[LOGIN_KEY] = loginAccessTokens;
    //persistent_provider->SetLogins("cognito-idp.eu-west-1.amazonaws.com/eu-west-1_xxxxxxx", client_id);

    auto cognito_client = std::make_shared<Aws::CognitoIdentity::CognitoIdentityClient>(clientConfig);

    Aws::CognitoIdentity::Model::GetIdRequest id_request;
    id_request.SetAccountId(account_id);
    id_request.SetIdentityPoolId(identityPool_id);
    id_request.AddLogins("cognito-idp.eu-west-1.amazonaws.com/eu-west-1_xxxxxx", client_id);
    id_request.AddLogins("USERNAME", "tester@xxxxxxxxx");
    id_request.AddLogins("PASSWORD", "xxxxxxxxxxxxx");
    cognito_client->GetId(id_request);

    Aws::Auth::CognitoCachingAuthenticatedCredentialsProvider authenticated_provider(persistent_provider, cognito_client);
    Aws::Auth::AWSCredentials credentials = authenticated_provider.GetAWSCredentials();

    std::cout << "AccessKeyID : " << credentials.GetAWSAccessKeyId() << std::endl;
    std::cout << "SecretKey : " << credentials.GetAWSSecretKey() << std::endl;

    Aws::S3::S3Client s3_client(credentials, clientConfig);

    S3ListObject(s3_client, "cloudtesting");
    // do stuff with the s3 bucket 
}

Aws::ShutdownAPI(options);

上面的代码返回访问键的空字符串。

在 GetId 调用返回处添加一些调试:

Request error: NotAuthorizedException Invalid login token. Not a valid OpenId Connect identity token.

我显然在这里或设置中遗漏了一些东西。任何建议/帮助/代码示例将不胜感激!

【问题讨论】:

  • 您的第一个问题是您使用用户名/密码而不是 Cognito 身份提供者调用 Cognito 联合身份。 Cognito Identity Provider 用于验证您的用户并获取 OIDC 令牌,Cognito Federated Identity 用于将您获得的令牌交换为 AWS 凭证。在我深入回答之前,您是从不受信任的环境(即移动设备或最终用户的桌面)还是从您的服务器后端执行此操作?
  • 感谢您的回复。这一切都将转到客户端代码,所以是的,这将是一个不受信任的环境。我使用Aws::CognitoIdentityProvider::Model::AdminInitiateAuthRequest 模拟了一些服务器端代码。但这显然不适合客户端代码。一些关于我如何验证我的用户名/密码的澄清将不胜感激,然后交换 AWS 凭证将不胜感激!

标签: amazon-cognito aws-sdk-cpp


【解决方案1】:

为了通过 Cognito 用户池进行身份验证,您必须使用 CognitoIdentityProviderClient(请参阅 aws/cognito-idp/CognitoIdentityProviderClient.h)。它使用安全远程密码协议 (SRP) 进行身份验证,遗憾的是您必须自己实现。您首先调用 InitiateAuth,然后它会回复一些您必须使用 RespondToAuthChallenge 回复的信息。

这是在Amazon Cognito Identity SDK for JavaScript 中实现的,您可以将其用作参考。

【讨论】:

  • 谢谢,您的解释确实帮助了我的误解。我现在已经使用 openssl 实现了 SRP,并且登录现在似乎表现良好。
  • 补充一下,这个blog post 对 SRP 实施的帮助很大。非常感谢原作者@mmlac
  • 对于任何返回此问题的人,我已将我的 SRP 代码上传到 gist gist.github.com/manishpin/f7d8e9af84068bd9b0220bb2c7d14a4d
猜你喜欢
  • 2022-06-19
  • 2016-09-27
  • 1970-01-01
  • 2018-07-13
  • 1970-01-01
  • 1970-01-01
  • 2018-03-14
  • 2018-12-19
  • 2018-05-22
相关资源
最近更新 更多