Estou usando o WSO2 como meu provedor de identidade (IDP). Ele está colocando o JWT em um cabeçalho chamado "X-JWT-Assertion".
Para alimentar isso no sistema ASP.NET Core, adicionei um OnMessageReceived
evento. Isso permite que eu defina token
o valor fornecido no cabeçalho.
Aqui está o código que eu tenho que fazer isso (a parte principal são as últimas 3 linhas do código que não está entre colchetes):
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;
}
}
};
Tudo isso funciona perfeitamente, exceto na primeira chamada após o início do serviço. Para ser claro, todas as chamadas, exceto a primeira, funcionam exatamente como eu quero. (Ele coloca o token e atualiza o User
objeto como eu preciso.)
Mas para a primeira chamada, o OnMessageReceived
não é atingido. E o User
objeto no meu controlador não está configurado.
Eu verifiquei HttpContext
a primeira chamada e o cabeçalho "X-JWT-Assertion" está na Request.Headers
lista (com o JWT). Mas, por alguma razão, o OnMessageReceived
evento não é necessário.
Como posso OnMessageReceived
ser chamado para a primeira chamada de uma operação de serviço para o meu serviço?
NOTA IMPORTANTE: eu descobri que o problema era async
await
no AddJwtBearer
. (Veja minha resposta abaixo.) Era isso que eu realmente queria fora desta questão.
No entanto, como uma recompensa não pode ser excluída, ainda a concederei a qualquer pessoa que possa mostrar uma maneira de usá AddJwtBearer
- async
await
la onde está aguardando uma HttpClient
ligação real . Ou mostre a documentação do motivo pelo qual async
await
não deve ser usado AddJwtBearer
.
async
await
não funcionar bem com o pipeline de chamadas.)
AddJwtBearer
(e subjacente AuthenticationBuilder.AddSchemeHelper
) não esperam chamadas assíncronas por lá - apenas adiciona IConfigureOptions aos serviços. OnMessageReceived
, por outro lado - está sendo aguardado em. Então, eu estou querendo saber se você poderia fazer esse OnMessageReceived
lambda assíncrono, mover sua chamada http para o OnMessageReceived
corpo e, de alguma forma, armazenar os resultados lá?