【问题标题】:RemoteAuthenticationHandler state and code_challenge verificationRemoteAuthenticationHandler 状态和 code_challenge 验证
【发布时间】:2022-10-06 00:13:39
【问题描述】:

我创建了 RemoteAuthenticationHandler,它看起来像这样:

public class AuthAndAuthHandler : RemoteAuthenticationHandler<AuthAndAuthSchemeOptions>

{
    public AuthAndAuthHandler(IOptionsMonitor<AuthAndAuthSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
        : base(options, logger, encoder, clock)
    {
    }

    protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
    {
        var rng = RandomNumberGenerator.Create();

        var state = new byte[128];
        var nonce = new byte[128];
        var codeVerifier = new byte[64];

        rng.GetBytes(state);
        rng.GetBytes(nonce);
        rng.GetBytes(codeVerifier);

        var codeChallenge = SHA256.HashData(codeVerifier);

        Response.Cookies.Append(\"Nonce\", Convert.ToBase64String(SHA256.HashData(nonce)), new CookieOptions
        {
            Path = \"/callback\",
            HttpOnly = true,
            IsEssential = true,
            Secure = true,
            SameSite = SameSiteMode.Strict,
            Expires = Clock.UtcNow.AddHours(1)
        });

        Response.Redirect($\"{Options.Authority}/authorization?client_id={Options.ClientId}\" +
            $\"&callback_uri={Request.Scheme}://{Request.Host}{Options.CallbackPath}&scopes={Options.Scopes}\" +
            $\"&state={Convert.ToBase64String(state)}&nonce={Convert.ToBase64String(nonce)}&code_challenge={Convert.ToBase64String(codeChallenge)}\");
    }

    protected override async Task<HandleRequestResult> HandleRemoteAuthenticateAsync()
    {
        throw new NotImplementedException();
    }
}

HandleRemoteAuthenticateAsync() 方法中,我必须验证状态,在远程授权成功后我会得到。当挑战之后我失去了早期生成的状态和代码验证器时,我该怎么做?

  • 可以分享更多代码吗?HandleChallengeAsync 方法是用来处理 401 挑战问题的,为什么你认证成功并进入这个方法?
  • 也许我含糊地表达了自己。假设是收到401后,我打电话给HandleChallengeAsync。如果用户在重定向到/authorization 后登录,他应该被重定向到/callback,这里会调用HandleRemoteAuthenticationAsync 方法。而现在我不知道如何验证状态参数,我将获得它作为查询参数 dla w /callback,因为我不再有权访问我在HandleChallengeAsync 中创建的状态。也许我的方式是错误的?

标签: c# asp.net-core asp.net-core-authenticationhandler


【解决方案1】:

根据状态,您可以使用Microsoft.AspNetCore.Authentication.ISecureDataFormat&lt;TData&gt; 进行验证。它可以定义为自定义选项中的属性(伪代码):

public class CustomRemoteOptions : RemoteAuthenticationOptions
{
    public CustomRemoteOptions()
    {
        var dataProtector = DataProtectionProvider.CreateProtector(
            typeof(CustomRemoteHandler).FullName);
        StateDataFormat = new PropertiesDataFormat(dataProtector);
    }

    internal ISecureDataFormat<AuthenticationProperties> StateDataFormat { get; }
}

然后在CustomRemoteHandler里面使用它:

public class CustomRemoteHandler : RemoteAuthenticationHandler<CustomRemoteOptions>
{
    protected override Task HandleChallengeAsync(AuthenticationProperties properties)
    {
        string state = Options.StateDataFormat.Protect(properties);
        // Then add the state to the URI.
    }
    
    protected override async Task<HandleRequestResult> HandleRemoteAuthenticateAsync()
    {
        var query = Request.Query;
        var state = query["state"];
    
        var properties = Options.StateDataFormat.Unprotect(state);
        if (properties == null)
        {
            return HandleRequestResult.Fail("The Custom authentication state was missing or invalid.");
        }
    }
}

笔记:如果您还需要验证关联 ID,则在 HandleChallengeAsync 中添加 GenerateCorrelationId(properties); 并在 HandleRemoteAuthenticateAsync 中添加以下行:

if (!ValidateCorrelationId(properties))
{
    return HandleRequestResult.Fail("Validation of correlation failed.", properties);
}

笔记:为了使代码可测试,您可以将StateDataFormat 的初始化移动到自定义IPostConfigureOptions 实现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-07
    相关资源
    最近更新 更多