Mohamad Mousheimish
Mohamad Mousheimish

Reputation: 1695

IsAuthenticated is always false in Custom Authorization Attribute (.NET Core 2.2 and JSON Web Token)

I'm trying to build my own custom authorization attribute using JSON Web Token JWT in .net core 2.2.

I'm calling the Authorized API using Postman and I'm facing two problems here:

  1. The Claims in the JWT sent are not being received
  2. IsAuthenticated property is always false in User.Identity.IsAuthenticated.

Please note that the part of JWT is working totally fine, a JWT is being created as I want with the correct Claims and I've checked it on https://jwt.io.

As for my Startup.cs I'm using app.UseAuthentication()

Here's how I'm adding the JWTAuthentication to services:

        services.AddAuthentication(x =>
        {
            x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(x=>
        {
            x.RequireHttpsMetadata = false;
            x.SaveToken = true;
            x.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = true,
                ValidateAudience = false
            };
        });
        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<AppIdentityDbContext>()
            .AddDefaultTokenProviders();

And here's a snippet of MyCustomAuthorizationAttribute.cs

    public string Permissions { get; set; } //Permission string to get from controller

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        //Validate if any permissions are passed when using attribute at controller or action level
        if (string.IsNullOrEmpty(Permissions))
        {
            //Validation cannot take place without any permissions so returning unauthorized
            context.Result = new UnauthorizedResult();
            return;
        }


        //The below line can be used if you are reading permissions from token
        var permissionsFromToken = context.HttpContext.User.Claims.Where(x => x.Type == "Permissions").Select(x => x.Value).ToList();

        var requiredPermissions = Permissions.Split(','); //Multiple permissiosn can be received from controller, delimiter "," is used to get individual values
        foreach (var x in requiredPermissions)
        {
            if (permissionsFromToken.Contains(x))
                return; //User Authorized. Wihtout setting any result value and just returning is sufficent for authorizing user
        }

        context.Result = new UnauthorizedResult();
        return;
    }

Note: I know that this question is asked a lot before, but I tried most of them and nothing worked for me.

Upvotes: 1

Views: 1295

Answers (1)

Mohamad Mousheimish
Mohamad Mousheimish

Reputation: 1695

I found out that the order of putting the middleware services in Startup.cs matters. As we can see in the code snippet above. I'm using AddIdentity() middleware after using AddAuthentication() and AddJwtBearer() which was somehow removing the JWT authentication provider.

The solution was simply to put AddIdentity() middleware with all of its sub-methods before AddAuthentication() and AddJWTBearer() middlware.

Upvotes: 3

Related Questions