.NET Framework客户端无法从IdentityServer4获取name声明
解决.NET Framework Owin OpenIdConnect无法获取name声明的问题
我之前在对接IdentityServer4和.NET Framework的Owin应用时,也碰到过一模一样的问题——.NET Core里的GetClaimsFromUserInfoEndpoint属性在Owin的OpenIdConnect组件里确实不存在,导致默认不会调用UserInfo端点,进而缺失name这类属于profile范围的声明。下面是亲测有效的解决方法:
手动调用UserInfo端点获取声明
我们可以通过OpenIdConnectAuthenticationNotifications里的SecurityTokenValidated事件,在令牌验证通过后手动请求IdentityServer的UserInfo端点,把获取到的声明添加到用户身份中。
步骤1:安装IdentityModel库
首先需要安装IdentityModel NuGet包,它提供了方便调用UserInfo端点的客户端:
Install-Package IdentityModel
步骤2:修改OpenIdConnect配置
在你的UseOpenIdConnectAuthentication配置中添加Notifications节点,实现SecurityTokenValidated事件:
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions { AuthenticationType = "oidc", SignInAsAuthenticationType = "Cookies", Authority = identityServerUrl, RedirectUri = appUrl + "/signin-oidc", PostLogoutRedirectUri = appUrl + "/signout-callback-oidc", ClientId = "clientId", ClientSecret = @"secret", ResponseType = OpenIdConnectResponseTypes.CodeIdToken, Scope = "openid profile offline_access", UseTokenLifetime = false, // 添加以下Notifications配置 Notifications = new OpenIdConnectAuthenticationNotifications { SecurityTokenValidated = async notification => { // 从协议消息中获取访问令牌 var accessToken = notification.ProtocolMessage.AccessToken; if (string.IsNullOrEmpty(accessToken)) { return; } // 初始化UserInfo客户端,指向IdentityServer的UserInfo端点 var userInfoClient = new UserInfoClient( new Uri($"{notification.Options.Authority}/connect/userinfo"), accessToken); // 请求UserInfo端点 var userInfoResponse = await userInfoClient.GetAsync(); if (userInfoResponse.IsError) { throw new InvalidOperationException($"获取用户信息失败: {userInfoResponse.Error}"); } // 将UserInfo返回的声明添加到当前用户的身份中 var identity = notification.AuthenticationTicket.Identity; identity.AddClaims(userInfoResponse.Claims); } } });
关键检查点
除了上面的代码,还要确保以下几点:
- 你的客户端Scope已经包含
profile(从你的代码看已经加了,这是name声明所在的范围) - 在IdentityServer4的配置中,确保你的用户(或者IProfileService)正确返回了
name声明。如果使用的是测试用户,要确认用户配置里包含该声明;如果是自定义ProfileService,要在GetProfileDataAsync方法中添加对应的声明。 - 确认IdentityServer的UserInfo端点可以正常访问(可以通过携带有效令牌的请求测试端点可用性)
这样配置后,你的.NET Framework应用就能成功获取到name声明了,原理就是模拟.NET Core里GetClaimsFromUserInfoEndpoint=true的行为,手动触发UserInfo端点的调用并合并声明。
内容的提问来源于stack exchange,提问作者user2173353
相关产品推荐
相关产品推荐

