我有下面的配置
public static IEnumerable<IdentityResource> GetIdentityResources=>
new List<IdentityResource>
{
new IdentityResources.Profile(),
new IdentityResources.OpenId(),
new IdentityResources.Email(),
};
public static IEnumerable<ApiResource> ApiResources=>
new List<ApiResource>
{
new ApiResource(AuthorizePolicy.apiScope, "Falcon Api")
};
public static IEnumerable<Client> Clients(IConfiguration configuration) =>
new Client[]
{
new Client
{
ClientId = "Falcon_Identity_Server",
ClientName = "FalconIdentityServer",
AllowedCorsOrigins = CorsUris(configuration),
AllowedGrantTypes = GrantTypes.Code,
AllowAccessTokensViaBrowser = bool.Parse(configuration.GetSection("IdentityServer:Client:AllowAccessTokensViaBrowser").Value),
IdentityTokenLifetime = Int32.Parse(configuration.GetSection("IdentityServer:Client:IdentityTokenLifetime").Value),
AccessTokenLifetime = Int32.Parse(configuration.GetSection("IdentityServer:Client:AccessTokenLifetime").Value),
RequireConsent = bool.Parse(configuration.GetSection("IdentityServer:Client:RequireConsent").Value),
UpdateAccessTokenClaimsOnRefresh = bool.Parse(configuration.GetSection("IdentityServer:Client:UpdateAccessTokenClaimsOnRefresh").Value),
RedirectUris = LocalRedirectUris(configuration),
PostLogoutRedirectUris = LocalRedirectUris(configuration),
AllowedScopes = AllowedScopes(),
AllowOfflineAccess = bool.Parse(configuration.GetSection("IdentityServer:Client:AllowOfflineAccess").Value),
AccessTokenType = AccessTokenType.Jwt,
RequireClientSecret = bool.Parse(configuration.GetSection("IdentityServer:Client:RequireClientSecret").Value),
RequirePkce = bool.Parse(configuration.GetSection("IdentityServer:Client:RequirePkce").Value),
//AllowRememberConsent = true
}
};
private static ICollection<string> AllowedScopes()
{
return new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
AuthorizePolicy.apiScope
};
}
// API scopes represent values that describe scope of access and can be requested by the scope parameter (OAuth)
public static readonly IEnumerable<ApiScope> ApiScopes =
new[]
{
new ApiScope(IdentityServerConstants.StandardScopes.OpenId),
new ApiScope(IdentityServerConstants.StandardScopes.Profile),
new ApiScope(IdentityServerConstants.StandardScopes.Email),
new ApiScope(AuthorizePolicy.apiScope),
};
配置文件服务
public class ProfileService : IProfileService
{
private readonly IUserClaimsPrincipalFactory<ApplicationUser> _claimsFactory;
private readonly UserManager<ApplicationUser> _userManager;
private readonly ILogger<ProfileService> Logger;
public ProfileService(UserManager<ApplicationUser> userManager,
IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory,
ILogger<ProfileService> logger)
{
_userManager = userManager;
_claimsFactory = claimsFactory;
Logger = logger;
}
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var sub = context.Subject?.GetSubjectId();
if (sub == null) throw new Exception("No sub claim present");
var user = await _userManager.FindByIdAsync(sub);
if (user == null)
{
Logger?.LogWarning("No user found matching subject Id: {0}", sub);
}
else
{
var principal = await _claimsFactory.CreateAsync(user);
if (principal == null) throw new Exception("ClaimsFactory failed to create a principal");
context.IssuedClaims.AddRange(principal.Claims);
}
}
public async Task IsActiveAsync(IsActiveContext context)
{
var sub = context.Subject?.GetSubjectId();
if (sub == null) throw new Exception("No subject Id claim present");
var user = await _userManager.FindByIdAsync(sub);
if (user == null)
{
Logger?.LogWarning("No user found matching subject Id: {0}", sub);
}
context.IsActive = user != null;
}
}
在AuthorizationHandler
中访问声明时,用户具有以下声明
然而,在令牌上它有更多的主张
{
"iss": "https://localhost:5001",
"nbf": 1651829483,
"iat": 1651829483,
"exp": 1651829683,
"scope": [
"openid",
"profile",
"email"
],
"amr": [
"pwd"
],
"client_id": "Falcon_Identity_Server",
"sub": "9717a359-f83b-43b3-97b3-2f04f1148988",
"auth_time": 1651828196,
"idp": "local",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier": "9717a359-f83b-43b3-97b3-2f04f1148988",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": "admin@local.com",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress": "admin@local.com",
"AspNet.Identity.SecurityStamp": "1999ca9c-398d-4ffe-907a-b1f1b5e8cbfe",
"identityserver": "owner",
"fb_product": "owner",
"fb_order": "owner",
"fb_payment": "owner",
"sid": "215A4703E0D026F660C44D0BB7235EDA",
"jti": "D5989213C1F6D659141D57D07AC2EFDF"
}
注册以下jwt
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
// base-address of your identityserver
options.Authority = "https://localhost:5001";
// audience is optional, make sure you read the following paragraphs
// to understand your options
options.TokenValidationParameters.ValidateAudience = false;
// it's recommended to check the type header to avoid "JWT confusion" attacks
options.TokenValidationParameters.ValidTypes = new[] { "at+jwt" };
});
经办人
public class IdentityServerUserClaimHandler : AuthorizationHandler<IdentityServerUserClaimRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
IdentityServerUserClaimRequirement requirement)
{
if (context.User.HasClaim(c => c.Type == requirement.ClaimType &&
c.Value == requirement.ClaimValue))
context.Succeed(requirement);
return Task.CompletedTask;
}
}
1条答案
按热度按时间q3qa4bjr1#
默认情况下,ASP.NET不会将令牌中的所有声明传递给User(claimsPrincipal),因为它们中的大多数是内部OpenID-Connect声明。
要将声明放入User对象,则需要使用以下代码手动Map它们:
(In AddJwtBearer或AddOpenIdconnect)
为了补充这个答案,我写了一篇博客文章,更详细地介绍了这个主题:Debugging OpenID Connect claim problems in ASP.NET Core