After updating all NuGet packages (to ServiceStack 6.11, System.IdentityModel.Tokens.Jwt 7.3.1, Microsoft.IdentityModel.JsonWebTokens 7.3.1, and more) I get the following error message on the client:

IDX12723: Unable to decode the payload '[PII of type 'System.String' is hidden. For more details, see https://aka.ms/IdentityModel/PII.]' as Base64Url encoded string.

In the debugger I found this message:

IDX11020: The JSON value of type: 'Number', could not be converted to 'JsonTokenType.String'. Reading: 'System.IdentityModel.Tokens.Jwt.JwtPayload.jti', Position: '144', CurrentDepth: '1', BytesConsumed: '145'.'

The payload which is trying to be parsed is (I've masked name and preferred_username).

{ 
  "iss": "ssjwt", 
  "sub": null, 
  "iat": 1707237670, 
  "exp": 1707241270, 
  "name": "xxxxxx@xxxxxxxx", 
  "preferred_username": "xxxxxxxx@xxxxxxxxxxx", 
  "jti": 4, 
  "OriginalProvider": "msalauth" 
}

I think the issue is the "jti" claim which is returned as a number instead of a string by the ServiceStack service. I've checked with older versions of the ServiceStack service, and it has always been a number.

In System.IdentityModel.Tokens.Jwt.JwtPayload.cs the following code snippet is reading the value as a string instead of a number:

else if (reader.ValueTextEquals(JwtPayloadUtf8Bytes.Jti)) { 
  payload._jti = JsonSerializerPrimitives.ReadString(ref reader, JwtRegisteredClaimNames.Jti, ClassName, true);
  payload[JwtRegisteredClaimNames.Jti] = payload._jti; 
}

I've posted this issue here: https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/2401, but they replied that the "jti" JWT ID should be a string as specified here: https://www.rfc-editor.org/rfc/rfc7519.html#section-4.1.7

Where is the JWT ID added in the claims by ServiceStack and can I change the datatype? Or should the datatype be changed in the ServiceStack package?

1

There are 1 best solutions below

1
mythz On

You can change it to use a string for jti by overriding ResolveJwtId and ResolveRefreshJwtId when registering the JWT Auth Provider:

Plugins.Add(new AuthFeature(() => new CustomUserSession(), 
[
    new JwtAuthProvider(appSettings) {
        ResolveJwtId = _ => Guid.NewGuid().ToString(),
        ResolveRefreshJwtId = _ => Guid.NewGuid().ToString(),
    }, 
]));

Although it's not recommended to read ServiceStack JWT Tokens with external libraries. Instead if you need compatibility we recommend using ServiceStack JWT Identity Auth from ServiceStack v8.1+ which uses ASP.NET Core's JWT Configuration and implementation to implement its JWT support.