Я использую 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
никогда не вызывается. Другие решения, которые я нахожу для этой проблемы, обычно говорят, что вам нужно сделать ее схемой аутентификации по умолчанию, но я не хочу, чтобы это мешало настройке других внешних провайдеров входа в систему.
Есть ли Как я могу заставить это работать без изменения схемы аутентификации по умолчанию или добавления дополнительных атрибутов в мои контроллеры или действия?