.NET 7 Web API如何从AWS Cognito获取更多用户声明(如email)
实现自动从OIDC UserInfo端点获取额外声明的方案
你的需求完全可以实现,不需要手动编写独立的UserInfo调用逻辑,通过扩展JwtBearer的验证事件就能优雅完成。以下是具体步骤:
1. 核心思路
利用JwtBearerOptions的OnTokenValidated事件,在Token验证通过后,自动调用Cognito的UserInfo端点获取用户属性,并将这些属性添加到当前请求的ClaimsPrincipal中,后续接口就能直接读取这些声明。
2. 修改Program.cs配置
先注入IHttpClientFactory(用于复用HttpClient,避免Socket耗尽问题),再修改JwtBearer的配置,添加事件处理逻辑:
// 注入HttpClient工厂 builder.Services.AddHttpClient(); builder.Services .AddAuthentication(options => options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { builder.Configuration.GetSection("Auth:Cognito").Bind(options); // 配置Token验证完成后的事件 options.Events = new JwtBearerEvents { OnTokenValidated = async context => { // 获取HttpClient实例 var httpClientFactory = context.HttpContext.RequestServices.GetRequiredService<IHttpClientFactory>(); var httpClient = httpClientFactory.CreateClient(); // 构造Cognito UserInfo端点地址 var userInfoEndpoint = $"{options.Authority}/oauth2/userInfo"; // 构造请求,携带当前验证通过的AccessToken var request = new HttpRequestMessage(HttpMethod.Get, userInfoEndpoint); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.SecurityToken.RawData); // 调用UserInfo端点 var response = await httpClient.SendAsync(request); response.EnsureSuccessStatusCode(); // 解析返回的用户属性 var userInfo = await response.Content.ReadFromJsonAsync<Dictionary<string, object>>(); // 将属性添加到当前用户的声明集合 var claimsIdentity = context.Principal.Identity as ClaimsIdentity; foreach (var kvp in userInfo) { // 避免重复添加已存在的声明 if (!claimsIdentity.HasClaim(c => c.Type == kvp.Key)) { claimsIdentity.AddClaim(new Claim(kvp.Key, kvp.Value.ToString())); } } } }; });
3. 关键注意事项
- 确保AccessToken包含
openidScope:Cognito的UserInfo端点要求AccessToken必须携带openid权限,否则会返回403。需要在生成Token的客户端配置中添加该Scope。 - 异常处理:生产环境中要添加对
SendAsync失败的异常捕获(比如网络问题、Token过期),避免验证流程中断导致请求失败。 - 声明去重:代码中已经处理了重复声明的问题,避免同一属性被多次添加。
4. 关于AddOpenIdConnect的说明
你提到的AddOpenIdConnect确实是为带有登录页面的Cookie认证场景设计的,它会处理完整的OIDC授权流程(跳转登录页、获取授权码、交换Token等),不适合纯REST API的Bearer Token验证模式,所以用JwtBearer的事件扩展是更适配的方案。
内容的提问来源于stack exchange,提问作者Rowan Freeman
相关产品推荐
相关产品推荐

