.net core 在客户端向委托人添加自定义索赔(用于授权)

.net core 在客户端向委托人添加自定义索赔(用于授权),.net-core,identityserver4,asp.net-core-3.1,.net Core,Identityserver4,Asp.net Core 3.1,我已经能够在.net core 3.1上成功地实现我自己的IdentityServer 4身份验证服务器,并且我有一个客户端web应用程序连接到它。客户端正在成功接收访问令牌和id。令牌包含所有用户标识信息 我的下一个目标是将用户在客户机中拥有的特权添加到HttpContext.user as声明,在我获得令牌之后,在呈现任何其他页面之前。权限存储在主体ID与用户关联的数据库中 我需要在何处寻找能够添加这些声明的帮助,以便我的授权策略能够处理委托人中的声明。我希望该进程在每次发出令牌时都执行 另

我已经能够在.net core 3.1上成功地实现我自己的IdentityServer 4身份验证服务器,并且我有一个客户端web应用程序连接到它。客户端正在成功接收访问令牌和id。令牌包含所有用户标识信息

我的下一个目标是将用户在客户机中拥有的特权添加到HttpContext.user as声明,在我获得令牌之后,在呈现任何其他页面之前。权限存储在主体ID与用户关联的数据库中

我需要在何处寻找能够添加这些声明的帮助,以便我的授权策略能够处理委托人中的声明。我希望该进程在每次发出令牌时都执行

另外,我正在使用GetClaimsFromUserInfoEndpoint=true和SaveTokens=true的Identity server代码流


谢谢

您可以通过使用TokenValidated事件来实现这一点

    public class CustomJwtBearerEvents : JwtBearerEvents
{
    public override async Task TokenValidated(TokenValidatedContext context)
    {
        var claims = context.Principal.Claims.ToList();
        claims.Add(new Claim("key", "value"));
        context.Principal = new ClaimsPrincipal(new ClaimsIdentity(claims, "Bearer"));        }
}
然后在启动中注册它

        services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
            {
              ...
                options.Events = new JwtBearerEvents();
                options.EventsType = typeof(CustomJwtBearerEvents);
            });

您可以在identityServer4中使用Profile sevise:

 services .AddIdentityServer(x =>
            {
                x.IssuerUri = "null";
                x.Authentication.CookieLifetime = TimeSpan.FromDays(10);
            })
.
.
.          
              .AddProfileService<ProfileService>();
services.AddIdentityServer(x=>
{
x、 IssuerUri=“null”;
x、 Authentication.CookieLifetime=TimeSpan.FromDays(10);
})
.
.
.          
.AddProfileService();
这是一个很好的参考: ProfileService可以类似于以下代码模板:

public class ProfileService : IProfileService
{
    private readonly UserManager<ApplicationUser> _userManager;


    public ProfileService(UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;

    }

    public async Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        var subject = context.Subject ?? throw new ArgumentNullException(nameof(context.Subject));

        var subjectId = subject.Claims.Where(x => x.Type == "sub").FirstOrDefault().Value;

        var user = await _userManager.FindByIdAsync(subjectId);
        if (user == null)
            throw new ArgumentException("Invalid subject identifier");

        var claims = GetClaimsFromUser(user,subject);
        context.IssuedClaims = claims.Result.ToList();
    }

    public async Task IsActiveAsync(IsActiveContext context)
    {
        var subject = context.Subject ?? throw new ArgumentNullException(nameof(context.Subject));

        var subjectId = subject.Claims.Where(x => x.Type == "sub").FirstOrDefault().Value;
        var user = await _userManager.FindByIdAsync(subjectId);

        context.IsActive = false;

        if (user != null)
        {
            if (_userManager.SupportsUserSecurityStamp)
            {
                var security_stamp = subject.Claims.Where(c => c.Type == "security_stamp").Select(c => c.Value).SingleOrDefault();
                if (security_stamp != null)
                {
                    var db_security_stamp = await _userManager.GetSecurityStampAsync(user);
                    if (db_security_stamp != security_stamp)
                        return;
                }
            }

            context.IsActive =
                !user.LockoutEnabled ||
                !user.LockoutEnd.HasValue ||
                user.LockoutEnd <= DateTime.Now;
        }
    }

    private async Task<IEnumerable<Claim>> GetClaimsFromUser(ApplicationUser user,ClaimsPrincipal subject)
    {
        var claims = new List<Claim>
        {
            new Claim(JwtClaimTypes.Subject, user.Id),
            new Claim(JwtClaimTypes.PreferredUserName, user.UserName),
            new Claim(JwtRegisteredClaimNames.UniqueName, user.UserName)

        };

        if (!string.IsNullOrWhiteSpace(user.Name))
            claims.Add(new Claim("name", user.Name));

        if (!string.IsNullOrWhiteSpace(user.LastName))
            claims.Add(new Claim("last_name", user.LastName));


        return claims;
    }
}
public类ProfileService:IProfileService
{
私有只读用户管理器_UserManager;
公共配置文件服务(UserManager UserManager)
{
_userManager=userManager;
}
公共异步任务GetProfileDataAsync(ProfileDataRequestContext上下文)
{
var subject=context.subject??抛出新ArgumentNullException(nameof(context.subject));
var subjectId=subject.Claims.Where(x=>x.Type==“sub”).FirstOrDefault()值;
var user=await\u userManager.FindByIdAsync(subjectId);
if(user==null)
抛出新ArgumentException(“无效的主题标识符”);
var索赔=GetClaimsFromUser(用户,主体);
context.IssuedClaims=claims.Result.ToList();
}
公共异步任务IsActiveAsync(IsActiveContext上下文)
{
var subject=context.subject??抛出新ArgumentNullException(nameof(context.subject));
var subjectId=subject.Claims.Where(x=>x.Type==“sub”).FirstOrDefault()值;
var user=await\u userManager.FindByIdAsync(subjectId);
context.IsActive=false;
如果(用户!=null)
{
if(_userManager.SupportsUserSecurityStamp)
{
var security_stamp=subject.Claims.Where(c=>c.Type==“security_stamp”)。选择(c=>c.Value.SingleOrDefault();
如果(安全戳!=null)
{
var db_security_stamp=wait_userManager.GetSecurityStampAsync(用户);
if(db_安全戳!=安全戳)
返回;
}
}
context.IsActive=
!user.LockoutEnabled||
!user.LockoutEnd.HasValue||

user.LockoutEnd这将是在Identity Server中,其中没有存储权限。我需要客户端上的一些东西,能够检索SubjectId并根据客户端信息向令牌添加其他声明。因此,感谢您让我走上了正确的方向。我最终使用了基于以下信息的本文关于你提供的()