C# 在ALB上使用Cognito用户池进行ASP.NET核心身份验证

C# 在ALB上使用Cognito用户池进行ASP.NET核心身份验证,c#,amazon-web-services,asp.net-core,amazon-cognito,C#,Amazon Web Services,Asp.net Core,Amazon Cognito,我正在将一个遗留的ASP.NET MVC应用程序移植到.NET Core,我还试图替换现有的Identity框架,以使用由应用程序负载平衡器处理的AWS Cognito用户池 我有大多数的设置和工作,当请求到达ALB,未经授权的用户被重定向到Cognoto托管的登录页面,在那里他们可以登录。这一切正常,但我想将JWT(从ALB传回)中的信息连接到ASP.NET Identity framework,以便访问填充的“User”对象 包含JWT的响应头也是非标准的“X-Amzn-Oidc-Data”

我正在将一个遗留的ASP.NET MVC应用程序移植到.NET Core,我还试图替换现有的Identity框架,以使用由应用程序负载平衡器处理的AWS Cognito用户池

我有大多数的设置和工作,当请求到达ALB,未经授权的用户被重定向到Cognoto托管的登录页面,在那里他们可以登录。这一切正常,但我想将JWT(从ALB传回)中的信息连接到ASP.NET Identity framework,以便访问填充的“User”对象

包含JWT的响应头也是非标准的“X-Amzn-Oidc-Data”,而不是在标准授权中。我已经研究过使用Microsoft.AspNetCore.Authentication.JwtBearer,但我相信这需要标准授权头

我确实遇到了这个项目,它似乎正是我需要的那种东西,但它似乎已经被放弃了。有没有人有过类似的经历,可以分享同样的东西

更新:这是我们根据Mickaël的评论更新的启动代码:

services.AddAuthentication("Cognito")
            .AddJwtBearer("Cognito", options =>
                {
                    options.Events = options.Events ?? new JwtBearerEvents();
                    options.Events.OnMessageReceived = context =>
                        {
                            string amazonOidcDataHeader = context.Request.Headers["X-Amzn-Oidc-Data"];
                            if (!string.IsNullOrEmpty(amazonOidcDataHeader))
                            {
                                context.Token = amazonOidcDataHeader.Trim();
                            }

                            return Task.CompletedTask;
                        };

                    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 = this.Configuration["Authentication:Cognito:ValidIssuer"],
                        ValidateIssuerSigningKey = true,
                        ValidateIssuer = true,
                        ValidateLifetime = true,
                        ValidAudience = this.Configuration["Authentication:Cognito:ClientId"],
                        ValidateAudience = true
                    };
                });
services.AddAuthentication(“Cognito”)
.AddJwtBearer(“Cognito”,选项=>
{
options.Events=options.Events??新的JWTBeareEvents();
options.Events.OnMessageReceived=上下文=>
{
字符串amazonOidcDataHeader=context.Request.Headers[“X-Amzn-Oidc-Data”];
如果(!string.IsNullOrEmpty(AmazonOIDCataHeader))
{
context.Token=amazonOidcDataHeader.Trim();
}
返回Task.CompletedTask;
};
options.TokenValidationParameters=新的TokenValidationParameters
{
IssuerSigningKeyResolver=(s、securityToken、标识符、参数)=>
{
//从AWS获取JsonWebKeySet
var json=new WebClient().DownloadString(parameters.validisuser+“/.well-known/jwks.json”);
//序列化结果
var keys=JsonConvert.DeserializeObject(json).keys;
//将结果强制转换为IssuerSigningKeyResolver期望的类型
返回(IEnumerable)键;
},
ValidIssuer=this.Configuration[“Authentication:Cognito:ValidIssuer”],
ValidateSuersigningKey=true,
validateisuer=true,
ValidateLifetime=true,
validudience=this.Configuration[“Authentication:Cognito:ClientId”],
ValidateAudience=true
};
});

现在从标头检索令牌并将其推送到上下文中。令牌属性,标识用户对象仍然不包含声明。

内置JWT提供程序有一个扩展点,可以通过
JWTBeareEvents.OnMessageReceived
事件从几乎任何地方获取令牌

你可以这样做:

服务
.AddAuthentication(“Cognito”)
.AddJwtBearer(“Cognito”,选项=>
{
options.Events???=newjwtbearerevents();
options.Events.OnMessageReceived=上下文=>
{
常量字符串bearprefix=“Bearer”;
字符串amazonOidcDataHeader=context.Request.Headers[“X-Amzn-Oidc-Data”];
if(!string.IsNullOrEmpty(amazonOidcDataHeader)&&amazonOidcDataHeader.StartsWith(bearerPrefix,StringComparison.OrdinalIgnoreCase))
{
context.Token=amazonOidcDataHeader.Substring(bearerPrefix.Length).Trim();
}
返回Task.CompletedTask;
};
});

如需参考,请参阅GitHub上的此代码摘录,其中显示了处理程序的实现,以及它如何使用
MessageReceived
事件期间分配的令牌(如果有),或者尝试从标准
Authorization
头中提取令牌,否则:

谢谢,这非常有用。我认为这应该从JWT填充Identity User对象,对吗?没问题。是的,除了令牌的来源之外,其他所有内容都将起相同的作用,包括填充
HttpContext.User
属性。我的HttpContext必须缺少一些内容。用户仍然为空,是否需要设置中间件的其他部分?增加日志记录级别以调试和分析HTTP请求的条目。如果没有完整的代码,即
Startup
类,就不可能知道可能缺少什么。