{"record":{"id":"fdfa10b9d7c3d555","repo":"hashicorp/nomad","slug":"oidcclientsecret-is-required-for-client-secret-k","errorCode":null,"errorMessage":"OIDCClientSecret is required for `client_secret` KeySource","messagePattern":"OIDCClientSecret is required for `client_secret` KeySource","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/acl.go","lineNumber":1785,"sourceCode":"func (c *OIDCClientAssertion) Validate() error {\n\tif c == nil {\n\t\treturn nil\n\t}\n\tif len(c.Audience) == 0 || c.Audience[0] == \"\" {\n\t\treturn errors.New(\"missing Audience\")\n\t}\n\tswitch c.KeySource {\n\tcase OIDCKeySourceNomad:\n\tcase OIDCKeySourcePrivateKey:\n\t\tif c.PrivateKey == nil {\n\t\t\treturn errors.New(\"PrivateKey is required for `private_key` KeySource\")\n\t\t}\n\t\tif err := c.PrivateKey.Validate(); err != nil {\n\t\t\treturn fmt.Errorf(\"invalid PrivateKey: %w\", err)\n\t\t}\n\tcase OIDCKeySourceClientSecret:\n\t\tif c.ClientSecret == \"\" {\n\t\t\treturn errors.New(\"OIDCClientSecret is required for `client_secret` KeySource\")\n\t\t}\n\tdefault:\n\t\treturn fmt.Errorf(\"invalid KeySource %q\", c.KeySource)\n\t}\n\treturn nil\n}\n\ntype OIDCClientAssertionKeyIDHeader string\n\nconst (\n\tOIDCClientAssertionHeaderKid     OIDCClientAssertionKeyIDHeader = \"kid\"\n\tOIDCClientAssertionHeaderX5t     OIDCClientAssertionKeyIDHeader = \"x5t\"\n\tOIDCClientAssertionHeaderX5tS256 OIDCClientAssertionKeyIDHeader = \"x5t#S256\"\n)\n\n// OIDCClientAssertionKey contains key material provided by users for Nomad\n// to use to sign the private key JWT.\n// See api.OIDCClientAssertionKey for full field descriptions.","sourceCodeStart":1767,"sourceCodeEnd":1803,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/acl.go#L1767-L1803","documentation":"Returned by OIDCClientAssertion.Validate when KeySource is client_secret but ClientSecret is empty. That key source signs client assertions with the secret, so a missing secret makes the assertion configuration unusable.","triggerScenarios":"Configuring OIDCClientAssertion with KeySource \"client_secret\" while ClientSecret is empty, then upserting the auth method.","commonSituations":"Secrets left to a template variable that rendered empty; teams switching from nomad/private_key key sources and not yet obtaining the IdP client secret; redaction tooling that blanked the secret before submission.","solutions":["Set OIDCClientAssertion.ClientSecret to the secret from the IdP client registration","Load the secret from a secure source (Vault, env) at deploy time and verify it is non-empty","Choose a different KeySource if no client secret exists"],"exampleFix":"// before\nassertion := &api.OIDCClientAssertion{KeySource: \"client_secret\", Audience: aud, ClientSecret: \"\"}\n// after\nassertion := &api.OIDCClientAssertion{KeySource: \"client_secret\", Audience: aud, ClientSecret: os.Getenv(\"OIDC_CLIENT_SECRET\")}","handlingStrategy":"validation","validationCode":"func clientSecretAssertionOK(c *structs.OIDCClientAssertion) bool {\n  return c == nil || c.KeySource != structs.OIDCKeySourceClientSecret || c.ClientSecret != \"\"\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Inject the secret from Vault/env at deploy time","Assert non-empty secret before upserting; avoid redaction tools that blank it"],"tags":["nomad","oidc","validation","client-secret"],"backgroundTag":"missing-client-secret","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"}