Estoy usando WSO2 como mi proveedor de identidad (IDP). Está poniendo el JWT en un encabezado llamado "X-JWT-Assertion".
Para alimentar esto al sistema ASP.NET Core, agregué un OnMessageReceived
evento. Esto me permite establecer token
el valor proporcionado en el encabezado.
Aquí está el código que tengo que hacer eso (la parte clave son las últimas 3 líneas de código sin paréntesis):
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie()
.AddJwtBearer(async options =>
{
options.TokenValidationParameters =
await wso2Actions.JwtOperations.GetTokenValidationParameters();
options.Events = new JwtBearerEvents()
{
// WSO2 sends the JWT in a different field than what is expected.
// This allows us to feed it in.
OnMessageReceived = context =>
{
context.Token = context.HttpContext.Request.Headers["X-JWT-Assertion"];
return Task.CompletedTask;
}
}
};
Todo esto funciona perfectamente, excepto la primera llamada después de que se inicia el servicio. Para ser claros, cada llamada, excepto la primera, funciona exactamente como yo quiero. (Pone el token y actualiza el User
objeto como lo necesito).
Pero para la primera llamada, OnMessageReceived
no se golpea. Y el User
objeto en mi controlador no está configurado.
Verifiqué HttpContext
esa primera llamada y el encabezado "X-JWT-Assertion" está en la Request.Headers
lista (con el JWT en él). Pero, por alguna razón, el OnMessageReceived
evento no se requiere.
¿Cómo puedo OnMessageReceived
ser llamado para la primera invocación de una operación de servicio para mi servicio?
NOTA IMPORTANTE: descubrí que el problema estaba async
await
en AddJwtBearer
. (Vea mi respuesta a continuación.) Eso es lo que realmente quería de esta pregunta.
Sin embargo, desde una recompensa no puede ser cancled, yo todavía otorgará la recompensa a cualquiera que pueda demostrar una manera de utilizar AddJwtBearer
con async
await
donde está a la espera de una verdadera HttpClient
llamada. O muestre la documentación de por qué async
await
no se debe utilizar AddJwtBearer
.
async
await
no funcionaba bien con el
AddJwtBearer
(y subyacente AuthenticationBuilder.AddSchemeHelper
) no espera llamadas asíncronas allí, solo agrega IConfigureOptions a los servicios. OnMessageReceived
, por otro lado, se está esperando. Entonces, me pregunto si podría hacer que esa OnMessageReceived
lambda sea asíncrona, mover su llamada http al OnMessageReceived
cuerpo y de alguna manera almacenar los resultados de la caché allí.