这很容易成为我去年不得不使用的最困难的代码——“在 .NET Web API 应用程序中从 AWS Cognito 验证 JWT 令牌”。 AWS 文档仍有很多不足之处。
这是我用于新的 .NET 6 Web API 解决方案的内容(因此 Startup.cs 现在包含在 Program.cs 等中。如果需要,请调整以适合您的 .NET 版本):
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = "https://cognito-idp.{aws region here}.amazonaws.com/{Cognito UserPoolId}",
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidateLifetime = true,
ValidAudience = "{Cognito AppClientId here}",
ValidateAudience = false
};
options.MetadataAddress = "https://cognito-idp.{aws region here}.amazonaws.com/{Cognito UserPoolId here}/.well-known/openid-configuration";
});
请注意,我将 ValidateAudience 设置为 false。否则,我会从 .NET 应用程序收到 401 Unauthorized 响应。 SO上的其他人说他们必须这样做才能使OAuth的身份验证/身份验证代码授权类型起作用。显然ValidateAudience = true 可以很好地用于隐式授权。你为什么要在 2022 年使用隐式授权?
另请注意,我正在设置options.MetadataAddress。对于另一个 SO 用户来说,这显然允许在幕后缓存来自 AWS 的签名密钥,它们会不时轮换。
一些官方 AWS 文档 (boo) 让我误入歧途,这些文档让我使用 builder.Services.AddCognitoIdentity(); (.NET 6) AKA services.AddCognitoIdentity(); (.NET 5 及更早版本)。显然,这适用于后端为前端提供服务的“ASP.NET”应用程序(例如 Razor/Blazor)。或者它可能已被弃用,谁知道呢。它在 AWS 的网站上,因此很可能会被弃用...
对于控制器,类级别的简单[Authorize] 属性就足够了。无需在[Authorize] 属性中将“Bearer”指定为AuthenticationScheme,也无需创建中间件或做任何额外的事情。
如果您不想为每个控制器以及 [Authorize] 添加另一个 using (using Microsoft.AspNetCore.Authorization;),您只希望每个控制器中的每个端点都需要 JWT,您可以将其放入 Startup/程序.cs:
builder.Services.AddControllers(opt =>
{
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
opt.Filters.Add(new AuthorizeFilter(policy));
});
确保在 Startup.cs (.NET 5) / Program.cs (.NET 6) 中 app.UseAuthentication 在 app.UseAuthorization() 之前。
这里是 Startup.cs 或 Program.cs 中的usings:
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.IdentityModel.Tokens;