IdentityServer4令牌中的所有客户端范围

时间:2019-01-02 18:52:53

标签: identityserver4 identitymodel

我有一个使用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);

它将返回令牌中为客户端定义的所有范围。这已不再是这种情况。我该如何配置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";
    }

1 个答案:

答案 0 :(得分:1)

默认情况下,像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;
    }
}

然后只需将其注册到IdentityServerBuilder服务容器中即可。

        var builder = services.AddIdentityServer(options =>
        {
            //Your identity server options
        });

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

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