Home > Mobile >  How to do some actions in .net core web api side when receives an invalid token (API is decorated wi
How to do some actions in .net core web api side when receives an invalid token (API is decorated wi

Time:07-20

builder.Services
    .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.Configuration = openIdConfig;
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            IssuerSigningKeyResolver = (string token, SecurityToken securityToken, string kid, TokenValidationParameters validationParameters) =>
            {
                // get JsonWebKeySet from issuer
                var json = new HttpClient().GetStringAsync(openIdConfig.JwksUri).Result;
                var jsonWebkeySet = JsonWebKeySet.Create(json);
                return jsonWebkeySet.GetSigningKeys();
            },
            ValidateIssuer = true,
            ValidIssuer = tokenIssuer,
            ValidateLifetime = true,
            ValidateAudience = false
        };
    });

Above is the code to configure jwtbearer In Asp.Net core web API application Controllers decorated with Authorize attribute to validate request along with token comes from the browser. Here when an invalid token received, 401 unauthorize returns without hitting inside the controller. I just wanted to log when receives invalid token in application side
So please suggest how to do this when receives invalid token in web API ?

CodePudding user response:

You can create an error handler middleware to catch the 401 error, Then log the error in this middleware, Refer to this simple demo.

public class ErrorHandlingMiddleware
{
    private readonly RequestDelegate next;

    private readonly ILogger<ErrorHandlingMiddleware> _logger;

    public ErrorHandlingMiddleware(RequestDelegate next, ILogger<ErrorHandlingMiddleware> logger)
    {
        this.next = next;
        _logger = logger;
    }

    public async Task Invoke(HttpContext context)
    {
        try
        {
            await next(context);
        }
        catch (Exception ex)
        {
            //.......
            _logger.LogError(ex.Message);
        }
        finally
        {
            var statusCode = context.Response.StatusCode;

            if (statusCode == 401)
            {
                _logger.LogError("JWT Token error!!!!!!!");
            }

            //catch another error
        }
    }
}

public static class ErrorHandlingExtensions
{
    public static IApplicationBuilder UseErrorHandling(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<ErrorHandlingMiddleware>();
    }
}

Then add this middleware.

app.UseErrorHandling();

Demo

When receiving the invalid token, the application will log

enter image description here

CodePudding user response:

you can achieve it by specifying the EventType in the JWT auth configuration (I think it is the cleanest solution). You have to create a class that inherits from JwtBearerEvents like this:

public sealed class MyJwtBearerEvents : JwtBearerEvents
{
    private readonly ILogger<MyJwtBearerEvents> _logger;

    public MyJwtBearerEvents(ILogger<MyJwtBearerEvents> logger,)
    {
        _logger = logger;
    }

    public override async Task TokenValidated(TokenValidatedContext context)
    {
        //TODO: Once token is validated (no 401)

        await base.TokenValidated(context);
    }

    public override async Task Challenge(JwtBearerChallengeContext context)
    {
        //TODO: Once token in not valid (401)
        _logger.Log(LogLevel.Error, "Token is not valid...");

        await base.Challenge(context);
    }

    public override async Task AuthenticationFailed(AuthenticationFailedContext context)
    {
        //TODO: Once authentication failed with exception

        await base.AuthenticationFailed(context);
    }

    public override async Task Forbidden(ForbiddenContext context)
    {
        //TODO: Once authentication failed with forbidden result (403)
        
        await base.Forbidden(context);
    }
}

and override the methods that interest you, in your case you can override only the Challenge method that is invoked when authentication fail with 401.

To specify usage of your custom events you have to register your class as "Scoped" and add the EventsType option during JWT configuration:

builder.Services.AddScoped<MyJwtBearerEvents>();

builder.Services
    .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.Configuration = openIdConfig;
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            IssuerSigningKeyResolver = (string token, SecurityToken securityToken, string kid, TokenValidationParameters validationParameters) =>
            {
                // get JsonWebKeySet from issuer
                var json = new HttpClient().GetStringAsync(openIdConfig.JwksUri).Result;
                var jsonWebkeySet = JsonWebKeySet.Create(json);
                return jsonWebkeySet.GetSigningKeys();
            },
            ValidateIssuer = true,
            ValidIssuer = tokenIssuer,
            ValidateLifetime = true,
            ValidateAudience = false
        };
        options.EventsType = typeof(MyJwtBearerEvents); //<==
    });
  • Related