azure-activedirectory-identitymodel-extensions-for-dotnet
azure-activedirectory-identitymodel-extensions-for-dotnet copied to clipboard
The "cty" header is always added breaking compatibility with certain services
Which version of Microsoft.IdentityModel are you using? 6.18
Where is the issue?
- [x] M.IM.JsonWebTokens
Is this a new or an existing app? The app is in production and I have upgraded to a new version of Microsoft.IdentityModel.
Expected behavior
The cty header addition for JsonWebTokenHandler.CreateToken is controlled by some flag.
Actual behavior
The cty header is added unconditionally.
Possible solution
Since #1588, there seems to be no way to control the addition of the cty header, and there are services (for example Apple ID token service) that require the produced token to contain only specified headers. The header set works just fine in the versions up to and including 6.17. After #1588 was completed, there appears to be no way to control the cty header presence.
https://www.rfc-editor.org/rfc/rfc7519#section-5.2
@onyxmaster as brockallen pointed out, in a JWE with an inner JWS, the cty is required. Are you seeing the cty in other than JWE's? Do you need a back-compat switch?
Thanks for answering.
I don't argue that the cty field is required by the spec. Unfortunately, the Apple ID secret token expectations are quite specific regarding the set of the expected fields (see Generate and Validate tokens -> Creating the Client Secret).
I don't think that Apple is going to change this to match the RFC, breaking all existing code. To generate this token we're using JsonWebTokenHandler.CreateToken, which, since 6.18 creates a JWS with the cty field unconditionally :(
The back-compat switch would be great, or we would be stuck on the 6.17 forever.
I have the same issue with Adobe API after upgrading to 6.18.0. When trying to exchange token (see Exchanging JWT to retrieve an access token) it fails because a new cty header is presented. It would be nice to have ability to control that header.
@onyxmaster @dmitry-kosar would on by default, with the ability to turn off with a switch in SecurityTokenDescriptor work for you?
Sorry about the hassle.
Yes, some kind of a flag to toggle the field addition would be great, regardless of its default value! I don’t think you should be sorry for anything, after all it’s some other service not following the spec.
The cty header parameter is added in some cases even when one is creating a JWS. Here is an example that reproduces this:
using System.IdentityModel.Tokens.Jwt;
using System.Security.Cryptography;
using Microsoft.IdentityModel.Tokens;
using var ecdsa = ECDsa.Create();
var key = new ECDsaSecurityKey(ecdsa);
var signingCredentials = new SigningCredentials(key, "ES256");
var header = new JwtHeader(signingCredentials);
var payload = new JwtPayload();
var token = new JwtSecurityToken(header, payload);
Console.WriteLine(new JwtSecurityTokenHandler().WriteToken(token));
Example output:
eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImN0eSI6IkpXVCJ9.e30.AcDSZ_pY6LJRXZWMGdNhWJY1d3uuyCzL97jYcHvflLwRLUGQOc63j1ltSi-IFE8pH5b7iVfT0_wq2YWvs1mwUEH_Acb1kHTcTRiDi_EOfNXP4kaaZjvYGSdPu5yFuO14tKSFULgchMNmJrfUZgQDx4eTLcsok7wCNv_V1FFwkUtwKu1m
Decoded:
{
"header": {
"alg": "ES256",
"typ": "JWT",
"cty": "JWT"
},
"payload": {},
"signature": "AF2C-PDYpLhqxuRHNULNs6aPrfTT2g_LVi9oofDI1-pBwkvlVrdS-9tnZB4JlFmbKR_9MUJByybK-Um1R43nNgdbAU0Qsv0xV2YQfXGJP84efocWBVA6JCpF_2Wde6WB719XSlakF-3GgI3trCmyOvm23w6WwbLW-Fzkcrt60LaOj7iy"
}
In this case, there is no nesting (the payload is not a JWT), so according to the RFC, adding a cty header parameter is not recommended.
If the cty header parameter is added to the header when the payload is not a nested JWT, some JWT validators seem to treat this as an invalid token; for example, we had trouble validating such tokens using jose4j on Java.
@RojaEnnam make sure to address ^^ @onyxmaster we should apologize, after all these years we know changing a wire format needs a back-compat switch.
We are hitting this as well with regular JWT's, some of our partners using Java cannot handle the new cty in the header and explode :)
I just added this comment pointing to the probable code causing this: https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/1295#issuecomment-1149932370
Released in 6.20.0.