How to verify JWT provided by KeyCloak using .Net Core?

Viewed 3056

I have an ASP.Net Core 5 Resource Server and I want to verify my access tokens but not succeeded yet.

I wrote a middleware for better error handling:

var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_configuration["Jwt:Kid"]); // Kid is copied from 'openid-connect/certs'

tokenHandler.ValidateToken(token, new TokenValidationParameters
{
    ValidIssuer = _configuration["Jwt:Issuer"],
    IssuerSigningKey = new SymmetricSecurityKey(key),
    ValidateAudience = false,
    ValidateIssuer = true,
    ValidateIssuerSigningKey = true,
    ValidateLifetime = false
}, out SecurityToken validatedToken);

And my KeyCloak's keys are on */auth/realms/test/protocol/openid-connect/certs:

{
  "keys": [
    {
      "kid": "O9cbi7dzidpxZGLV2eXlTvIECoKDB_YbUN2m73rp8",
      "kty": "RSA",
      "alg": "RS256",
      "use": "sig",
      "n": "qMaFN3tmQ0TaGWaWcanebanGDgh_bz7RzlTbbkiGtY707x...hF40ofv1Fxoy7hBUEKARUqCgjltj5_0TtWn850Eqak41lpa-P_PNsGdwBf18mqBCT8pFbzs8DeRZaD1Q",
      "e": "AQAB",
      "x5c": [
        "MIIClzCCAX8CBgF3jSSr9TANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDAR0ZXN0MB4XDTIxMDIxMDE4MTAyNloXDTMxMDIxMDE4MTIwNlowDzENMAsGA1UEAwwEdGVzdDCCASIwDQYJKoZI...8tUe5h/7rg1+bHAGVbWg=="
      ],
      "x5t": "G5NYmhm8yEwqHtyLwygxGw89A",
      "x5t#S256": "nEnZWkJQyCG4czEJx04Nyszyzc3l8bsxZ3es2wDTw"
    }
  ]
}

When making a request I always get the following exception.

{"IDX10501: Signature validation failed. Unable to match key: \nkid: 'System.String'.\nExceptions caught:\n 'System.Text.StringBuilder'. \ntoken: 'System.IdentityModel.Tokens.Jwt.JwtSecurityToken'."}

Any idea what am I doing wrong?

1 Answers

RSA is not a symmetric algo. So do not use SymmetricSecurityKey as a signing key use JsonWebKey instead to automatically generate correct key for you:

tokenHandler.ValidateToken(token, new TokenValidationParameters
{
    ValidIssuer = _configuration["Jwt:Issuer"],
    IssuerSigningKey = new JsonWebKey(jsonKeyString),
    ValidateAudience = false,
    ValidateIssuer = true,
    ValidateIssuerSigningKey = true,
    ValidateLifetime = false
}, out SecurityToken validatedToken);

Where jsonKeySting is a string variable which is holding your key segment in the mentioned json

{
  "kid": "O9cbi7dzidpxZGLV2eXlTvIECoKDB_YbUN2m73rp8",
  "kty": "RSA",
  "alg": "RS256",
  "use": "sig",
  "n": "qMaFN3tmQ0TaGWaWcanebanGDgh_bz7RzlTbbkiGtY707x...hF40ofv1Fxoy7hBUEKARUqCgjltj5_0TtWn850Eqak41lpa-P_PNsGdwBf18mqBCT8pFbzs8DeRZaD1Q",
  "e": "AQAB",
  "x5c": [
    "MIIClzCCAX8CBgF3jSSr9TANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDAR0ZXN0MB4XDTIxMDIxMDE4MTAyNloXDTMxMDIxMDE4MTIwNlowDzENMAsGA1UEAwwEdGVzdDCCASIwDQYJKoZI...8tUe5h/7rg1+bHAGVbWg=="
  ],
  "x5t": "G5NYmhm8yEwqHtyLwygxGw89A",
  "x5t#S256": "nEnZWkJQyCG4czEJx04Nyszyzc3l8bsxZ3es2wDTw"
}
Related