Adding claims to IdentityServer setup by AddIdentityServer
我有一个SPA,它具有ASP.NET Core Web API以及使用
1 2 3 4 | services.AddIdentityServer() .AddApiAuthorization<User, UserDataContext>(); services.AddAuthentication() .AddIdentityServerJwt(); |
我还具有需要"管理员"角色声明的授权策略设置:
1 2 3 4 | services.AddAuthorization(options => { options.AddPolicy("IsAdmin", policy => policy.RequireClaim(ClaimTypes.Role,"Admin")); }); |
我有一个使用此策略的控制器操作
1 2 3 4 5 6 | [Authorize(Policy ="IsAdmin")] [HttpDelete("{id}")] public IActionResult Deleten(int id) { ... } |
经过身份验证的用户确实具有"管理员"角色声明:
该身份验证用户的访问令牌似乎不包含管理员声明:
尝试向管理员用户请求此资源时,我收到了403的回信:
因此,如果我正确理解这一点,则IdentityServer不包括管理员角色声明,因此用户无权访问该资源。
是否可以使用
在Identity Server方面,可以创建配置文件服务,以在颁发令牌时使IDS4包含
您可以从ClaimsPrincipal获取角色声明,或者从数据库获取角色并创建个人档案服务,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public class MyProfileService : IProfileService { public MyProfileService() { } public Task GetProfileDataAsync(ProfileDataRequestContext context) { //get role claims from ClaimsPrincipal var roleClaims = context.Subject.FindAll(JwtClaimTypes.Role); //add your role claims context.IssuedClaims.AddRange(roleClaims); return Task.CompletedTask; } public Task IsActiveAsync(IsActiveContext context) { // await base.IsActiveAsync(context); return Task.CompletedTask; } } |
并在Startup.cs中注册:
1 | services.AddTransient<IProfileService, MyProfileService>(); |
在客户端,您应该从JWT令牌映射角色声明,并尝试在
1 2 | options.ClaimActions.MapJsonKey("role","role","role"); options.TokenValidationParameters.RoleClaimType ="role"; |
然后,您的api可以验证访问令牌并使用角色策略进行授权。
我这样做时没有使用角色,而是使用了添加到用户令牌中的特殊声明。 我创建了一个CustomUserClaimsPrincipalFactory,这使我可以向用户添加其他声明。
寄存器
1 | services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, CustomUserClaimsPrincipalFactory>(); |
代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | public class CustomUserClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser, IdentityRole<long>> { public CustomUserClaimsPrincipalFactory( UserManager<ApplicationUser> userManager, RoleManager<IdentityRole<long>> roleManager, IOptions<IdentityOptions> optionsAccessor) : base(userManager, roleManager, optionsAccessor) { } protected override async Task<ClaimsIdentity> GenerateClaimsAsync(ApplicationUser user) { var userId = await UserManager.GetUserIdAsync(user); var userName = await UserManager.GetUserNameAsync(user); var id = new ClaimsIdentity("Identity.Application", Options.ClaimsIdentity.UserNameClaimType, Options.ClaimsIdentity.RoleClaimType); id.AddClaim(new Claim(Options.ClaimsIdentity.UserIdClaimType, userId)); id.AddClaim(new Claim(Options.ClaimsIdentity.UserNameClaimType, user.Name)); id.AddClaim(new Claim("preferred_username", userName)); id.AddClaim(new Claim("culture", user.Culture ??"da-DK")); if (UserManager.SupportsUserSecurityStamp) { id.AddClaim(new Claim(Options.ClaimsIdentity.SecurityStampClaimType, await UserManager.GetSecurityStampAsync(user))); } if (UserManager.SupportsUserClaim) { id.AddClaims(await UserManager.GetClaimsAsync(user)); } if(user.IsXenaSupporter) id.AddClaim(new Claim("supporter", user.Id.ToString())); return id; } } |
政策
1 2 3 4 | services.AddAuthorization(options => { options.AddPolicy("Supporter", policy => policy.RequireClaim("supporter")); }); |
用法
1 2 3 4 5 6 7 8 | [Authorize(AuthenticationSchemes ="Bearer", Policy ="Supporter")] [HttpPost("supporter")] public async Task<ActionResult> ChangeToSpecificUser([FromBody] ChangeUserRequest request) { // .................. } |