Saltar al contenido

Usar múltiples autenticación de portador JWT

Recabamos en distintos espacios para traerte la solución a tu dilema, si continúas con dudas puedes dejar la inquietud y te responderemos con mucho gusto, porque estamos para ayudarte.

Solución:

Puedes lograr totalmente lo que quieres:

services
    .AddAuthentication()
    .AddJwtBearer("Firebase", options =>
    
        options.Authority = "https://securetoken.google.com/my-firebase-project"
        options.TokenValidationParameters = new TokenValidationParameters
        
            ValidateIssuer = true,
            ValidIssuer = "my-firebase-project"
            ValidateAudience = true,
            ValidAudience = "my-firebase-project"
            ValidateLifetime = true
        ;
    )
    .AddJwtBearer("Custom", options =>
    
        // Configuration for your custom
        // JWT tokens here
    );

services
    .AddAuthorization(options =>
    
        options.DefaultPolicy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .AddAuthenticationSchemes("Firebase", "Custom")
            .Build();
    );

Repasemos las diferencias entre su código y ese.

AddAuthentication no tiene parametro

Si establece un esquema de autenticación predeterminado, en cada solicitud individual, el middleware de autenticación intentará ejecutar el controlador de autenticación asociado con el esquema de autenticación predeterminado. Dado que ahora tenemos dos esquemas de autenticación posibles, no tiene sentido ejecutar uno de ellos.

Utilice otra sobrecarga de AddJwtBearer

Cada uno AddXXX El método para agregar una autenticación tiene varias sobrecargas:

  • Uno en el que se utiliza el esquema de autenticación predeterminado asociado con el método de autenticación, como puede ver aquí para la autenticación de cookies.
  • Uno donde se le pasa, además de la configuración de las opciones, el nombre del esquema de autenticación, como en esta sobrecarga

Ahora, debido a que usa el mismo método de autenticación dos veces pero los esquemas de autenticación deben ser únicos, debe usar la segunda sobrecarga.

Actualizar la política predeterminada

Dado que las solicitudes ya no se autenticarán automáticamente, poner [Authorize] attributes en algunas acciones resultará en el rechazo de las solicitudes y una HTTP 401 Será mencionado.

Dado que eso no es lo que queremos porque queremos dar a los controladores de autenticación la oportunidad de autenticar la solicitud, cambiamos la política predeterminada del sistema de autorización al indicar tanto el Firebase y Custom los esquemas de autenticación deben ser intentado para autenticar la solicitud.

Eso no impide que seas más restrictivo en algunas acciones; los [Authorize] attribute tiene un AuthenticationSchemes propiedad que le permite anular qué esquemas de autenticación son válidos.

Si tiene escenarios más complejos, puede utilizar la autorización basada en políticas. Creo que la documentación oficial es excelente.

Imaginemos que algunas acciones solo están disponibles para tokens JWT emitidos por Firebase y deben tener un reclamo con un valor específico; podrías hacerlo de esta manera:

// Authentication code omitted for brevity

services
    .AddAuthorization(options =>
    
        options.DefaultPolicy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .AddAuthenticationSchemes("Firebase", "Custom")
            .Build();

        options.AddPolicy("FirebaseAdministrators", new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .AddAuthenticationSchemes("Firebase")
            .RequireClaim("role", "admin")
            .Build());
    );

Entonces podrías usar [Authorize(Policy = "FirebaseAdministrators")] sobre algunas acciones.

Un último punto a tener en cuenta: si se está contagiando AuthenticationFailed eventos y usando cualquier cosa menos la primera AddJwtBearer política, usted puede ver IDX10501: Signature validation failed. Unable to match key... Esto se debe a que el sistema verifica cada AddJwtBearer a su vez hasta que consiga una coincidencia. Por lo general, el error se puede ignorar.

Esta es una extensión de la respuesta de Mickaël Derriey.

Nuestra aplicación tiene un requisito de autorización personalizado que resolvemos desde una fuente interna. Estábamos usando Auth0 pero estamos cambiando a la autenticación de la cuenta de Microsoft usando OpenID. Aquí está el código ligeramente editado de nuestro ASP.Net Core 2.1 Startup. Para futuros lectores, esto funciona a partir de este escrito para las versiones especificadas. La persona que llama usa el id_token de OpenID en las solicitudes entrantes pasadas como un token de portador. Espero que ayude a alguien más que intente hacer una conversión de autoridad de identidad tanto como esta pregunta y respuesta me ayudaron a mí.

const string Auth0 = nameof(Auth0);
const string MsaOpenId = nameof(MsaOpenId);

string domain = "https://myAuth0App.auth0.com/";
services.AddAuthentication()
        .AddJwtBearer(Auth0, options =>
            
                options.Authority = domain;
                options.Audience = "https://myAuth0Audience.com";
            )
        .AddJwtBearer(MsaOpenId, options =>
            
                options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                
                    ValidateAudience = true,
                    ValidAudience = "00000000-0000-0000-0000-000000000000",

                    ValidateIssuer = true,
                    ValidIssuer = "https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0",

                    ValidateIssuerSigningKey = true,
                    RequireExpirationTime = true,
                    ValidateLifetime = true,
                    RequireSignedTokens = true,
                    ClockSkew = TimeSpan.FromMinutes(10),
                ;
                options.MetadataAddress = "https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0/.well-known/openid-configuration";
            
        );

services.AddAuthorization(options =>

    options.DefaultPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .AddAuthenticationSchemes( Auth0, MsaOpenId )
        .Build();

    var approvedPolicyBuilder =  new AuthorizationPolicyBuilder()
           .RequireAuthenticatedUser()
           .AddAuthenticationSchemes(Auth0, MsaOpenId)
           ;

    approvedPolicyBuilder.Requirements.Add(new HasApprovedRequirement(domain));

    options.AddPolicy("approved", approvedPolicyBuilder.Build());
);

Finalizando este artículo puedes encontrar las notas de otros gestores de proyectos, tú igualmente puedes mostrar el tuyo si te apetece.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *