Custom Authorization Attribute Fails To Work When Entered JWT Token in Request Header

[a simple Web API in ASP.NET]

The code gives 401 Unauthorized response when I send a request without JWT token. everything looks good up to this point.

When I enter the JWT token which is generated by the generateJWT() method in my code to authenticate a user the request ends without reaching the custom authorization attribute and the controller.

this is the custom authorization attribute:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AuthorizeAttribute : Attribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationFilterContext context)
    {
        var user = (User)context.HttpContext.Items["User"];

        if (user == null)
        {
            context.Result = new JsonResult(new { message = "unauthorized" }) { StatusCode = StatusCodes.Status401Unauthorized };
        }
    }
}

when I don’t add a jwt token into the request header, the request reaches here and gives the 401 response.

With jwt token, the request does not reach here. It ends in the custom JwtMiddleware although it works perfectly as far as I obsevered, validates the token and finds the user:

public class JwtMiddleware
{
    private readonly RequestDelegate _next;
    private readonly AppSettings _appSettings;

    public JwtMiddleware(RequestDelegate next, IOptions<AppSettings> appSettings)
    {
        _next = next;
        _appSettings = appSettings.Value;
    }

    public async Task Invoke(HttpContext context, IUserService userService)
    {
        var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();

        if (token == null) await _next(context);

        attachUserToContext(context, userService, token);
    }

    private void attachUserToContext(HttpContext context, IUserService userService, string token)
    {
        try
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.ASCII.GetBytes(_appSettings.Secret);

            tokenHandler.ValidateToken(token, new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = false,
                ValidateAudience = false,
                ClockSkew = TimeSpan.Zero
            }, out SecurityToken validatedToken);

            var jwtToken = (JwtSecurityToken)validatedToken;
            var userId = int.Parse(jwtToken.Claims.First(x => x.Type == "id").Value);

            context.Items["User"] = userService.GetById(userId);
        }

        catch
        {
            // do nothing
        }


    }
}

Can you spot what’s going on here?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

In the middleware, looks like the RequestDelegate is invoked only if there’s no token provided:
if (token == null) await _next(context);

And if there’s a token, attachUserToContext method is run but _next(context) is not invoked, thus the rest of the pipeline is not being executed (this is where mvc pipeline is along with the custom attribute).

From the docs: Each middleware component in the request pipeline is responsible for invoking the next component in the pipeline or short-circuiting the pipeline.

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-3.1

So, we should change the logic to always invoke _next:

var token = ...

if (token != null)
    attachUserToContext(context, userService, token);

await _next(context);

Another possible option is to short-circuit the pipeline if no token provided by writing 401 status code to context.Response and not invoking _next.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x