IdentityServer4令牌中的所有客户端作用域

IdentityServer4令牌中的所有客户端作用域,identityserver4,identitymodel,Identityserver4,Identitymodel,我有一个带有IdentityServer4实现的多租户应用程序。我最近将其更新为最新的ID4,行为似乎已经改变。以前,我可以在IdentityModel包中使用TokenClient发出请求: var parameters = new Dictionary<string, string>(); parameters.Add("username", loginModel.UserName); parameters.Add("password", loginModel.Password

我有一个带有IdentityServer4实现的多租户应用程序。我最近将其更新为最新的ID4,行为似乎已经改变。以前,我可以在IdentityModel包中使用TokenClient发出请求:

var parameters = new Dictionary<string, string>();

parameters.Add("username", loginModel.UserName);
parameters.Add("password", loginModel.Password);
var tokenClient = new TokenClient(new Uri(new Uri(accountsConfig.EndpointUrl), "/connect/token").ToString(), accountsConfig.ClientId, accountsConfig.Secret,  null, AuthenticationStyle.PostValues); 

var tokenResponse = await tokenClient.RequestCustomGrantAsync("AgentLogin", extra: parameters);
var参数=新字典();
添加参数(“用户名”,loginModel.username);
添加参数(“密码”,loginModel.password);
var tokenClient=new tokenClient(新Uri(新Uri(accountsConfig.EndpointUrl),“/connect/token”).ToString()、accountsConfig.ClientId、accountsConfig.Secret、null、AuthenticationStyle.PostValues);
var tokenResponse=wait tokenClient.RequestCustomGrantAsync(“AgentLogin”,额外:参数);
它将返回令牌中为客户机定义的所有作用域。情况不再如此。我如何配置ID4来做到这一点,而不在TokenClient内部显式请求它们

public class AgentLoginCustomGrantValidator : IExtensionGrantValidator
    {
        private readonly ILogger<AgentLoginCustomGrantValidator> _logger;
        private readonly IAdminUserService _adminUserService;

        public AgentLoginCustomGrantValidator(ILogger<AgentLoginCustomGrantValidator> logger, IAdminUserService adminUserService)
        {
            _logger = logger;
            _adminUserService = adminUserService;
        }

        public async Task ValidateAsync(ExtensionGrantValidationContext context)
        {
            try
            {
                var username = context.Request.Raw.Get("username");
                var password = context.Request.Raw.Get("password");

                var userId = _adminUserService.AuthenticateUser(username, password);


                if (userId != null)
                {
                    var agencyUser = _adminUserService.GetUser(userId.Value);
                    context.Result = new GrantValidationResult($"{userId}", GrantType, agencyUser.Roles.Select(x => new Claim(JwtClaimTypes.Role, x.Name)).Concat(new List<Claim>() { new Claim(JwtClaimTypes.Name, agencyUser.UserName) { } }));

                }
                else
                {
                    _logger.LogWarning($"Bum creds: {username} ");
                    context.Result = new GrantValidationResult(TokenRequestErrors.InvalidClient, "Invalid credentials");
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.ToString());
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidClient, ex.Message);

            }
        }

        public string GrantType => "AgentLogin";
    }
公共类代理LogincustomGrantValidator:IExtensionGrantValidator
{
专用只读ILogger\u记录器;
私有只读IADMINSERSERVICE\u adminUserService;
公共代理logincustomgrantvalidator(ILogger记录器、IAdminUserService adminUserService)
{
_记录器=记录器;
_adminUserService=adminUserService;
}
公共异步任务ValidateAsync(ExtensionGrantValidationContext上下文)
{
尝试
{
var username=context.Request.Raw.Get(“用户名”);
var password=context.Request.Raw.Get(“密码”);
var userId=\u adminUserService.AuthenticateUser(用户名、密码);
if(userId!=null)
{
var agencyUser=\u adminUserService.GetUser(userId.Value);
context.Result=new GrantValidationResult($“{userId}”,GrantType,agencyUser.Roles.Select(x=>newclaim(JwtClaimTypes.Role,x.Name)).Concat(new List(){newclaim(JwtClaimTypes.Name,agencyUser.UserName){});
}
其他的
{
_logger.LogWarning($“Bum creds:{username}”);
context.Result=新的GrantValidationResult(TokenRequestErrors.InvalidClient,“无效凭据”);
}
}
捕获(例外情况除外)
{
_logger.LogError(例如ToString());
context.Result=new GrantValidationResult(TokenRequestErrors.InvalidClient,ex.Message);
}
}
公共字符串GrantType=>“AgentLogin”;
}

默认情况下,Identity Server 4似乎只返回每个客户端请求的标识或api资源。但是,可以轻松重写此行为以返回所有作用域,而不管它们是否在令牌请求中被请求。您可以创建一个
CustomClaimsService
,该服务继承自
DefaultClaimsService

public class CustomClaimsService : DefaultClaimsService
{
    public CustomClaimsService(IProfileService profile, ILogger<DefaultClaimsService> logger) : base(profile, logger)
    {
    }

    public override async Task<IEnumerable<Claim>> GetAccessTokenClaimsAsync(ClaimsPrincipal subject,
        Resources resources, ValidatedRequest request)
    {
        var baseResult = await base.GetAccessTokenClaimsAsync(subject, resources, request);
        var outputClaims = baseResult.ToList();

        //If there are any allowed scope claims that are not yet in the output claims - add them
        foreach (var allowedClientScope in request.Client.AllowedScopes)
        {
            if (!outputClaims.Any(x => x.Type == JwtClaimTypes.Scope && x.Value == allowedClientScope))
            {
                outputClaims.Add(new Claim(JwtClaimTypes.Scope, allowedClientScope));
            }
        }

        return outputClaims;
    }
}

每个访问令牌现在将包含给定客户端允许的所有作用域。

请共享您的自定义授权代码。@VidmantasBlazevicius done情况不再是这样了吗?你是说TokenClient现在已经过时了?
        var builder = services.AddIdentityServer(options =>
        {
            //Your identity server options
        });

        //Register the custom claims service with the service container
        builder.Services.AddTransient<IClaimsService, CustomClaimsService>();