Entonces, después de un largo día tratando de resolver este problema, finalmente descubrí cómo Microsoft quiere que creemos controladores de autenticación personalizados para su nueva configuración de middleware único en core 2.0.
Después de revisar parte de la documentación de MSDN, encontré una clase llamada AuthenticationHandler<TOption>
que implementa la IAuthenticationHandler
interfaz.
A partir de ahí, encontré una base de código completa con los esquemas de autenticación existentes ubicados en https://github.com/aspnet/Security
Dentro de uno de estos, muestra cómo Microsoft implementa el esquema de autenticación JwtBearer. ( https://github.com/aspnet/Security/tree/master/src/Microsoft.AspNetCore.Authentication.JwtBearer )
Copié la mayor parte de ese código en una nueva carpeta y borré todas las cosas que tenían que ver con JwtBearer
.
En la JwtBearerHandler
clase (que se extiende AuthenticationHandler<>
), hay una anulación paraTask<AuthenticateResult> HandleAuthenticateAsync()
Agregué nuestro antiguo middleware para configurar reclamos a través de un servidor de tokens personalizado, y todavía tenía algunos problemas con los permisos, solo escupía un en 200 OK
lugar de un 401 Unauthorized
cuando un token no era válido y no se configuraron reclamos.
Me di cuenta de que había anulado lo Task HandleChallengeAsync(AuthenticationProperties properties)
que, por cualquier motivo, se usa para establecer permisos a través [Authorize(Roles="")]
de un controlador.
Después de eliminar esta anulación, el código había funcionado y se había lanzado con éxito 401
cuando los permisos no coincidían.
La principal conclusión de esto es que ahora no puede usar un middleware personalizado, debe implementarlo a través de AuthenticationHandler<>
y debe configurar DefaultAuthenticateScheme
y DefaultChallengeScheme
al usar services.AddAuthentication(...)
.
Aquí hay un ejemplo de cómo debería verse todo esto:
En Startup.cs / ConfigureServices () agregue:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = "Custom Scheme";
options.DefaultChallengeScheme = "Custom Scheme";
})
.AddCustomAuth(o => { });
En Startup.cs / Configure () agregue:
app.UseAuthentication();
Cree un nuevo archivo CustomAuthExtensions.cs
public static class CustomAuthExtensions
{
public static AuthenticationBuilder AddCustomAuth(this AuthenticationBuilder builder, Action<CustomAuthOptions> configureOptions)
{
return builder.AddScheme<CustomAuthOptions, CustomAuthHandler>("Custom Scheme", "Custom Auth", configureOptions);
}
}
Cree un nuevo archivo CustomAuthOptions.cs
public class CustomAuthOptions: AuthenticationSchemeOptions
{
public CustomAuthOptions()
{
}
}
Cree un nuevo archivo CustomAuthHandler.cs
internal class CustomAuthHandler : AuthenticationHandler<CustomAuthOptions>
{
public CustomAuthHandler(IOptionsMonitor<CustomAuthOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
{
}
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
return AuthenticateResult.NoResult();
}
}