I have an ASP.NET Core 2.1 Web Application project that uses JWT tokens for authenticating the Web API that's built-in to the project. It works fine when I run it locally on my machine, but when I deploy it to Azure (with identical environment and app-settings) it simply returns empty HTTP 401 responses to requests from my authenticated clients and I need to find out why so I can fix it.
I enabled logging of every detail in ASP.NET Core, however I never received any useful output.
First, I added Serilog.AspNetCore
and the Console sink to the project through NuGet, then configured logging at Verbose
level in Program.cs
:
public class Program
{
public static void Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose()
.MinimumLevel.Override("Microsoft", LogEventLevel.Verbose)
.MinimumLevel.Override("System", LogEventLevel.Verbose)
.MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Verbose)
.Enrich.FromLogContext()
.WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Literate)
.CreateLogger();
CreateWebHostBuilder( args ).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(String[] args)
{
return WebHost.CreateDefaultBuilder( args )
.ConfigureLogging( (ctx, cfg ) =>
{
cfg.ClearProviders();
} )
.UseStartup<Startup>()
.UseSerilog();
}
}
But when I run my web-application on Azure (with console stdout
logging to file) I got this output:
[04:13:10 Verbose] Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker
Authorization Filter: Before executing OnAuthorizationAsync on filter
Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter.
[04:13:10 Verbose]
IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler
HandleAuthenticateAsync called
[04:13:10 Debug]
IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler
AuthenticationScheme: Bearer was not authenticated.
[04:13:10 Information]
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService
Authorization failed.
[04:13:10 Verbose] Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker
Authorization Filter: After executing OnAuthorizationAsync on filter
Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter.
[04:13:10 Information]
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker
Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
[04:13:10 Verbose] Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker
Before executing action result Microsoft.AspNetCore.Mvc.ChallengeResult.
[04:13:10 Information] Microsoft.AspNetCore.Mvc.ChallengeResult
Executing ChallengeResult with authentication schemes (["Bearer"]).
[04:13:10 Verbose]
IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler
Forwarding challenge to scheme: BearerIdentityServerAuthenticationJwt
Note how despite verbose logging, the error messages (repeated below) don't give me any explanation:
AuthenticationScheme: Bearer was not authenticated.
Authorization failed.
I dug around the ASP.NET Core Security source-code to see that JwtBearerHandler.HandleAuthenticateAsync
doesn't do much logging of its own, but it does call into the not-open-sourced System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler
which does normally do a lot of logging, including detailed reasons (e.g. (with IDX10209
-type error codes in strings), but I don't know why it isn't outputting anything I can capture.
How do I log messages from JwtSecurityTokenHandler
?