angular - 带有 PKCE 的 OpenID Connect 代码流仅返回子声明
问题描述
我正在使用这个带有 PKCE 的 OpenID Connect 代码流的 Angular Lib来创建一个带有 openid 连接身份验证的 SPA。此外,我正在使用身份服务器 4。
SPA 中的 OIDC 配置
{
"stsServer": "http://localhost:5000",
"redirect_url": "http://localhost:4200",
"client_id": "angularclient",
"response_type": "code",
"scope": "openid profile email address phone api1",
"post_logout_redirect_uri": "http://localhost:4200",
"start_checksession": true,
"silent_renew": true,
"silent_renew_url": "http://localhost:4200/silent-renew.html",
"post_login_route": "/home",
"forbidden_route": "/forbidden",
"unauthorized_route": "/unauthorized",
"log_console_warning_active": true,
"log_console_debug_active": true,
"max_id_token_iat_offset_allowed_in_seconds": 10
}
身份服务器的 OIDC 配置
new Client
{
ClientName = "angularclient",
ClientId = "angularclient",
AccessTokenType = AccessTokenType.Reference,
// RequireConsent = false,
AccessTokenLifetime = 3600,// 330 seconds, default 60 minutes
IdentityTokenLifetime = 3600,
RequireClientSecret = false,
AllowedGrantTypes = GrantTypes.Code,
RequirePkce = true,
AllowAccessTokensViaBrowser = true,
RedirectUris = new List<string>
{
"http://localhost:4200",
"http://localhost:4200/callback.html",
"http://localhost:4200/silent-renew.html"
},
PostLogoutRedirectUris = new List<string>
{
"http://localhost:4200/",
"http://localhost:4200"
},
AllowedCorsOrigins = new List<string>
{
"http://localhost:4200"
},
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
IdentityServerConstants.StandardScopes.Address,
IdentityServerConstants.StandardScopes.Phone,
"api1"
}
}
当我访问 userinfo_endpoint 时,仅返回 sub 声明。
{ "sub": "818727" }
我的配置中缺少什么?我是否必须配置从 userinfo_endpoint 返回的声明?
解决方案
使用 CustomProfileService 会返回声明。感谢@Randy 和@Shantanu 的提示。
public class CustomProfileService : IProfileService
{
private readonly TestUserStore _users;
public CustomProfileService(TestUserStore users = null)
{
_users = users ?? new TestUserStore(TestUsers.Users);
}
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var sub = context.Subject.FindFirst("sub").Value;
if (sub != null)
{
var user = _users.FindBySubjectId(sub);
var claimsPrincipal = await GetClaimsAsync(user);
var claims = claimsPrincipal.Claims.ToList();
if (context.RequestedClaimTypes != null && context.RequestedClaimTypes.Any())
{
claims = claims.Where(x => context.RequestedClaimTypes.Contains(x.Type)).ToList();
}
context.IssuedClaims = claims;
}
}
public async Task IsActiveAsync(IsActiveContext context)
{
}
private async Task<ClaimsPrincipal> GetClaimsAsync(TestUser user)
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
return await Task.Factory.StartNew(() =>
{
var claimsIdentity = new ClaimsIdentity();
claimsIdentity.AddClaims(user.Claims);
return new ClaimsPrincipal(claimsIdentity);
});
}
}
启动.cs
builder.Services.AddTransient<IProfileService, CustomProfileService>();
推荐阅读
- django - 在Django中动态地从对象_meta中获取外键的详细名称
- css - AWS 无服务器部署 antd 注入不需要的内联 css
- java - Java 内存模型与同步、易失和(标记)锁的交互
- python - 从 scipy.spatial.procrustes 转换矩阵
- python - 熊猫 read_csv 跳到新行
- spring - 测试期间出现 UnsatisfiedDependencyException
- netsuite - Netsuite-Suitelet post to restlet 获取参数
- ios - 无法在 Xcode 10 中查找屏幕比例和意外的物理屏幕方向
- php - Laravel如何将参数传递给中间件?
- spring - 杰克逊将日期序列化为时间戳