0

I am trying to validate a JWT token being passed onto a C# application. I confirmed that the token is being sent with every request. If I decode it manually everything works fine (I see the claims). However when I enable Authorization I get a 404 from the (Angular) client when I try to access the page. My theory is that Angular is sending an OPTIONS request that is failing because it cant Auth with the token properly. Any advice on how to confirm this is the issue, and troubleshoot it?

Auth via claim in token

[Authorize(Policy = "IsEmployee")]
[HttpGet("TestTokenAccess")]
public JsonResult TestTokenAccess()
{
    return Json("token decoded. you have claim IsEmployee=yes");
}

Manual token decode

[HttpGet("TestDecodeToken")]
public JsonResult TestDecodeToken()
{
    //https://shellmonger.com/2015/07/18/decoding-an-auth0-json-web-token-with-c/
    if (this.HttpContext.Request.Headers.ContainsKey("Authorization"))
    {
        var authHeader = this.HttpContext.Request.Headers["Authorization"];
        var authBits = authHeader.ToString().Split(' ');
        if (authBits.Length != 2)
        {
            return Json("{error:\"auth bits needs to be length 2\"}");
        }
        if (!authBits[0].ToLowerInvariant().Equals("bearer"))
        {
            return Json("{error:\"authBits[0] must be bearer\"}");
        }

        var secret = "xxxxx";

        //Install-Package JWT -Version 4.0.0
        try
        {
            var json = new JwtBuilder()
                .WithSecret(secret)
                //.MustVerifySignature()
                .Decode(authBits[1]);
            return Json(json);
        }
        catch (TokenExpiredException)
        {
            return Json("Token has expired");
        }
        catch (SignatureVerificationException)
        {
            return Json("Token has invalid signature");
        }
        catch (Exception e)
        {
            return Json($"other token err: {e.Message}");
        }

    }
    return Json("no token");
}

Startup.cs inside of ConfigureServices, but above the AddMVC() call

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.Authority = Configuration["JwtIssuer"];
        options.Audience = Configuration["JwtIssuer"];

        options.RequireHttpsMetadata = true;
        options.SaveToken = true;
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = Configuration["JwtIssuer"],
            ValidAudience = Configuration["JwtIssuer"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtKey"]))
        };
    }
);

services.AddAuthorization(options =>
{
    options.AddPolicy("IsEmployee", policy => policy.Requirements.Add(new IsEmployeeRequirement("yes")));

});

services.AddSingleton<IAuthorizationHandler, IsEmployeeAuthorizationHandler>();

appsettings.json

  "JwtKey": "xxx",
  "JwtIssuer": "http://localhost:44362/",
  "JwtExpireDays": 30

snippet from web.config enable CORS

<!--added to enable CORS for Angular-->

<httpProtocol>

  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="https://localhost:44362/" />

    <add name="Access-Control-Allow-Headers" value="Content-Type" />

    <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
  </customHeaders>

</httpProtocol>
Rilcon42
  • 9,584
  • 18
  • 83
  • 167

1 Answers1

0

Turned out my issue was an incorrectly specified claim in Startup.ConfigureServices() I needed to have:

services.AddAuthorization(options =>
{
    options.AddPolicy("IsEmployee", policy =>policy.RequireClaim("IsEmployee", "Yes", "yes"));          
});

rather than the policy specific way Microsoft used in their example here. I also removed the AddSingleton() line because it is not necessary

Rilcon42
  • 9,584
  • 18
  • 83
  • 167