Con Core 1.1, siguió el consejo de @ blowdart e implementó un middleware personalizado:
https://stackoverflow.com/a/31465227/29821
Funcionó así:
- Se ejecutó el middleware. Recogió un token de los encabezados de la solicitud.
- Verificó el token y, si es válido, construyó una identidad (ClaimsIdentity) que contenía múltiples reclamos que luego agregó a través de HttpContext.User.AddIdentity ();
- En ConfigureServices usando services.AddAuthorization, agregué una política para requerir el reclamo que proporciona el middleware.
- En los controladores / acciones, usaría [Authorize (Roles = "algún rol que agregó el middleware")]
Esto funciona de alguna manera con 2.0, excepto que si el token no es válido (paso 2 anterior) y la reclamación nunca se agrega, obtengo "No se especificó un esquema de autenticación y no se encontró un esquema de desafío predeterminado".
Así que ahora estoy leyendo que la autenticación cambió en 2.0:
https://docs.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x
¿Cuál es la ruta correcta para que yo haga lo mismo en ASP.NET Core 2.0? No veo un ejemplo para hacer una autenticación verdaderamente personalizada.
Respuestas:
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 laIAuthenticationHandler
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 extiendeAuthenticationHandler<>
), 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 un401 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 configurarDefaultAuthenticateScheme
yDefaultChallengeScheme
al usarservices.AddAuthentication(...)
.Aquí hay un ejemplo de cómo debería verse todo esto:
En Startup.cs / ConfigureServices () agregue:
services.AddAuthentication(options => { // the scheme name has to match the value we're going to use in AuthenticationBuilder.AddScheme(...) options.DefaultAuthenticateScheme = "Custom Scheme"; options.DefaultChallengeScheme = "Custom Scheme"; }) .AddCustomAuth(o => { });
En Startup.cs / Configure () agregue:
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) { // store custom services here... } protected override async Task<AuthenticateResult> HandleAuthenticateAsync() { // build the claims and put them in "Context"; you need to import the Microsoft.AspNetCore.Authentication package return AuthenticateResult.NoResult(); } }
fuente
DefaultAuthenticateScheme
yDefaultChallengeScheme
? No entiendo por qué se usan ambos. y cuáles son las diferencias entre ellos.AuthExtension
debe estar dentro delMicrosoft.Extensions.DependencyInjection
espacio de nombres. Vea este ejemplo: github.com/aspnet/Security/blob/rel/2.0.0/src/…Hay cambios considerables en la identidad de Core 1.xa Core 2.0, como señala el artículo al que hace referencia. El cambio principal es alejarse del enfoque de middleware y usar la inyección de dependencia para configurar servicios personalizados. Esto proporciona mucha más flexibilidad a la hora de personalizar Identity para implementaciones más complejas. Por lo tanto, desea alejarse del enfoque de middleware que mencionó anteriormente y avanzar hacia los servicios. Siga los pasos de migración en el artículo de referencia para lograr este objetivo. Comience reemplazando app.UseIdentity con app.UseAuthentication . UseIdentity está depreciado y no será compatible con versiones futuras. Para obtener un ejemplo completo de cómo insertar una transformación de notificaciones personalizada y realizar la autorización en la notificaciónver esta publicación de blog .
fuente