.net core 如何使用.AddJwtBearer()在.NET核心Web API中验证AWS Cognito JWT

.net core 如何使用.AddJwtBearer()在.NET核心Web API中验证AWS Cognito JWT,.net-core,jwt,amazon-cognito,asp.net-core-webapi,jwk,.net Core,Jwt,Amazon Cognito,Asp.net Core Webapi,Jwk,在我的.NET核心Web API中,我很难弄清楚如何验证AWS Cognito提供给客户端的JWT 我不仅无法确定Microsoft.IdentityModel.Tokens.TokenValidationParameters的变量应该是什么,而且一旦我最终确定了,我就不知道如何从检索JWT密钥集https://cognito-idp.{region}.amazonaws.com/{pool ID}/.well-known/jwks.json 最后,通过大量随机搜索和反复试验,我找到了一个(似乎

在我的.NET核心Web API中,我很难弄清楚如何验证AWS Cognito提供给客户端的JWT

我不仅无法确定Microsoft.IdentityModel.Tokens.TokenValidationParameters的变量应该是什么,而且一旦我最终确定了,我就不知道如何从
检索JWT密钥集https://cognito-idp.{region}.amazonaws.com/{pool ID}/.well-known/jwks.json

最后,通过大量随机搜索和反复试验,我找到了一个(似乎不是很有效的解决方案)解决方案。然而,我花了太多的时间做这件事。引用这一点,再加上AWS关于这个主题的文档严重缺乏,我决定发布这个问答,以帮助其他人在将来更容易地找到这个解决方案


如果有更好的方法,请有人告诉我,因为除了下面列出的答案之外,我还没有找到一种方法。答案主要在于正确定义
TokenValidationParameters。IssuerSigningKeyResolver
(参数等,见此处:)

这就是告诉.NETCore验证发送的JWT的依据。还必须告诉它在哪里可以找到钥匙列表。人们不一定要硬编码密钥集,因为它通常由AWS旋转

一种方法是从
issueSigningKeyResolver
方法中的URL获取并序列化列表。整个
.AddJwtBearer()
可能如下所示:

Startup.cs ConfigureServices()方法:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(options =>
                {
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        IssuerSigningKeyResolver = (s, securityToken, identifier, parameters) =>
                        {
                            // get JsonWebKeySet from AWS
                            var json = new WebClient().DownloadString(parameters.ValidIssuer + "/.well-known/jwks.json");
                            // serialize the result
                            var keys = JsonConvert.DeserializeObject<JsonWebKeySet>(json).Keys;
                            // cast the result to be the type expected by IssuerSigningKeyResolver
                            return (IEnumerable<SecurityKey>)keys;
                        },

                        ValidIssuer = "https://cognito-idp.{region}.amazonaws.com/{pool ID}",
                        ValidateIssuerSigningKey = true,
                        ValidateIssuer = true,
                        ValidateLifetime = true,
                        ValidAudience = "{Cognito AppClientID}",
                        ValidateAudience = true
                    };
                });
// get the current logged in user's info
Auth.currentSession().then((user) => {
fetch('https://localhost:5001/api/values',
  {
    method: 'GET',
    headers: {
      // get the user's JWT token given to it by AWS cognito 
      'Authorization': `Bearer ${user.signInUserSession.accessToken.jwtToken}`,
      'Content-Type': 'application/json'
    }
  }
).then(response => response.json())
 .then(data => console.log(data))
 .catch(e => console.error(e))
})

只有当您需要对验证进行更细粒度的控制时,才需要这里提供的答案

否则,下面的代码足以验证jwt

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
    options.Authority = "{yourAuthorizationServerAddress}";
    options.Audience = "{yourAudience}";
});
Okta有一篇关于这方面的好文章

当JwtBearer中间件第一次处理请求时,它 尝试从授权服务器检索某些元数据(也包括 称为权威机构或发行人)。此元数据或发现文档 在OpenID Connect术语中,包含公钥和其他 验证令牌所需的详细信息。(想知道元数据是什么样子吗?下面是一个示例发现文档。)

如果JwtBearer中间件找到此元数据文档,则 自动配置自身。很漂亮


真棒的回答。客户端的Amplify已经做了一些更改,因此对于令牌,我们现在应该使用user.signInUserSession.accessToken.jwtToken:)与2021年(core 3.1)一样,
JsonConvert.DeserializeObject(json)
可能不起作用-改用这个:
new JsonWebKeySet(json)
谢谢您的回答!当我在2018年做这件事时,我无法使用您描述的方法专门与AWS Cognito合作并进行放大。然而,我已经多次成功地将JWT与我自己的身份验证和用户管理实现结合使用。然而,如果这现在起作用,那是个好消息!这会处理关键点集的旋转吗?