Identity Server 4.令牌端点,密码授予。如何检查acr_values?

时间:2020-07-30 23:51:51

标签: identityserver4

我怀疑这很简单,但是我找不到我需要做的事情。

我正在尝试使用名称/密码/ SomethingExtra启用密码授予,令牌终结点

所有功能都仅使用名称和密码即可。我可以在服务器上的acr_values中看到“ Data:SomethingExtra”,但只能在GetProfileDataAsync覆盖中看到。

因此,我可以在令牌生成(GetProfileDataAsync)中获取acr_values,但是我想用这些额外的数据“验证”用户。如何在验证时测试我的acr_values?

我怀疑有一种方法可以覆盖额外的acr_values来获取“登录请求”,因此我可以决定返回令牌或拒绝访问,与使用Quickstart网页进行交互式登录一样。

但是我要覆盖哪些值才能对3个值进行身份验证?

2 个答案:

答案 0 :(得分:0)

如果您正在使用密码授予,那么您将实现IResourceOwnerPasswordValidator来验证密码。您可以在此类中获得acr值,如下所示:

public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context) {
    string acrValues = context.Request.Raw.Get("acr_values");
    IEnumerable<string> values = acrValues.Trim().Split(new[] { ' ' });
    string extraDataAcr = values.FirstOrDefault(x => x.StartsWith("ExtraData:"));
    string extraDataValue extraDataAcr?.Substring("ExtraData:".Length);

答案 1 :(得分:0)

经过一番挖掘...可能会节省一些时间

public class ACustomTokenRequestValidator : ICustomTokenRequestValidator
{
    private readonly UserManager<ApplicationUser> _userManager;

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

    public async Task ValidateAsync(CustomTokenRequestValidationContext context)
    {
        if (context?.Result?.ValidatedRequest?.GrantType != null &&
            context.Result.ValidatedRequest.GrantType.ToUpper() == "PASSWORD")  // Only interested in password Grant
        {
            var acr_values = new Dictionary<string, string>();

            string username = string.Empty;
            string error = string.Empty;
            string Tester = string.Empty;

            bool ok = true;

            if (context.Result.ValidatedRequest.Raw != null)
            {
                var reqParamsDict = context.Result.ValidatedRequest.Raw.ToDictionary();

                if (reqParamsDict.ContainsKey("acr_values"))
                {
                    var raw = reqParamsDict["acr_values"].Split(' ', StringSplitOptions.RemoveEmptyEntries).ToList();
                    acr_values = raw.Select(item => item.Split(':', 2, StringSplitOptions.RemoveEmptyEntries)).ToDictionary(s => s[0], s => s[1]);
                }

                if (reqParamsDict.ContainsKey("username"))   // Should always be there, name/password check would have failed already
                {
                    username = reqParamsDict["username"];
                }
                else
                {
                    ok = false;
                    error = "username missing from request";
                }

                if (ok && acr_values.ContainsKey("ExtraField"))   // Could be missing
                {
                    Tester = acr_values["ExtraField"];
                }
                else
                {
                    ok = false;
                    error = "ExtraField missing from request";
                }

                if (ok)
                {
                    if (context.Result.ValidatedRequest.Scopes.Contains("API_Name"))
                    {
                        var user = await _userManager.FindByNameAsync(username);

                        if (user != null)
                        {
                            if ( user.ExtraField != Tester )
                            { 
                                ok = false;
                                error = "Failed extra test";
                            }
                        }
                        else
                        {
                            ok = false;
                            error = "User not found";
                        }
                    }
                }
            }

            if (!ok)
            {
                context.Result.IsError = true;
                context.Result.Error = error;
            }
        }
    }
}

For completeness this is my Postman setup to get it working

  [https://i.stack.imgur.com/BtihJ.png][1]
相关问题