1

My colleague produced a token using the code below.

byte[] secret = Encoding.UTF8.GetBytes("hakunana_matata_kurva_garbata");
SecurityKey key = new SymmetricSecurityKey(secret);
SigningCredentials credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
JwtSecurityToken jwt = new JwtSecurityToken(
  "https://localhost:44385",
  "https://localhost:44385",
  new Claim[] { },
  DateTime.Now,
  DateTime.Now.AddMinutes(1),
  credentials);
string token = new JwtSecurityTokenHandler().WriteToken(jwt);

The way I expected it to perform was to be allow access for 6o seconds and then stop working. This doesn't seem to happen and the secured method keeps getting invoked regardless (it doesn't for wrong tokens and for requests without a token). After a while (not sure how long) the token stops working (and I guess it's expired then).

I also checked the token in the JWT page. What stroke me as odd was the two lines for not before and expiry. It seems that the difference between them is 60 seconds, as expected.

{
  "nbf": 1563895482,
  "exp": 1563895542,
  "iss": "https://localhost:44385",
  "aud": "https://localhost:44385"
}

I made sure that the configuration for the security demands validation of expiry date.

TokenValidationParameters parameters = new TokenValidationParameters
{
  ValidateIssuerSigningKey = true,
  ValidateLifetime = true,
  ValidateAudience = false,
  ValidateIssuer = false,
  IssuerSigningKey = new SymmetricSecurityKey(hakuna_whatever)
};

What am I missing here?

Konrad Viltersten
  • 36,151
  • 76
  • 250
  • 438
  • 1
    What is the "secured" method? I think we might need to see more of your JWT workflow to attempt an answer here. Note that JWT are, ideally, intended to be a completely _stateless_ way of maintaining session state. That is, in some cases, your .NET application would only need to check the claims of the incoming JWT to decide how to handle that request. – Tim Biegeleisen Jul 23 '19 at 15:47
  • @TimBiegeleisen Are you implying that checking for expiration and no-before aren't of relevance for the security and that I should focus on claims only? – Konrad Viltersten Jul 23 '19 at 19:42
  • Not sure what you mean, but `exp` (expiry) _is_ a claim. – Tim Biegeleisen Jul 24 '19 at 00:20
  • @TimBiegeleisen Aha, it's me being ignorant of the definition of claim. I thought that a claim is one of those things that are explicitly passed as members of the list of type *Claim[]*. Now that I think of it, it makes perfect sense that *exp*, *nbf* etc. are claims as well but being so fundamental, those are passed by dedicated variables instead of a general list. Luckily, someone took a guess and hit it spot on - it was the timely skewness. – Konrad Viltersten Jul 24 '19 at 09:40

1 Answers1

3

The problem is ClockSkew which default to 5 minutes (see for instance this post). Set it to TimeSpan.Zero when specifying the TokenValidationParameters

TokenValidationParameters parameters = new TokenValidationParameters
{
    // [...]
    ClockSkew = TimeSpan.Zero
};
i regular
  • 584
  • 6
  • 16