hashicorp/nomad · error
unable to get validation keys from OIDC provider: %v
Error message
unable to get validation keys from OIDC provider: %v
What it means
usingOIDC fails when jwt.NewOIDCDiscoveryKeySet cannot complete OIDC discovery — fetching `<oidc_discovery_url>/.well-known/openid-configuration` and then the JWKS it references. This is typically a network/TLS problem or an endpoint that is not a valid OIDC provider.
Source
Thrown at lib/auth/jwt/validator.go:124
if err != nil {
return nil, fmt.Errorf("unable to get validation keys from JWKS: %v", err)
}
return keySet, nil
}
func usingOIDC(ctx context.Context, oidcurl string, oidccapem []string) (jwt.KeySet, error) {
// Measure the OIDC endpoint performance.
defer metrics.MeasureSince([]string{"nomad", "acl", "jwt", "oidc_jwt"}, time.Now())
// TODO why do we have DiscoverCaPem as an array but JWKSCaPem as a single string?
pem := ""
if len(oidccapem) > 0 {
pem = oidccapem[0]
}
keySet, err := jwt.NewOIDCDiscoveryKeySet(ctx, oidcurl, pem)
if err != nil {
return nil, fmt.Errorf("unable to get validation keys from OIDC provider: %v", err)
}
return keySet, nil
}
View on GitHub (pinned to 482b49bf1a)
Solutions
- Verify `curl <oidc_discovery_url>/.well-known/openid-configuration` returns valid discovery JSON from a Nomad server.
- Set OidcDiscoveryCACert to the PEM of the CA that signed the provider's certificate if using a private/self-signed CA.
- Fix the OidcDiscoveryURL (include issuer path, e.g. `https://idp.example.com/realms/prod`).
- Check provider availability and Nomad server egress/firewall rules.
Example fix
// before
cfg := &structs.ACLAuthMethodConfig{
OidcDiscoveryURL: "https://idp.internal:8443",
}
// after: CA pinned for private endpoint
cfg := &structs.ACLAuthMethodConfig{
OidcDiscoveryURL: "https://idp.internal:8443/realms/main",
OidcDiscoveryCACert: "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
} Defensive patterns
Strategy: validation
Validate before calling
discURL := strings.TrimSuffix(oidcURL, "/") + "/.well-known/openid-configuration"
resp, err := http.Get(discURL)
if err != nil { return fmt.Errorf("discovery unreachable: %w", err) }
if resp.StatusCode != 200 { return fmt.Errorf("discovery returned %d", resp.StatusCode) }
var doc struct{ Issuer string `json:"issuer"`; JwksURI string `json:"jwks_uri"` }
json.NewDecoder(resp.Body).Decode(&doc)
if doc.Issuer == "" || doc.JwksURI == "" { return fmt.Errorf("not a valid OIDC discovery doc") } Try / catch
keySet, err := usingOIDC(ctx, oidcURL, caPEMs)
if err != nil {
return fmt.Errorf("verify OidcDiscoveryURL and OidcDiscoveryCACert: %w", err)
} Prevention
- Validate the discovery URL returns openid-configuration JSON before configuring the auth method.
- Set OidcDiscoveryCACert when the provider uses a private CA.
- Include the full issuer path (realm/tenant) in OidcDiscoveryURL.
When it happens
Trigger: Validate → usingOIDC when the auth method uses OidcDiscoveryURL and discovery document or key fetch fails, including when OidcDiscoveryCACert cannot validate the provider's TLS chain.
Common situations: Internal OIDC provider with private CA and no OidcDiscoveryCACert set; discovery URL missing the realm/tenant path; provider temporarily down; egress blocked from Nomad servers; provider does not publish openid-configuration at the expected path.
Related errors
- unable to get validation keys from JWKS: %v
- no auth method config or client assertion
- certificate has expired or is not yet valid
- x5t assertion headers use SHA-1, which is forbidden in FIPS-
- missing Audience
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/545b6504a103461c.
Report an issue: GitHub.