{"record":{"id":"9d1cb30425e5a756","repo":"hashicorp/nomad","slug":"no-auth-method-config-or-client-assertion","errorCode":null,"errorMessage":"no auth method config or client assertion","messagePattern":"no auth method config or client assertion","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/auth/oidc/client_assertion.go","lineNumber":57,"sourceCode":"//   - \"client_secret\": uses the config's ClientSecret as an HMAC key to sign\n//     the JWT. This is marginally more secure than a bare ClientSecret, as the\n//     JWT is time-bound, and signed by the secret rather than sending the\n//     secret itself over the network.\n//   - \"nomad\": uses the RS256 nomadKey (Nomad's private key) to sign the JWT,\n//     and the nomadKID as the JWT's \"kid\" header, which the OIDC provider uses\n//     to find the public key at Nomad's JWKS endpoint (/.well-known/jwks.json)\n//     to verify the JWT signature. This is arguably the most secure option,\n//     because only Nomad has the private key.\n//   - \"private_key\": uses an RSA private key provided by the user. They may\n//     provide a KeyID to use as the JWT's \"kid\" header, or an x509 public\n//     certificate to derive an x5t#S256 (or x5t) header, which the OIDC\n//     provider uses to find the cert on their end to verify the JWT signature.\n//     This is the most flexible option, allowing users to manage their own\n//     keys however they like.\nfunc BuildClientAssertionJWT(config *structs.ACLAuthMethodConfig, nomadKey *rsa.PrivateKey, nomadKID string) (*cass.JWT, error) {\n\t// should already be validated by caller, but just in case.\n\tif config == nil || config.OIDCClientAssertion == nil {\n\t\treturn nil, errors.New(\"no auth method config or client assertion\")\n\t}\n\n\t// this is all we use config for\n\tclientID := config.OIDCClientID\n\t// client assertion-specific info is in here\n\tas := config.OIDCClientAssertion\n\n\t// this should have also happened long before, but again, just in case.\n\tif err := as.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\topts := []cass.Option{\n\t\tcass.WithHeaders(as.ExtraHeaders),\n\t}\n\n\tswitch as.KeySource {\n","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/lib/auth/oidc/client_assertion.go#L39-L75","documentation":"BuildClientAssertionJWT returns this error when the ACLAuthMethodConfig is nil or has no OIDCClientAssertion configured. A client-assertion JWT cannot be built without the private-key/JWKS/derived-key assertion settings, and the function refuses to proceed.","triggerScenarios":"Calling BuildClientAssertionJWT with config == nil, or config.OIDCClientAssertion == nil — i.e. the auth method is not configured for OIDC client assertion (private_key_jwt).","commonSituations":"OIDC auth method configured without BoundAudiences/ClientAssertion while the OIDC provider requires private_key_jwt; calling the assertion builder for auth methods using a different client authentication style (client_secret); config dropped or overwritten in the ACL auth method update.","solutions":["Configure OIDCClientAssertion (with key source: private key, JWKS, or derived key) on the ACL auth method before enabling private_key_jwt","Verify the auth method's config is loaded and non-nil before building the assertion","If the provider uses client_secret auth instead, do not use the client assertion path","Re-check the ACL auth method after any config update that may have cleared the assertion settings"],"exampleFix":"// before: missing assertion config\nauthMethodConfig := &structs.ACLAuthMethodConfig{\n  OIDCClientID: \"nomad\",\n}\njwt, err := auth.BuildClientAssertionJWT(authMethodConfig, key, kid) // errors\n// after: configure the assertion\nauthMethodConfig := &structs.ACLAuthMethodConfig{\n  OIDCClientID:        \"nomad\",\n  OIDCClientAssertion: &structs.OIDCClientAssertion{KeySource: \"nomad\", ...},\n}\njwt, err := auth.BuildClientAssertionJWT(authMethodConfig, key, kid)","handlingStrategy":"validation","validationCode":"if config == nil || config.OIDCClientAssertion == nil {\n  // fall back to client_secret auth or configure assertion first\n  return errors.New(\"auth method lacks OIDC client assertion; cannot use private_key_jwt\")\n}","typeGuard":"func hasClientAssertion(c *structs.ACLAuthMethodConfig) bool {\n  return c != nil && c.OIDCClientAssertion != nil\n}","tryCatchPattern":"jwt, err := auth.BuildClientAssertionJWT(config, key, kid)\nif err != nil && strings.Contains(err.Error(), \"no auth method config or client assertion\") {\n  return configureAssertionThenRetry()\n}","preventionTips":["Validate the ACL auth method config on create/update so assertion settings are required when the provider uses private_key_jwt","Check hasClientAssertion before choosing the client-assertion auth flow","Keep auth method configs in version control to catch accidental clearing","Match the assertion style (private key / JWKS / derived key) to what the OIDC provider documents"],"tags":["oidc","jwt","authentication","configuration","nomad"],"backgroundTag":"missing-client-assertion-config","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"}