Добавление пользовательского AuthenticationHandler в список внешних провайдеров входа - PullRequest
0 голосов
/ 04 февраля 2020

Я использую ASP. NET Core 3.1, и у меня настроено несколько внешних провайдеров входа:

services.AddAuthentication()
    .AddDeviantArt(d => {
        d.Scope.Add("feed");
        d.ClientId = Configuration["Authentication:DeviantArt:ClientId"];
        d.ClientSecret = Configuration["Authentication:DeviantArt:ClientSecret"];
        d.SaveTokens = true;
    })
    .AddTwitter(t => {
        t.ConsumerKey = Configuration["Authentication:Twitter:ConsumerKey"];
        t.ConsumerSecret = Configuration["Authentication:Twitter:ConsumerSecret"];
        t.SaveTokens = true;
    });

Я бы хотел создать пользовательский AuthenticationProvider, который вместо перенаправляя на другой сайт, запрашивает «ключ API» этого сайта и рассматривает его как маркер доступа. (Веб-сайт, о котором идет речь, не поддерживает ни одну версию OAuth.)

Прежде чем приступить к его подключению, я хочу проверить, можно ли вообще заставить работать пользовательский AuthenticationProvider, поэтому я нашел такую, которая реализует HTTP Basi c аутентификация:

public class CustomAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions> {
    public CustomAuthenticationHandler(
        IOptionsMonitor<AuthenticationSchemeOptions> options,
        ILoggerFactory logger,
        UrlEncoder encoder,
        ISystemClock clock)
        : base(options, logger, encoder, clock) { }

    protected override async Task<AuthenticateResult> HandleAuthenticateAsync() {
        if (!Request.Headers.ContainsKey("Authorization")) {
            return AuthenticateResult.NoResult();
        }

        if (!AuthenticationHeaderValue.TryParse(Request.Headers["Authorization"], out AuthenticationHeaderValue headerValue)) {
            return AuthenticateResult.NoResult();
        }

        if (!"Basic".Equals(headerValue.Scheme, StringComparison.OrdinalIgnoreCase)) {
            return AuthenticateResult.NoResult();
        }

        byte[] headerValueBytes = Convert.FromBase64String(headerValue.Parameter);
        string userAndPassword = Encoding.UTF8.GetString(headerValueBytes);
        string[] parts = userAndPassword.Split(':');
        if (parts.Length != 2) {
            return AuthenticateResult.Fail("Invalid Basic authentication header");
        }
        string user = parts[0];
        string password = parts[1];

        bool isValidUser = true;

        if (!isValidUser) {
            return AuthenticateResult.Fail("Invalid username or password");
        }
        var claims = new[] { new Claim(ClaimTypes.Name, user) };
        var identity = new ClaimsIdentity(claims, Scheme.Name);
        var principal = new ClaimsPrincipal(identity);
        var ticket = new AuthenticationTicket(principal, Scheme.Name);
        return AuthenticateResult.Success(ticket);
    }

    protected override async Task HandleChallengeAsync(AuthenticationProperties properties) {
        Response.Headers["WWW-Authenticate"] = $"Basic realm=\"Custom realm name here\", charset=\"UTF-8\"";
        await base.HandleChallengeAsync(properties);
    }
}

Я добавил это в Startup.cs:

.AddScheme<AuthenticationSchemeOptions, CustomAuthenticationHandler>("Test", "Testing", o => { })

Проблема в том, что метод HandleAuthenticateAsync никогда не вызывается. Другие решения, которые я нахожу для этой проблемы, обычно говорят, что вам нужно сделать ее схемой аутентификации по умолчанию, но я не хочу, чтобы это мешало настройке других внешних провайдеров входа в систему.

Есть ли Как я могу заставить это работать без изменения схемы аутентификации по умолчанию или добавления дополнительных атрибутов в мои контроллеры или действия?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...