Search code examples
c#authenticationjwtasp.net-core-2.2.net-core-2.2

Authentication based on JWT token bearer fails under .NET Core 2.2 after move from 3.0


I took a solution with a working authentication and downgraded it from Core 3.0 to Core 2.2. After that, the setup stopped working. Apparently, there's some minor difference in how it's organized that I'm missing. Comparing to the blogs and walk-throughs, I fail to see it.

The authentication is configured like this. Very simple, checking only the time stamp at the moment.

TokenValidationParameters parameters = new TokenValidationParameters
{
  ValidateLifetime = true,
  ValidateAudience = false,
  ValidateIssuer = false,
  ValidIssuer = "https://localhost:44385",
  ValidAudience = "https://localhost:44385"
};
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  .AddJwtBearer(config => config.TokenValidationParameters = parameters);

The token is issued using the following code.

TokenValidationParameters parameters = ...
byte[] secret = Encoding.UTF8.GetBytes("my_top_secret");
SecurityKey key = new SymmetricSecurityKey(secret);
SigningCredentials credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

JwtSecurityToken jwt = new JwtSecurityToken(
  "https://localhost:44385",
  "https://localhost:44385",
  { new Claim("a", "b") },
  DateTime.Now,
  DateTime.Now.AddSeconds(3600),
  credentials
);

string token = new JwtSecurityTokenHandler().WriteToken(jwt);
return Ok(new { token });

The returned value seems correct and I had it verified on JWT.IO so I don't suspect that to be the issue. However, when I paste that value into Postman (just like I did previously when everything worked), it gives me 401.

I don't know for sure what the problem is but I sense it has to do with the way I configured the authentication in the Startup class. My references I'm using for how it's supposed to look are here and here.

What am I missing? Alternatively, how else could I troubleshoot it?


Solution

  • Thanks to the comment by @LGSon, I realized where the issue resided. For some weird and inexplicable reason, one has to specify IssuerSigningKey in the parameters. It makes sense if the value of ValidateIssuerSigningKey is set to true but in my case, I went by default, which is false.

    TokenValidationParameters parameters = ...;
    parameters.IssuerSigningKey = Configuration.GetSecurityKey();
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
      .AddJwtBearer(config => config.TokenValidationParameters = parameters);
    

    In Core 2.2 it's required to specify it regardless whether it's being used or not. In Core 3.0 (at least in the latest preview) it's not! This is a sneaky gotcha, in my opinion (borderline bug that's been corrected).