{"record":{"id":"a74764e290d99262","repo":"hashicorp/nomad","slug":"failed-to-retrieve-oidc-provider-metadata-w","errorCode":null,"errorMessage":"failed to retrieve OIDC provider metadata: %w","messagePattern":"failed to retrieve OIDC provider metadata: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/acl_endpoint.go","lineNumber":2776,"sourceCode":"\t\tif done, err := a.srv.forward(structs.ACLOIDCCompleteAuthRPCMethod, args, args, reply); done {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// Use the cache to provide us with an OIDC provider for the auth method\n\t// that was resolved from state.\n\toidcProvider, err := a.oidcProviderCache.Get(authMethod)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to generate OIDC provider: %v\", err)\n\t}\n\n\t// Check if the OIDC provider requires the `iss` parameter to be\n\t// validated\n\tproviderMetadata := struct {\n\t\tAuthorizationResponseIssParameterSupported bool `json:\"authorization_response_iss_parameter_supported\"`\n\t}{}\n\tif err := oidcProvider.Claims(&providerMetadata); err != nil {\n\t\treturn fmt.Errorf(\"failed to retrieve OIDC provider metadata: %w\", err)\n\t}\n\tif providerMetadata.AuthorizationResponseIssParameterSupported {\n\t\tif args.Iss == \"\" || args.Iss != authMethod.Config.OIDCDiscoveryURL {\n\t\t\treturn errors.New(\"invalid or missing issuer parameter in callback\")\n\t\t}\n\t}\n\n\t// Retrieve the request generated in OIDCAuthURL()\n\toidcReq := a.oidcRequestCache.LoadAndDelete(args.ClientNonce) // I am so done with this NONCENSE\n\tif oidcReq == nil {\n\t\t// note: this may happen if there is a leader election between getting\n\t\t// the auth url and completing the login flow here.\n\t\treturn errors.New(\"no OIDC request found for client nonce\")\n\t}\n\n\t// Generate a context with a deadline. This is passed to the OIDC provider\n\t// and used when making remote HTTP requests.\n\tctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(aclOIDCCallbackRequestExpiryTime))","sourceCodeStart":2758,"sourceCodeEnd":2794,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/acl_endpoint.go#L2758-L2794","documentation":"During OIDCCompleteAuth, Nomad reads provider metadata via oidcProvider.Claims to see whether the IdP supports the authorization_response_iss parameter. If the underlying library fails to extract those claims from the cached provider's discovery data, the error is wrapped as 'failed to retrieve OIDC provider metadata'.","triggerScenarios":"Calling OIDCCompleteAuth when the provider's discovery document lacks or fails to decode the expected claims — malformed/partial .well-known/openid-configuration, a provider object that could not fully load metadata, or library decode errors.","commonSituations":"IdP behind a proxy that truncates or mangles the discovery document; non-standard OIDC implementation with incomplete metadata; transient network failure during provider construction earlier in the flow.","solutions":["Inspect the wrapped error for the underlying decode/claim failure.","Fetch <discovery-url>/.well-known/openid-configuration with curl and validate the JSON fields.","Fix or replace the non-compliant IdP discovery endpoint (or upgrade the IdP to a compliant version).","Clear any stale provider state by restarting the login flow after correcting the discovery URL/config."],"exampleFix":"// before: discovery URL points at an app that returns HTML\nconfig := &api.ACLAuthMethodConfig{OIDCDiscoveryURL: \"https://idp.example.com/app\"}\n// after: point at the real OIDC discovery root\nconfig := &api.ACLAuthMethodConfig{OIDCDiscoveryURL: \"https://idp.example.com/realms/main\"}","handlingStrategy":"fallback","validationCode":"resp, err := http.Get(discoveryURL + \"/.well-known/openid-configuration\")\nif err != nil { return err }\nvar doc map[string]interface{}\nif err := json.NewDecoder(resp.Body).Decode(&doc); err != nil {\n    return fmt.Errorf(\"discovery doc is not valid JSON: %w\", err)\n}\nlog.Printf(\"iss parameter support: %v\", doc[\"authorization_response_iss_parameter_supported\"])","typeGuard":"func looksLikeOIDCDiscovery(body []byte) bool {\n    var m map[string]interface{}\n    if json.Unmarshal(body, &m) != nil { return false }\n    _, hasIssuer := m[\"issuer\"]\n    _, hasAuthEp := m[\"authorization_endpoint\"]\n    return hasIssuer && hasAuthEp\n}","tryCatchPattern":"_, _, err := client.ACL().GetOIDCCompleteAuth(req, nil)\nif err != nil && strings.Contains(err.Error(), \"failed to retrieve OIDC provider metadata\") {\n    return fmt.Errorf(\"IdP discovery document incomplete/non-compliant; validate %s/.well-known/openid-configuration: %w\", discoveryURL, err)\n}","preventionTips":["Validate the discovery document JSON after configuring a new auth method","Use a standards-compliant IdP (Keycloak/Okta/Auth0) behind stable endpoints","Check proxies don't modify or truncate .well-known responses","Retry the login flow if a transient network error corrupted provider metadata"],"tags":["nomad","acl","oidc","sso","metadata"],"backgroundTag":"oidc-discovery-failed","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}