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.