在最终用户应用程序中使用 AWS Cognito 的正确身份验证流程

问题描述 投票:0回答:1

我正在开发一个简单的 PoC,我只想探索 AWS 的功能。因此,我的意图非常简单(我认为):我想构建一个小型基础设施,允许将 S3 存储桶下载到 Windows 计算机。因此,我使用 Cognito 创建了一个用户池,创建了一个新的演示用户,并创建了一个启用了授权代码流的应用程序客户端。之后,我创建了一个新角色,它只提供对我的 AWS S3 服务的完全访问权限(当然只是用于测试目的),将该角色分配给一个组,并将我的演示用户分配给该组。由于我能够从 Cognito 接收 OAuth 2.0 令牌,因此我进入了下一步:在 .NET Core 8 中构建一个应用程序,该应用程序的功能与我之前在 Insomnia 中所做的完全一样:针对 Cognito 进行身份验证并下载 S3 存储桶。当然,我可以在计算机上创建一个 AWS 配置文件,然后调用 S3 SDK,但所有 API 调用都通过我的 AWS 帐户完成。这完全不是我想要的。此外,我想管理一些用户,让他们访问一些存储桶,仅此而已。

因此,我为任务栏开发了一个小应用程序,它打开 Web 浏览器,将用户重定向到 Cognito 登录页面,然后重定向回应用程序的 Web 服务器。通过收集到的授权代码,我使用普通的 HttpClient 类获取了 OAuth 2.0 令牌。

但现在我很困惑。我现在应该如何访问 S3 存储桶?

我已经花了几个小时在网络上搜索,才发现我需要使用提供 OAuth 2.0 凭证的安全令牌服务担任角色,然后接收 AWS 凭证,然后可以使用该凭证通过 SDK 联系 S3。所以我用了

AmazonSecurityTokenServiceClient
。但我收到一个错误,我是
Unable to get IAM security credentials from EC2 Instance Metadata Service
。但现在 EC2 服务如何发挥作用呢?

通过以下代码片段,我尝试将有效的 OIC ID 令牌与 AWS 凭证进行交换。

// Get AWS credentials using the identity pool
AmazonSecurityTokenServiceClient securityTokenServiceClient = new AmazonSecurityTokenServiceClient(RegionEndpoint.EUNorth1);
AssumeRoleWithWebIdentityResponse roleResponse = await securityTokenServiceClient.AssumeRoleWithWebIdentityAsync(new AssumeRoleWithWebIdentityRequest()
{
    WebIdentityToken = tokenResponse?.IdToken,
    RoleArn = "arn:aws:iam::1234:role/cognito-demo-bucket",
    RoleSessionName = "demo"
});

_logger.LogTrace("Access key: {awsCredentials}\nSecret access key: {secretAccessKey}", roleResponse.Credentials.AccessKeyId, roleResponse.Credentials.SecretAccessKey);

我的假设是,使用 SDK“部署”的应用程序无法在计算机上找到 AWS 配置文件来联系 STS,但我认为这在最终用户计算机上是正常的。我认为我不需要在所有这些机器上创建 AWS 配置文件。

c# windows amazon-web-services amazon-s3 amazon-cognito
1个回答
0
投票

您获得

Unable to get IAM security credentials from EC2 Instance Metadata Service
的原因在于适用于 .NET 的 AWS 开发工具包如何搜索凭证。

.NET SDK 的

默认凭据提供程序链按照特定顺序一一搜索凭据。如果一切都失败了,目前,凭证提供者最终要考虑的地方是:

    Amazon EC2 实例元数据。
由于 .NET SDK 在其他 7 个位置的任何位置都找不到您的应用程序的任何凭证,因此其最终尝试是从元数据项下的 EC2 实例元数据端点加载它们

iam/security-credentials/{role-name}


由于您没有在 EC2 实例上运行,因此也会失败,并且 SDK 会出错并显示上述错误消息 - 基本上是说:

我在任何地方都找不到任何凭据。

本例中的
AmazonSecurityTokenServiceClient

不需要

任何 AWS 凭证
。它用于调用 AssumeRoleWithWebIdentity
 操作,该操作将 Cognito ID 令牌交换为临时 AWS 凭证。
根据文档:

调用
AssumeRoleWithWebIdentity

不需要使用 AWS 安全凭证

因此,您需要告诉AWS SDK不要签署请求。

对于 .NET SDK,您可以使用

AnonymousAWSCredentials

 类来完成此操作:
using Amazon; using Amazon.Runtime; using Amazon.SecurityToken; var anonymousCredentials = new AnonymousAWSCredentials(); var stsClient = new AmazonSecurityTokenServiceClient(anonymousCredentials, RegionEndpoint.EUWest1);

对于 Amazon S3,这是一个完整的、最小的示例:

using Amazon; using Amazon.Runtime; using Amazon.S3; using Amazon.SecurityToken; using Amazon.SecurityToken.Model; var anonymousCredentials = new AnonymousAWSCredentials(); var stsClient = new AmazonSecurityTokenServiceClient(anonymousCredentials, RegionEndpoint.EUWest1); var assumeRoleResponse = await stsClient.AssumeRoleWithWebIdentityAsync(new AssumeRoleWithWebIdentityRequest { RoleArn = "arn:aws:iam::1234:role/cognito-demo-bucket", RoleSessionName = "xxx", WebIdentityToken = "yyy" }); var assumedCredentials = new SessionAWSCredentials( assumeRoleResponse.Credentials.AccessKeyId, assumeRoleResponse.Credentials.SecretAccessKey, assumeRoleResponse.Credentials.SessionToken ); var s3Client = new AmazonS3Client(assumedCredentials); var getObjectResponse = await s3Client.GetObjectAsync(...);

© www.soinside.com 2019 - 2024. All rights reserved.