'Validate an externally created JWT with no key Id using System.IdentityModel.Tokens.Jwt

Given that there is no way to influence the JWT as it is created externally, how can I verify the signature of the token when it does not contain a kid.

This is the relevant code:

private bool ValidateToken(string authToken)
{
    var tokenHandler = new JwtSecurityTokenHandler();
    var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(_secretKey));
    var validationParameters = new TokenValidationParameters()
    {
        ValidAudience = "clientid",
        ValidIssuer = _issuer,
        ValidateAudience = false,
        ValidateIssuer = false,
        IssuerSigningKey = new SymmetricSecurityKey(hmac.Key),
    };

    try
    {
        tokenHandler.ValidateToken(authToken, validationParameters, out SecurityToken validatedToken);
    }
    catch (Exception ex)
    {
        //handle exception
    }
    return true;
}

However this throws an exception:

{
"IDX10503: Signature validation failed. 
    Token does not have a kid. 
    Keys tried: '[PII of type 'System.Text.StringBuilder' is hidden. 
        For more details, see https://aka.ms/IdentityModel/PII.]'.
    Number of keys in TokenValidationParameters: '1'. 
    Number of keys in Configuration: '0'. 
    Exceptions caught:
        '[PII of type 'System.Text.StringBuilder' is hidden. 
            For more details, see https://aka.ms/IdentityModel/PII.]'.
        token: '[PII of type 'System.IdentityModel.Tokens.Jwt.JwtSecurityToken' is hidden. 
            For more details, see https://aka.ms/IdentityModel/PII.]'."
}

Why does Microsoft insist on there being a key id in the token? Is there a way to ignore the missing kid?

Example token (edited to remove data):

header:

{
  "alg": "HS256",
  "typ": "JWT",
  "ver": 1,
  "typ_2": "ref"
}

payload:

{
  "jti": "<token_id>",
  "client_id": "<client_id>",
  "client_name": "<client>",
  "ref_token": "<ref_token>",
  "ref_token_type": "Full",
  "zone": "<zone>",
  "endusertype": "system",
  "nbf": 1643639617,
  "exp": 1643643217,
  "iat": 1643639617,
  "iss": "<issuer>"
}

Edit: removed IssuerSigningKeys to avoid confusion.



Solution 1:[1]

After validating the encoding and scratching my head for quite some time I managed to get a hold of the external party and they confirmed that the key was indeed wrong - the "key" was only intended to be used in the api-call in which the consumer asks for a token, to "authenticate" the consumer. They did not include a kid in the jwt as they did not intend for consumers to validate the token.

This does however not answer the question.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Haukland