如何将创建的用户声明传递给客户端

How to pass created user claims to client

我在 AspNetUserClaims table 中创建了多个身份声明,并将它们分配给了我的用户 ID。

我目前正在努力使这些在我的客户端应用程序中收到的索赔列表中生效。

我通过将 'roles' 范围添加到我的客户端身份设置然后在身份配置中(使用 EF数据库格式 a.k.a ConfigurationDbContext) 在 IdentityResources table 中创建了一条记录,它链接到名为 'role'.

的身份声明

这是按预期工作的。但是,我没有收到我创建的任何 UserClaims,我是否需要创建另一个特定范围?

这是我的客户端配置:

services.AddAuthentication(options =>
    {
        options.DefaultScheme = "cookie";
        options.DefaultChallengeScheme = "oidc";
    })
    .AddCookie("cookie")
    .AddOpenIdConnect("oidc", options =>
    {
        options.Authority = "https://localhost:44335/";
        options.ClientId = "openIdConnectClient";
        options.SignInScheme = "cookie";
        options.ResponseType = "id_token";
        options.GetClaimsFromUserInfoEndpoint = true;
        options.Scope.Add("openid profile roles all_claims");
    });

services.AddAuthorization();

这就是我检查用户拥有的声明的方式:

var claims = ((ClaimsIdentity)User.Identity).Claims;

它 returns 所有角色和配置文件声明(例如 preferred_username)只是不是在 AspNetUserClaims table.

中指定的那些

对于我的客户,我也将 属性 [AlwaysIncludeUserClaimsInIdToken] 设置为 true 但没有成功。

有谁知道我在通过用户声明时缺少什么?

您可以获得这样的用户声明:

var claims = User.Claims.Select(c => new { c.Type, c.Value });

您可以将其实现为您 api 中的端点,您在身份服务器中将其声明为范围:

using IdentityServer4;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Linq;

namespace IdentityServer4Demo.Api
{
    [Route("/api/test")]
    [Authorize]
    public class TestController : ControllerBase
    {
        public IActionResult Get()
        {
            var claims = User.Claims.Select(c => new { c.Type, c.Value });
            return new JsonResult(claims);
        }
    }
}

如果您想添加更多声明,您需要将 属性 添加到实现 IdentityUser 的 class 并在您的自定义配置文件服务中使用它

using Microsoft.AspNetCore.Identity;

namespace AuthServer.Infrastructure.Data.Identity
{
    public class AppUser : IdentityUser
    {
        // Add additional profile data for application users by adding properties to this class
        public string Name { get; set; }        
    }
}

您的自定义配置文件服务:

using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using AuthServer.Infrastructure.Constants;
using AuthServer.Infrastructure.Data.Identity;
using IdentityModel;
using IdentityServer4;
using IdentityServer4.Extensions;
using IdentityServer4.Models;
using IdentityServer4.Services;
using Microsoft.AspNetCore.Identity;

namespace AuthServer.Infrastructure.Services
{
    public class IdentityClaimsProfileService : IProfileService
    {
        private readonly IUserClaimsPrincipalFactory<AppUser> _claimsFactory;
        private readonly UserManager<AppUser> _userManager;

        public IdentityClaimsProfileService(UserManager<AppUser> userManager, IUserClaimsPrincipalFactory<AppUser> claimsFactory)
        {
            _userManager = userManager;
            _claimsFactory = claimsFactory;
        }

        public async Task GetProfileDataAsync(ProfileDataRequestContext context)
        {
            var sub = context.Subject.GetSubjectId();
            var user = await _userManager.FindByIdAsync(sub);
            var principal = await _claimsFactory.CreateAsync(user);

            var claims = principal.Claims.ToList();
            claims = claims.Where(claim => context.RequestedClaimTypes.Contains(claim.Type)).ToList();
            claims.Add(new Claim(JwtClaimTypes.GivenName, user.Name));
            claims.Add(new Claim(IdentityServerConstants.StandardScopes.Email, user.Email));
            // note: to dynamically add roles (ie. for users other than consumers - simply look them up by sub id
            claims.Add(new Claim(ClaimTypes.Role, Roles.Consumer)); // need this for role-based authorization - 

            context.IssuedClaims = claims;
        }
}

您是否有 IProfileService 实现来填充您的自定义声明?

您应该按照 中的说明实施 IProfileService

尝试 response_type 而不是 id_token,因为您的应用程序没有访问令牌来调用用户信息端点。也许与 id_token token 保持客户的隐式流量授权。