{"record":{"id":"1bd8bc9ce6a366f6","repo":"git-ecosystem/git-credential-manager","slug":"client-assertion-must-be-provided-for-generic-work","errorCode":null,"errorMessage":"Client assertion must be provided for generic workload federation scenario.","messagePattern":"Client assertion must be provided for generic workload federation scenario\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Core/Authentication/Entra/EntraAuthentication.ConfidentialClient.cs","lineNumber":94,"sourceCode":"            .WithClientAssertion(reqOpts => GetClientAssertion(fedOpts, reqOpts));\n\n        IConfidentialClientApplication app = builder.Build();\n        await RegisterCacheAsync(app);\n\n        AuthenticationResult result = await app.AcquireTokenForClient(scopes)\n            .ExecuteAsync(ct);\n\n        return AuthResult.FromMsalResult(result);\n    }\n\n    private async Task<string> GetClientAssertion(WorkloadFederationOptions fedOpts, AssertionRequestOptions _)\n    {\n        switch (fedOpts.Scenario)\n        {\n            case WorkloadFederationScenario.Generic:\n                Context.Trace.WriteLine(\"Getting client assertion for generic workload federation scenario...\");\n                if (string.IsNullOrWhiteSpace(fedOpts.GenericClientAssertion))\n                    throw new InvalidOperationException(\n                        \"Client assertion must be provided for generic workload federation scenario.\");\n                return fedOpts.GenericClientAssertion;\n\n            case WorkloadFederationScenario.ManagedIdentity:\n                Context.Trace.WriteLine(\n                    \"Getting client assertion for managed identity workload federation scenario...\");\n                var mi = ManagedIdentity.Create(fedOpts.ManagedIdentityId);\n                var miResult = await GetTokenForManagedIdentityAsync(fedOpts.Audience, mi);\n                return miResult.AccessToken;\n\n            case WorkloadFederationScenario.GitHubActions:\n                Context.Trace.WriteLine(\"Getting client assertion for GitHub Actions workload federation scenario...\");\n                return await GetGitHubOidcToken(fedOpts.GitHubTokenRequestUrl, fedOpts.Audience,\n                    fedOpts.GitHubTokenRequestToken);\n\n            default:\n                throw new ArgumentOutOfRangeException(nameof(fedOpts.Scenario), fedOpts.Scenario,\n                    \"Unsupported workload federation scenario.\");","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/git-ecosystem/git-credential-manager/blob/e8ce762cd04b4100ae637b5fbf39ef9d0a96561e/src/Core/Authentication/Entra/EntraAuthentication.ConfidentialClient.cs#L76-L112","documentation":"For the 'Generic' workload identity federation scenario, GCM must be handed a pre-obtained client assertion (a signed JWT) to exchange for tokens. This throws when credentialOptions.GenericClientAssertion is missing or whitespace, since there is nothing to authenticate with.","triggerScenarios":"GetClientAssertion switch hits case WorkloadFederationScenario.Generic and string.IsNullOrWhiteSpace(fedOpts.GenericClientAssertion) is true — i.e. workload federation is configured as Generic but no client assertion option was supplied.","commonSituations":"Using GitHub/GitLab/Azure workload federation via GCM but forgetting to supply the OIDC-derived client assertion option; a CI script that failed to fetch the ID token before invoking GCM; typo'd configuration key so the assertion never reaches fedOpts.","solutions":["Provide the client assertion via the GCM configuration option for the generic scenario (e.g. credential.workloadIdentity options carrying GenericClientAssertion)","Ensure the CI step that mints the OIDC/ID token runs before git/GCM and passes the token through","Fix the config key so the assertion is actually read into GenericClientAssertion","If you don't have a pre-minted assertion, use a supported scenario (GitHubActions or ManagedIdentity) instead of Generic"],"exampleFix":"// before\nvar fedOpts = new WorkloadIdentityCredentialOptions { Scenario = WorkloadFederationScenario.Generic };\n// after\nvar fedOpts = new WorkloadIdentityCredentialOptions {\n    Scenario = WorkloadFederationScenario.Generic,\n    GenericClientAssertion = clientAssertionJwt // must be non-empty\n};","handlingStrategy":"validation","validationCode":"if (fedOpts.Scenario == WorkloadFederationScenario.Generic && string.IsNullOrWhiteSpace(fedOpts.GenericClientAssertion))\n    throw new InvalidOperationException(\"Generic workload federation requires GenericClientAssertion.\");","typeGuard":"bool HasClientAssertion(WorkloadIdentityCredentialOptions o) =>\n    o.Scenario != WorkloadFederationScenario.Generic || !string.IsNullOrWhiteSpace(o.GenericClientAssertion);","tryCatchPattern":"try { /* entra auth */ }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"Client assertion must be provided\")) { /* mint or pass the assertion, then retry */ }","preventionTips":["Mint the OIDC ID token before invoking git/GCM in CI","Verify config keys that carry the assertion are spelled correctly","Use GitHubActions/ManagedIdentity scenarios when no pre-minted assertion is available"],"tags":["workload-identity-federation","client-assertion","entra","config"],"backgroundTag":"missing-required-config-field","analyzedSha":"e8ce762cd04b4100ae637b5fbf39ef9d0a96561e","analyzedAt":"2026-09-11T17:15:08.753Z","contentChangedAt":"2026-09-11T17:15:08.753Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}