Title
JWK validation fails with "X5T in marshal does not match X5T in marshalled" when fetching Auth0's JWKS endpoint
Environment
github.com/MicahParks/keyfunc/v3 (latest)
github.com/golang-jwt/jwt/v5
- JWKS source: Auth0 (
https://<tenant>.auth0.com/.well-known/jwks.json)
- Go version: 1.26.4
Description
When using keyfunc.NewDefaultCtx to build a Keyfunc from an Auth0 JWKS endpoint, every background refresh fails validation with the following error, and no keys are ever loaded:
ERROR Failed to refresh HTTP JWK Set from remote HTTP resource. error="failed to create JWK from JWK Marshal: failed to validate JSON Web Key: failed to validate JWK: X5T in marshal does not match X5T in marshalled" url=https://<tenant>.auth0.com/.well-known/jwks.json
Because the JWK Set never loads successfully, every subsequent jwt.Parse call using k.Keyfunc fails, resulting in 401s for all incoming requests.
Steps to Reproduce
const serverURL = "https://redacted.auth0.com/.well-known/jwks.json"
k, err := keyfunc.NewDefaultCtx(ctx, []string{serverURL})
if err != nil {
log.Fatalf("Failed to create a keyfunc.Keyfunc from the server's URL.\nError: %s", err)
}
parsedToken, err := jwt.Parse(
token,
k.Keyfunc,
jwt.WithValidMethods([]string{jwt.SigningMethodRS256.Alg()}),
jwt.WithAudience(validationAudience),
jwt.WithIssuer(validationIssuer),
)
JWKS Payload
{
"keys": [
{
"kty": "RSA",
"use": "sig",
"n": "4mKUhg1ZOo0mriez3LWBGoXvp8eXs_cCy4nXYyD0duKl_i-eDPzzWZ0nqrfzPLnnQS13XdJ8RyET0NXSyUaxGSVBbQvbHFc9ocq59jTmuHC-xQlnWsXVEwBacMLRIu8m3sfZoiJcqpvctLZtygCP5nATe7mPSPYAFQx_UK5Hkr5mJP7dIObQLFLLvq7mbTgzjfPdOiH2P-1SnCatJ2fpMQe0qdktEI8WekHI3vRTPerVr8h5JEps5QKpvppK3jcj1_Ezg1Kt_AfsWSTrVgUQzG5VvEnAFHYvs_cfZ74gq_p9yyxi-nvfuzvVI8ZqCetqekqncOXKLMn61NqfY3T2Hw",
"e": "AQAB",
"kid": "QzczNUNGNzFEMzQ0REU0M0MxNEY0N0M5M0FGRDVERjkyQzRBM0UzMg",
"x5t": "QzczNUNGNzFEMzQ0REU0M0MxNEY0N0M5M0FGRDVERjkyQzRBM0UzMg",
"x5c": [
"MIIDBzCCAe+gAwIBAgIJOo90qX3gnxJBMA0GCSqGSIb3DQEBCwUAMCExHzAdBgNVBAMTFmRldi1xb3A5czlvci5hdXRoMC5jb20wHhcNMTkwNzAzMjA0MDQ3WhcNMzMwMzExMjA0MDQ3WjAhMR8wHQYDVQQDExZkZXYtcW9wOXM5b3IuYXV0aDAuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4mKUhg1ZOo0mriez3LWBGoXvp8eXs/cCy4nXYyD0duKl/i+eDPzzWZ0nqrfzPLnnQS13XdJ8RyET0NXSyUaxGSVBbQvbHFc9ocq59jTmuHC+xQlnWsXVEwBacMLRIu8m3sfZoiJcqpvctLZtygCP5nATe7mPSPYAFQx/UK5Hkr5mJP7dIObQLFLLvq7mbTgzjfPdOiH2P+1SnCatJ2fpMQe0qdktEI8WekHI3vRTPerVr8h5JEps5QKpvppK3jcj1/Ezg1Kt/AfsWSTrVgUQzG5VvEnAFHYvs/cfZ74gq/p9yyxi+nvfuzvVI8ZqCetqekqncOXKLMn61NqfY3T2HwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRM0XxeTlV//5G7eN+A3wQqzTEVPDAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZIhvcNAQELBQADggEBAMtjDuuv4K22q2drPKZ0PD73cuYHbO1D7hmv1Kn7cpuiu18r4k5hevkvM7LBfda2uN++lbWfEc5PZ420qR3dZO5Fpoxrcgm2F7Tv3eOjmCWibrPsc2+hyk/VxK+9zFktzNosRC/Yza6diXn5Uk4+e3TRbfUs1PZl9ShzM3mCktSYd0+dxbHpkU2JtKPaDDqAmQOBGapKpt2NnXgGwMeV2SiMmF6hidVeWHxSy0UpicNRg2qPmqzoemVNhyqNc/N6xwI3SjGsAQhL8j1VBupmnYksp9/dHz/LZEKNU+p724he44PF7Irxa4FjHaQazzZP8CWmuewNzRjQwV5n5JLMPPQ="
],
"alg": "RS256"
},
{
"kty": "RSA",
"use": "sig",
"n": "na98UqN9aFk6XVccGUF2e9_W0Q8c4N_ajip-hEk9h25ayvLzfMTEdVPuJ-7QIfG2Jh9mptaMzyEjq4W0Y7EwZz7EjZk2146OKkBvYL0mnkEBBBdjZZEChY2dvfUJJJDW3sT7gVRND6yKlKow7M1-cvRQ16-FkZ2AzR3K3rHXD76CSGAc8Qifl0TV212oW0hrCNGN-X8rZiYr7HkaLOWyT3s2KGvXAEbGyptmI2DEYZDhu5Cig10hZwPzPAgfQlJoaa2Ern2C2WYej62iUJ5q9c9Vor2xnp6MJmuXvY4DiUq05E_FE3BoUgetX1nBzM4BH-dxHRAxcWPU7HH-mjT7fQ",
"e": "AQAB",
"kid": "WHajrvRI1wuPgQ6JJlUF4",
"x5t": "fXcPhcssdr97QaMpQg3tPR8Kq20",
"x5c": [
"MIIDBzCCAe+gAwIBAgIJOPRF+Zz8yRR3MA0GCSqGSIb3DQEBCwUAMCExHzAdBgNVBAMTFmRldi1xb3A5czlvci5hdXRoMC5jb20wHhcNMjAwMzEzMDM1NjE3WhcNMzMxMTIwMDM1NjE3WjAhMR8wHQYDVQQDExZkZXYtcW9wOXM5b3IuYXV0aDAuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAna98UqN9aFk6XVccGUF2e9/W0Q8c4N/ajip+hEk9h25ayvLzfMTEdVPuJ+7QIfG2Jh9mptaMzyEjq4W0Y7EwZz7EjZk2146OKkBvYL0mnkEBBBdjZZEChY2dvfUJJJDW3sT7gVRND6yKlKow7M1+cvRQ16+FkZ2AzR3K3rHXD76CSGAc8Qifl0TV212oW0hrCNGN+X8rZiYr7HkaLOWyT3s2KGvXAEbGyptmI2DEYZDhu5Cig10hZwPzPAgfQlJoaa2Ern2C2WYej62iUJ5q9c9Vor2xnp6MJmuXvY4DiUq05E/FE3BoUgetX1nBzM4BH+dxHRAxcWPU7HH+mjT7fQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSRECOJRsBmoj4XqH9sYYSFMSP/HDAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZIhvcNAQELBQADggEBAECjmGA3+0UXbQrU+hjK9+fdpY3CXBU68r1Tavl545IOP1xH5nJyaDVTRB5sxUomoCDUJNIyYMbBR8syxH1dc/pw2FSWr3fOk3p7CfCgsqPTs8wCel7s+RrvvGoj3mkS1PXkDPnXmFm8+nhTX9NidraYuXyYbJ5sjxsLzoSVZzvDtDCV9obiLbSYBPIvI5bGcItJzrVygLa9ElYbzpNwHY+SmOE9VDIYMJ25VpWmyLiCqo3GHaO4wxLs7Dmz4Ff/MxTIM1GwzRB7a7Xdf4TfWGgfj597Pdmw1ITIDOY6JddDd7iOzB4tZR706V8l7KiVhvrqW3wcq0ikiPtJupfnvPU="
],
"alg": "RS256"
}
]
}
- Point
keyfunc.NewDefaultCtx at any Auth0 tenant's .well-known/jwks.json.
- Any call to
k.Keyfunc / jwt.Parse fails to validate tokens because no keys were ever successfully loaded (results in 401 responses downstream).
Expected Behavior
The JWK Set should load successfully (or at minimum, keys with a mismatched x5t should be skipped/logged as a warning rather than causing the entire refresh to fail), since Auth0 is a widely used IdP and this appears to be a common JWKS shape.
Actual Behavior
The JWK Set fails to refresh entirely. keyfunc.NewDefaultCtx returns successfully, but the background refresh never populates usable keys, so all subsequent token validation fails.
Title
JWK validation fails with "X5T in marshal does not match X5T in marshalled" when fetching Auth0's JWKS endpoint
Environment
github.com/MicahParks/keyfunc/v3(latest)github.com/golang-jwt/jwt/v5https://<tenant>.auth0.com/.well-known/jwks.json)Description
When using
keyfunc.NewDefaultCtxto build aKeyfuncfrom an Auth0 JWKS endpoint, every background refresh fails validation with the following error, and no keys are ever loaded:Because the JWK Set never loads successfully, every subsequent
jwt.Parsecall usingk.Keyfuncfails, resulting in401s for all incoming requests.Steps to Reproduce
JWKS Payload
keyfunc.NewDefaultCtxat any Auth0 tenant's.well-known/jwks.json.k.Keyfunc/jwt.Parsefails to validate tokens because no keys were ever successfully loaded (results in 401 responses downstream).Expected Behavior
The JWK Set should load successfully (or at minimum, keys with a mismatched
x5tshould be skipped/logged as a warning rather than causing the entire refresh to fail), since Auth0 is a widely used IdP and this appears to be a common JWKS shape.Actual Behavior
The JWK Set fails to refresh entirely.
keyfunc.NewDefaultCtxreturns successfully, but the background refresh never populates usable keys, so all subsequent token validation fails.