Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Ao chamar uma API Web do ASP.NET Core protegida usando a autenticação da ID do Microsoft Entra, você pode encontrar um erro "401 Não autorizado". Este artigo fornece diretrizes para usar JwtBearerEvents
para capturar logs detalhados para solucionar esses erros.
Sintomas
Use o [Authorize]
atributo para proteger sua API Web do ASP.NET Core, da seguinte maneira:
[Authorize]
public class MyController : ControllerBase
{
...
}
Ou
public class MyController : ControllerBase
{
[Authorize]
public ActionResult<string> Get(int id)
{
return "value";
}
...
}
Quando você chama a API Web, uma resposta "401 Não autorizada" é retornada, mas a mensagem não contém detalhes de erro.
Motivo
A API pode retornar uma resposta "401 Não autorizada" nos seguintes cenários:
- A solicitação não inclui um cabeçalho de token válido "Autorização: Portador".
- O token expirou ou está incorreto:
- O token é emitido para um recurso diferente.
- As declarações de token não atendem aos critérios de validação de token do aplicativo, conforme definido na classe JwtBearerOptions.TokenValidationParameters .
Solução
Para depurar e resolver erros "401 Não Autorizado", utilize os JwtBearerEvents
callbacks para capturar e registrar informações detalhadas sobre o erro. Siga estas etapas para implementar um mecanismo personalizado de tratamento de erros.
A JwtBearerEvents
classe tem as seguintes propriedades de retorno de chamada (invocadas na seguinte ordem) que podem ajudá-lo a depurar esses problemas de "Erro 401: Acesso Negado" ou "Não Autorização":
-
OnMessageRecieved
é chamado primeiro para cada solicitação. -
OnAuthenticationFailed
será chamado se o token não passar nos critérios de validação de token do aplicativo. -
OnChallenge
é chamado por último antes de uma resposta "401" ser retornada.
Etapa 1: Habilitar o registro em log de PII
Por padrão, o registro em log de PII (informações de identificação pessoal) está desabilitado. Habilite-o no método Configurar do arquivo Startup.cs para depuração.
Cuidado
Utilize 'Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true' somente em um ambiente de desenvolvimento para depuração. Não o use em um ambiente de produção.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You might want to change this value for production scenarios. See https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
// turn on PII logging
Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseMvc();
}
Etapa 2: Criar um método utilitário para formatar mensagens de exceção
Adicione um método para formatar e nivele as mensagens de exceção para obter melhor legibilidade:
public static string FlattenException(Exception exception)
{
var stringBuilder = new StringBuilder();
while (exception != null)
{
stringBuilder.AppendLine(exception.Message);
stringBuilder.AppendLine(exception.StackTrace);
exception = exception.InnerException;
}
return stringBuilder.ToString();
}
Etapa 3: Implementar retornos de chamada JwtBearerEvents
Configure os JwtBearerEvents
callbacks no ConfigureServices
método de Startup.cs para lidar com eventos de autenticação e detalhes de erro no log.
public void ConfigureServices(IServiceCollection services)
{
....
.AddJwtBearer(options =>
{
options.Authority = "https://login.microsoftonline.com/<Tenant>.onmicrosoft.com";
// if you intend to validate only one audience for the access token, you can use options.Audience instead of
// using options.TokenValidationParameters which allow for more customization.
// options.Audience = "10e569bc5-4c43-419e-971b-7c37112adf691";
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidAudiences = new List<string> { "<Application ID URI>", "10e569bc5-4c43-419e-971b-7c37112adf691" },
ValidIssuers = new List<string> { "https://sts.windows.net/<Directory ID>/", "https://sts.windows.net/<Directory ID>/v2.0" }
};
options.Events = new JwtBearerEvents
{
OnAuthenticationFailed = ctx =>
{
ctx.Response.StatusCode = StatusCodes.Status401Unauthorized;
message += "From OnAuthenticationFailed:\n";
message += FlattenException(ctx.Exception);
return Task.CompletedTask;
},
OnChallenge = ctx =>
{
message += "From OnChallenge:\n";
ctx.Response.StatusCode = StatusCodes.Status401Unauthorized;
ctx.Response.ContentType = "text/plain";
return ctx.Response.WriteAsync(message);
},
OnMessageReceived = ctx =>
{
message = "From OnMessageReceived:\n";
ctx.Request.Headers.TryGetValue("Authorization", out var BearerToken);
if (BearerToken.Count == 0)
BearerToken = "no Bearer token sent\n";
message += "Authorization Header sent: " + BearerToken + "\n";
return Task.CompletedTask;
},
#For completeness, the sample code also implemented the OnTokenValidated property to log the token claims. This method is invoked when authentication is successful
OnTokenValidated = ctx =>
{
Debug.WriteLine("token: " + ctx.SecurityToken.ToString());
return Task.CompletedTask;
}
};
});
...
}
Resultados de exemplo
Quando você implementa JwtBearerEvents
retornos de chamada, se ocorrer um erro "401 Não autorizado", a saída da resposta deverá incluir detalhes, conforme o exemplo a seguir:
OnMessageRecieved:
Authorization Header sent: no Bearer token sent.
Se você usar a ferramenta de desenvolvimento de API para depurar a solicitação, deverá receber detalhes do erro, conforme mostrado na captura de tela a seguir.
Entre em contato conosco para obter ajuda
Se você tiver dúvidas ou precisar de ajuda, crie uma solicitação de suporte ou peça ajuda à comunidade de suporte do Azure. Você também pode enviar comentários sobre o produto para a comunidade de comentários do Azure.