0

我有一个使用 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";
    }
4

1 回答 1

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>();

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

于 2019-01-02T22:22:48.533 回答