Azure-activedirectory-identitymodel-extensions-for-dotnet: iat and exp are strings instead of numbers (System.IdentityModel.Tokens.Jwt/JwtRegisteredClaimNames.cs)

Created on 22 Nov 2017  Â·  7Comments  Â·  Source: AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet

Per RFC 7519 (https://tools.ietf.org/html/rfc7519#section-4), the iat and exp claims MUST be numbers. In System.IdentityModel.Tokens.Jwt/JwtRegisteredClaimNames.cs (https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/master/src/System.IdentityModel.Tokens.Jwt/JwtRegisteredClaimNames.cs) they are both of type string. This is a breaking error for code the follows the RFC spec, such as jsonwebtoken (https://github.com/auth0/node-jsonwebtoken). Specifically, jsonwebtoken considers every token issued with a string iat claim to be invalid. I did not have the chance to review if any other registered claims are of the wrong type, but the implentations should probably be reviewed against the spec.

Customer reported Investigate P2

Most helpful comment

@brentschmaltz @AndersAbel
However, the System.IdentityModel.Tokens.SecurityTokenHandler.WriteToken method creates the iat and exp claims as strings (with quotes) when I believe they should be NumericDates.
image
These being strings is breaking the jwt.verify function of jsonwebtokens.
https://www.npmjs.com/package/jsonwebtoken#token-expiration-exp-claim

Can this be corrected?

All 7 comments

That's just the constants for the names of the claims. And the names are of course strings. There's nothing in that file that concerns the format of the values.

OK, I referenced the wrong file. However, if you inspect the output of a JWT created using the reserved claims, the iat and exp are both strings. I will attach a code sample later.

Thanks,

Chris Kummer
Systems/Infrastructure Architect
Department of Technology

From: Anders Abel
Sent: Tuesday, November 21, 11:42 PM
Subject: Re: [AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet] iat and exp are strings instead of numbers (System.IdentityModel.Tokens.Jwt/JwtRegisteredClaimNames.cs) (#838)
To: AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet
Cc: Kummer, Chris@CIO, Author

That's just the constants for the names of the claims. And the names are of course strings. There's nothing in that file that concerns the format of the values.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHubhttps://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FAzureAD%2Fazure-activedirectory-identitymodel-extensions-for-dotnet%2Fissues%2F838%23issuecomment-346268276&data=02%7C01%7Cchris.kummer%40state.ca.gov%7Cd70e3ed42d794f939e4108d5317c9f30%7C52b26be47f5d4e1cbaed8cf75b7570d5%7C1%7C0%7C636469333679299561&sdata=uISCtidtEgQDDmvpaV1MmBO0Bp106QPd7xIq6tblGIw%3D&reserved=0, or mute the threadhttps://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAWD6xQqyRIB4oMiDxXky40U85ZBrlG0Vks5s49B0gaJpZM4Qmv0d&data=02%7C01%7Cchris.kummer%40state.ca.gov%7Cd70e3ed42d794f939e4108d5317c9f30%7C52b26be47f5d4e1cbaed8cf75b7570d5%7C1%7C0%7C636469333679299561&sdata=4OdhwVrpwZ5HJ9a4BkSKRdmAwM7kiVDBNn8sPzCIaTg%3D&reserved=0.

@cwkummer The 'Claims' returned have a string as the value, but JwtSecurityToken.Payload has the values as long.

@brentschmaltz @AndersAbel
However, the System.IdentityModel.Tokens.SecurityTokenHandler.WriteToken method creates the iat and exp claims as strings (with quotes) when I believe they should be NumericDates.
image
These being strings is breaking the jwt.verify function of jsonwebtokens.
https://www.npmjs.com/package/jsonwebtoken#token-expiration-exp-claim

Can this be corrected?

@cwkummer AH! this is worth revisiting.

@cwkummer I'm not able to reproduce this issue.
Actually _System.IdentityModel.Tokens.SecurityTokenHandler_ is an abstract class.

_System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler_ implements the _SecurityTokenHandler_ class and _WriteToken_ method returns a JWT in Compact Serialization Format.

See the example below:

        DateTime expires = new DateTime(2018, 8, 6, 13, 7, 24);
        var jwt = new JwtSecurityToken(expires: expires);
        var jwtHandler = new JwtSecurityTokenHandler();
        var compactSerializationFormat = jwtHandler.WriteToken(jwt);

compactSerializationFormat will be _eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJleHAiOjE1MzM1ODYwNDR9._
, which corresponds to:

{
"alg": "none",
"typ": "JWT"
}.{
"exp": 1533586044
}.[Signature]

Hi @mattiasback, this behavior is by design. You created a claim without specifying its value type.
String is used as a type when valueType is not specified (docs).

The iat claim will be created as long if you change your code to:
new Claim(JwtRegisteredClaimNames.Iat, unixSeconds.ToString(), ClaimValueTypes.Integer64)

Note: token.Payload.Iat always returns long.

Was this page helpful?
0 / 5 - 0 ratings