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 OnMessageReceivedevento. Esto me permite establecer tokenel 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 Userobjeto como lo necesito).
Pero para la primera llamada, OnMessageReceivedno se golpea. Y el Userobjeto en mi controlador no está configurado.
Verifiqué HttpContextesa primera llamada y el encabezado "X-JWT-Assertion" está en la Request.Headerslista (con el JWT en él). Pero, por alguna razón, el OnMessageReceivedevento no se requiere.
¿Cómo puedo OnMessageReceivedser llamado para la primera invocación de una operación de servicio para mi servicio?
NOTA IMPORTANTE: descubrí que el problema estaba async awaiten 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 AddJwtBearercon async awaitdonde está a la espera de una verdadera HttpClientllamada. O muestre la documentación de por qué async awaitno se debe utilizar AddJwtBearer.
async awaitno 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 OnMessageReceivedlambda sea asíncrona, mover su llamada http al OnMessageReceivedcuerpo y de alguna manera almacenar los resultados de la caché allí.