c# authentication asp.net-core asp.net-core-2.0

c# - ASP.NET Core 2.0 middleware de autenticación



authentication asp.net-core (2)

Con Core 1.1 siguió los consejos de @ blowdart e implementó un middleware personalizado:

https://stackoverflow.com/a/31465227/29821

Funcionó así:

  1. Middleware corrió. Recogió un token de los encabezados de solicitud.
  2. Verificó el token y, si es válido, creó una identidad (ClaimsIdentity) que contenía múltiples reclamos que luego se agregó a través de HttpContext.User.AddIdentity ();
  3. En ConfigureServices usando services.AddAuthorization, agregué una política para exigir el reclamo que proporciona el middleware.
  4. En los controladores / acciones, usaría [Authorize (Roles = "alguna función 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 el reclamo nunca se agrega, obtengo "No se especificó el esquema de autenticación, y no se encontró DefaultChallengeScheme".

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 el camino correcto para que yo haga lo mismo en ASP.NET Core 2.0? No veo un ejemplo para hacer una autenticación verdaderamente personalizada.


Entonces, después de un largo día tratando de resolver este problema, finalmente descubrí cómo Microsoft quiere que hagamos controladores de autenticación personalizados para su nueva configuración de middleware único en el núcleo 2.0.

Después de revisar parte de la documentación en MSDN, encontré una clase llamada AuthenticationHandler<TOption> que implementa la interfaz IAuthenticationHandler .

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 JwtBearer todas las cosas que tienen que ver con JwtBearer .

En la clase JwtBearerHandler (que extiende AuthenticationHandler<> ), hay una anulación para la Task<AuthenticateResult> HandleAuthenticateAsync()

Agregué nuestro antiguo middleware para configurar reclamos a través de un servidor de tokens personalizado, y todavía encontraba algunos problemas con los permisos, solo escupí un 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 Task HandleChallengeAsync(AuthenticationProperties properties) que, por cualquier motivo, se utiliza para establecer permisos a través de [Authorize(Roles="")] en un controlador.

Después de eliminar esta anulación, el código funcionó y arrojó con éxito un 401 cuando los permisos no coincidían.

La conclusión principal de esto es que ahora no puede usar un middleware personalizado, debe implementarlo a través de AuthenticationHandler<> y debe configurar DefaultAuthenticateScheme y DefaultChallengeScheme cuando usa services.AddAuthentication(...) .

Aquí hay un ejemplo de cómo debería ser 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:

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) { // 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(); } }


Hay cambios considerables en Identity de Core 1.x a 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 para personalizar Identity para implementaciones más complejas. Por lo tanto, desea alejarse del enfoque de middleware que menciona anteriormente y avanzar hacia los servicios. Siga los pasos de migración en el artículo referenciado para lograr este objetivo. Comience reemplazando app.UseIdentity con app.UseAuthentication . UseIdentity se deprecia y no se admitirá en futuras versiones. Para ver un ejemplo completo de cómo insertar una transformación de reclamos personalizada y realizar una autorización en el reclamo, vea esta publicación de blog .