How do I log authorization attempts in .net core
Asked Answered
K

4

12

I'm trying to write to a log when I person tries to access a method under an Authorize Attribute. Basically, I want to log if a person uses an invalid token or an expired token. I'm using basic Authentication for JWT

services.AddAuthentication(o =>
{
    o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(cfg =>
    {
        cfg.RequireHttpsMetadata = false;
        cfg.SaveToken = true;

        cfg.TokenValidationParameters = new TokenValidationParameters()
        {
            ValidAudience = jwtAudience,
            ValidIssuer = jwtIssuer,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSecurityKey))
        };

    });

Is there a way I can add a piece of code to the authorization check that logs if a authorization attempt was valid and why it wasn't?

Kimmi answered 20/2, 2018 at 16:24 Comment(3)
Okay, I clarified the question. Thanks for the heads up.Kimmi
You can inherit AuthorizeAttribute, do your logging and call the base methodKettledrum
Which method do I call though. From what I can tell, the AuthorizeAttribute just has two constructors but no actual methods.Kimmi
T
23

You have access to the JwtBearerEvents object, which defines a number of events that are raised as the bearer token is processed.

OnAuthenticationFailed
Invoked if exceptions are thrown during request processing. The exceptions will be re-thrown after this event unless suppressed.

OnChallenge Invoked before a challenge is sent back to the caller.

OnMessageReceived
Invoked when a protocol message is first received.

OnTokenValidated
Invoked after the security token has passed validation and a ClaimsIdentity has been generated.

https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.authentication.jwtbearer.jwtbearerevents?view=aspnetcore-2.0

When initialising the configuration at AddJwtBearer, add the events you'd like to subscribe to,

.AddJwtBearer(o =>
{
    o.Events = new JwtBearerEvents()
    {
        OnAuthenticationFailed = c =>
        {
            // do some logging or whatever...
        }

    };
});

Have a look at the source to see when events might be raised,

https://github.com/aspnet/Security/blob/dev/src/Microsoft.AspNetCore.Authentication.JwtBearer/JwtBearerHandler.cs

Tycho answered 20/2, 2018 at 17:20 Comment(5)
I did see that. But is there a way I can see the reason the authentication failed? For example, was the token invalid, or did it expire?Kimmi
I think there might have been a mixup between authentication and authorization. JwtBearerEvents handles authentication, but the question was about authorization.Slosberg
They mentioned "Basically, I want to log if a person uses an invalid token or an expired token.", so that's at AuthN stage. According to the source, github.com/aspnet/Security/blob/…, an invalid token triggers the OnAuthenticationFailed handlerTycho
You need to return Task.CompletedTask; if you're not doing anything async github.com/aspnet/Security/issues/1680Exterminatory
@MichaelKargl Did you find out how to intercept the authorization request and log any errors?Eulau
V
16

Not sure if it's already implemented in earlier versions of .NET (Core) but i'm using .NET 6 and i'm able to activate the logging implemented in .NET 6 by setting the loglevel to Information for to the Microsoft.AspNetCore.Authentication category.

For example in your appsettings.json:

 "Logging": {
    "LogLevel": {
      // ...
      "Microsoft.AspNetCore.Authentication": "Information"
    }
  }

This gave me the the following log for an expired token (i'm using log4net with a template):

INFO [Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler] - MESSAGE: Failed to validate the token.
 Microsoft.IdentityModel.Tokens.SecurityTokenExpiredException: IDX10223: Lifetime validation failed. The token is expired. ValidTo: 'System.DateTime', Current time: 'System.DateTime'.
   at Microsoft.IdentityModel.Tokens.Validators.ValidateLifetime(Nullable`1 notBefore, Nullable`1 expires, SecurityToken securityToken, TokenValidationParameters validationParameters)
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateLifetime(Nullable`1 notBefore, Nullable`1 expires, JwtSecurityToken jwtToken, TokenValidationParameters validationParameters)
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateTokenPayload(JwtSecurityToken jwtToken, TokenValidationParameters validationParameters)
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
   at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()

Of course if you want to be more restrictive you could instead use the Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler category in your appsettings.json. It's just important to have the loglevel for this class set to Information since the generated .NET 6 logs have this loglevel.

Virgy answered 18/5, 2022 at 12:30 Comment(1)
This exactly what I need. I got the error details in the console log. Thanks @Robin WindeyRumen
S
3

In addition to Robin Windey comment I also recommend to use Authorization in appsettings.json:

"Microsoft.AspNetCore.Authentication": "Information",
"Microsoft.AspNetCore.Authorization": "Information",
Salta answered 2/10, 2023 at 8:19 Comment(1)
This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From ReviewPoised
S
0

I was trying to show my "Authorisation" header of the clients requests. It kept showing [redacted]. The appropriate keyword search led me to this article, so here is how it finally worked for me.

services.AddHttpLogging(o =>
{
    o.RequestHeaders.Add("Authorization");
});

ofc this is for testing only

Subdued answered 6/6 at 12:27 Comment(1)
This does not really answer the question. If you have a different question, you can ask it by clicking Ask Question. To get notified when this question gets new answers, you can follow this question. Once you have enough reputation, you can also add a bounty to draw more attention to this question. - From ReviewChristiansen

© 2022 - 2024 — McMap. All rights reserved.