0

I'm trying to create a JWT token by signing it with a private key stored in an Azure key vault. The code I have works fine and it generates the token, but the token just wasn't working with the API I'm trying to log into. Generating the token via Python worked fine. I used jwt.io to decode the payload data and compared the tokens generated via C# and Python. I noticed that that the Issued At claim ("iat") is not surrounded by double-quotes in the Python generated token, but it had the quotes in the other one.

Is there a way to create a System.Security.Claim with an integer as the claim value? I tried including "Integer64" as the ValueType parameter, but it didn't work. In the code below I'm simply removing the quotes around the "iat" claim value and it works. Is this what I'm supposed to do?

var claims = new[]
{
    new Claim(JwtRegisteredClaimNames.Iat, DateTimeOffset.Now.ToUnixTimeSeconds().ToString(), "Integer64")
};

var payload = JsonSerializer.Serialize(new JwtPayload(claims));
payload = payload.Replace("iat\":\"", "iat\":").Replace("\"}", "}");
var headerAndPayload = $"{Base64UrlEncoder.Encode(header)}.{Base64UrlEncoder.Encode(payload)}";

Here is what the API expects (no double-quotes):

jwt.io decoded payload

jwt.io decoded payload

In C# I tried removing the double-quotes around the "iat" claim value and it worked. This wasn't necessary when using jwt.encode in Python.

burnsi
  • 6,194
  • 13
  • 17
  • 27
Dorian-B
  • 11
  • 3

1 Answers1

0

A better approach is to use the build in .NET Libraries to generate your JWT tokens, just to make sure you get everything right.

There are two different libraries in .NET for generating tokens and you can read about this here: Why we have two classes for JWT tokens JwtSecurityTokenHandler vs JsonWebTokenHandler?

Here's a resource to explore for manually creating a token: https://www.c-sharpcorner.com/article/jwt-validation-and-authorization-in-net-5-0/

Tore Nestenius
  • 16,431
  • 5
  • 30
  • 40
  • What you suggest still uses System.Security.Claims where the value of the claim must be a string. How would this solve the problem above? – Dorian-B Feb 02 '23 at 13:54
  • As claims are always strings, I suggest you use a string to represent IAT instead of an integer value. Also, if you use the libraries, they might handle serialization more correctly, than doing it yourself using JsonSerializer.Serialize(). – Tore Nestenius Feb 02 '23 at 14:11
  • Funny/scary as hell, but I asked ChatGPT this question and it suggested that I use ClaimValueType.Integer64 instead of "Integer64" and it worked. I still want to try using the newer library though, which was your suggestion. new Claim(JwtRegisteredClaimNames.Iat, DateTimeOffset.Now.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64) – Dorian-B Feb 02 '23 at 23:10
  • Usually, if you use the libraries, then the internal claims like iat, exp.. are handled for you. – Tore Nestenius Feb 03 '23 at 11:06