我正在使用此Angular Lib for OpenID Connect Code Flow with PKCE创建具有openid connect身份验证的SPA。另外,我正在使用identity server 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": "818727" }
我的配置中缺少什么?我必须配置从userinfo_endpoint返回的声明吗?
答案 0 :(得分:1)
使用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);
});
}
}
Startup.cs
builder.Services.AddTransient<IProfileService, CustomProfileService>();