如何使用 AWS Cognito 保护 .Net Core Web API 应用程序

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

我是 AWS 新手,需要使用 Cognito 保护对 .NET Core Web API 应用程序的访问。我主要关注 Les Jackson 在 YouTube 上发布的精彩视频 (https://www.youtube.com/watch?v=3PyUjOmuFic),但他使用的是 Azure 而不是 AWS。

到目前为止,我有一个非常简单的 API 控制器操作,只需从 SQL Server 中提取一些记录并发送 JSON 响应。

        [HttpGet]
        public async Task<IEnumerable<TodoItem>> Get()
        {
            var items = await context.TodoItem.ToListAsync();
            return items;
        }

这在 Visual Studio 本地运行良好,并且在使用 Elastic Beanstalk 部署到 AWS 实例时也运行良好。

为了保护应用程序,我添加到 Startup.cs 中的 ConfigureServices 方法中

    services.AddAuthentication("Bearer")
        .AddJwtBearer(options =>
        {
            options.Audience = "App client id";
            options.Authority = "https://cognito-idp.eu-west-2.amazonaws.com/Cognito User Pool id";
        });

并且在Configure方法中

            app.UseAuthentication();

我向应用程序添加了一个控制器,只是为了通过 Cognito 进行身份验证并取回访问令牌。

        private const string _clientId = "App client id";
        private readonly RegionEndpoint _region = RegionEndpoint.EUWest2;

        [HttpPost]
        [Route("/api/signin")]
        public async Task<ActionResult<string>> SignIn(User user)
        {
            var cognito = new AmazonCognitoIdentityProviderClient(_region);

            var request = new AdminInitiateAuthRequest
            {
                UserPoolId = "Cognito User Pool id",
                ClientId = _clientId,
                AuthFlow = AuthFlowType.ADMIN_USER_PASSWORD_AUTH
            };

            request.AuthParameters.Add("USERNAME", user.Username);
            request.AuthParameters.Add("PASSWORD", user.Password);

            var response = await cognito.AdminInitiateAuthAsync(request);

            return Ok(response.AuthenticationResult);
        }

经过一番混乱之后,我已经在本地和 AWS 上实现了此功能,当使用 Postman 发布 Cognito 用户名和密码时返回令牌,例如

{
    "accessToken": ".....",
    "expiresIn": 3600,
    "idToken": "...",
    "newDeviceMetadata": null,
    "refreshToken": "...",
    "tokenType": "Bearer"
}

因此,我将 [Authorize] 属性添加到我的 API 方法中,使用 SignIn 方法获取访问令牌,并在 Postman 中构造一个请求,其中包含值为“Bearer”+ accessToken 的授权 HTTP 标头。

可悲的是,这不起作用,我想不出还有什么可以尝试的。

通过 Visual Studio 对 IIS Express 中本地运行的应用程序使用 Postman 请求,我得到响应

System.InvalidOperationException: IDX20803: Unable to obtain configuration from: '[PII is hidden. For more details, see https://aka.ms/IdentityModel/PII.]'.
 ---> System.IO.IOException: IDX20807: Unable to retrieve document from: '[PII is hidden. For more details, see https://aka.ms/IdentityModel/PII.]'. HttpResponseMessage: '[PII is hidden. For more details, see https://aka.ms/IdentityModel/PII.]', HttpResponseMessage.Content: '[PII is hidden. For more details, see https://aka.ms/IdentityModel/PII.]'.

使用 Elastic Beanstalk 部署应用程序时,我只收到 500 内部服务器错误,没有其他消息。

我做错了什么?我将不胜感激任何帮助/指示。

道格

c# amazon-web-services authentication asp.net-core-webapi amazon-cognito
2个回答
4
投票

我不太清楚为什么,但现在似乎工作正常!

我最终得到的代码是:

在ConfigureServices中,Startup.cs

            services.AddAuthentication("Bearer")
                .AddJwtBearer(options =>
                {
                    options.TokenValidationParameters = new TokenValidationParameters { ValidateAudience = false };
                    options.Authority = "https://cognito-idp.eu-west-2.amazonaws.com/eu-west-2_xxxxxxxxx";
                    options.RequireHttpsMetadata = false;
                });

在配置中,Startup.cs

            app.UseAuthentication();

在appsettings.json中

  "AWSCognito": {
    "Region": "{Region}",
    "PoolId": "{PoolId}",
    "AppClientId": "{AppClientId}"
  }

当授权 HTTP 标头中提供访问令牌时,对用 [Authorize] 属性修饰的 API 方法的调用会成功,并且 User.Identity.Claims.Where(c => c.Type == "username").FirstOrDefault()给出经过身份验证的用户的用户 ID。

感谢您的建议。


0
投票

您可以采取以下措施来使用 Amazon Cognito 保护您的 .NET 6 API。

  1. 安装

    Microsoft.AspNetCore.Authentication.JwtBearer
    NuGet 包。

  2. appsettings.json
    文件中添加以下设置。

    {
      .
      .
      "AppSettings": {
        "AllowedOrigions": "http://localhost:80", //change it as per your requirement, this should have a comma values
        "Cognito": {
          "AppClientId": "",
          "UserPoolId": "",
          "AWSRegion": ""
        }
      }
    }
    
  3. WebApplicationBuilder
    文件中的
    Program.cs
    之后添加以下代码以读取配置。

    var builder = WebApplication.CreateBuilder(args);
    
    // read configurations
    string[] allowedDomains = builder.Configuration["AppSettings:AllowedOrigions"].Split(",");
    string cognitoAppClientId = builder.Configuration["AppSettings:Cognito:AppClientId"].ToString();
    string cognitoUserPoolId = builder.Configuration["AppSettings:Cognito:UserPoolId"].ToString();
    string cognitoAWSRegion = builder.Configuration["AppSettings:Cognito:AWSRegion"].ToString();
    
    string validIssuer = $"https://cognito-idp.{cognitoAWSRegion}.amazonaws.com/{cognitoUserPoolId}";
    string validAudience = cognitoAppClientId;
    
  4. 此外,在您的

    Program.cs
    文件中添加以下代码来注册必要的服务。

    // Configure CORS
    builder.Services.AddCors(item =>
    {
        item.AddPolicy("CORSPolicy", builder =>
        {
            builder.WithOrigins(allowedDomains)
            .AllowAnyMethod()
            .AllowAnyHeader();
        });
    });
    
    // Register authentication schemes, and specify the default authentication scheme
    builder.Services
        .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
        {
          // Note: Authority is the address of the token-issuing authentication server.
          // The JWT bearer authentication middleware will use this URI to find and retrieve the public key that can be used to validate the token’s signature.
          // It will also confirm that the iss parameter in the token matches this URI. Hence, we don't need to specify ValidateIssuer explicitly in TokenValidationParameters.
          // See https://devblogs.microsoft.com/dotnet/jwt-validation-and-authorization-in-asp-net-core/
    
            options.Authority = validIssuer;
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateLifetime = true,
                ValidAudience = validAudience,
                ValidateAudience = true,
            };
        });
    
    var app = builder.Build();
    
  5. 添加CORS和身份验证中间件。

    app.UseCors("CORSPolicy");
    
    app.UseAuthentication(); // resposible for constructing AuthenticationTicket objects representing the user's identity
    app.UseAuthorization();
    

    请注意,身份验证过程是由我们使用

    app.UseAuthentication()
    代码注册的身份验证中间件处理的。

  6. 创建如下所示的

    ProfileController
    用于测试目的。

    [Authorize]
    [ApiController]
    [Route("[controller]")]
    public class ProfileController : ControllerBase
    {
    
        [HttpGet]
        public IEnumerable<KeyValuePair<string, string>> Get()
        {
            return User.Claims.Select(item => new KeyValuePair<string, string>(item.Type, item.Value)).ToList();
        }
    }  
    
© www.soinside.com 2019 - 2024. All rights reserved.