{"record":{"id":"0e64265ab4231e85","repo":"git-ecosystem/git-credential-manager","slug":"public-client-configuration-is-required-for-user-a","errorCode":null,"errorMessage":"Public client configuration is required for user authentication.","messagePattern":"Public client configuration is required for user authentication\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Core/Authentication/Entra/EntraAuthentication.PublicClient.cs","lineNumber":444,"sourceCode":"\n    private Task ShowDeviceCodeAsync(DeviceCodeResult dcr)\n    {\n        Context.Console.WriteLine(dcr.Message);\n        return Task.CompletedTask;\n    }\n\n    private PublicClientApplicationBuilder _publicBuilder;\n    private bool _useBroker;\n\n    /// <summary>\n    /// Gets the public client application builder.\n    /// </summary>\n    /// <param name=\"useBroker\">True if the broker will be used for this applications build using this builder.</param>\n    private PublicClientApplicationBuilder GetPublicAppBuilder(out bool useBroker)\n    {\n        if (_publicClientConfig is null)\n        {\n            throw new InvalidOperationException(\n                \"Public client configuration is required for user authentication.\");\n        }\n\n        if (_publicBuilder is null)\n        {\n            Context.Trace.WriteLine(\"Creating public client application builder...\");\n            var builder = PublicClientApplicationBuilder.Create(_publicClientConfig.ClientId)\n                .WithHttpClientFactory(_httpFactory)\n                .WithTraceLogging(Context)\n                .WithLegacyCacheCompatibility(false)\n                .WithDefaultRedirectUri();\n\n            // Try and configure the broker if the user has opted in to using it,\n            // and it is available in the current environment\n            if (Context.SessionManager.IsDesktopSession && IsBrokerEnabled())\n            {\n                // Check that the app config supports the broker on this platform\n                if (_publicClientConfig.SupportsWindowsBroker && PlatformUtils.IsWindows() ||","sourceCodeStart":426,"sourceCodeEnd":462,"githubUrl":"https://github.com/git-ecosystem/git-credential-manager/blob/e8ce762cd04b4100ae637b5fbf39ef9d0a96561e/src/Core/Authentication/Entra/EntraAuthentication.PublicClient.cs#L426-L462","documentation":"Thrown from GetPublicAppBuilder when user (public client) authentication is attempted but no public client configuration (_publicClientConfig) has been set on the EntraAuthentication instance. Public client flows (interactive, device code, broker) require this configuration; without it the builder cannot be created.","triggerScenarios":"Calling GetTokenForUserAsync (directly or via GetInteractionModeAsync) on an EntraAuthentication instance that was constructed/configured only for confidential/client flows, without supplying a public client configuration.","commonSituations":"Mixing up service-principal and user authentication setup — the code path is initialized for client credentials but user token acquisition is requested; a configuration object was never passed to the EntraAuthentication constructor/factory; refactoring removed the public client setup call.","solutions":["Provide a public client configuration when constructing/configuring EntraAuthentication before calling user-authentication APIs.","Ensure you are calling the correct token method for your setup: use client-credential flows for confidential clients instead of GetTokenForUserAsync.","Check initialization order — the public client config must be set before the first GetTokenForUser* call."],"exampleFix":"// before\nvar auth = new EntraAuthentication(context);\nvar token = await auth.GetTokenForUserAsync(scopes); // throws: no public client config\n// after\nvar auth = EntraAuthentication.CreateWithPublicClientConfig(context, publicClientConfig);\nvar token = await auth.GetTokenForUserAsync(scopes);","handlingStrategy":"validation","validationCode":"if (publicClientConfig is null)\n    throw new InvalidOperationException(\"Public client configuration must be provided before user authentication.\");","typeGuard":null,"tryCatchPattern":"try\n{\n    token = await auth.GetTokenForUserAsync(scopes);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"Public client configuration\"))\n{\n    // re-initialize with a public client configuration, then retry once\n    auth = ConfigurePublicClient();\n    token = await auth.GetTokenForUserAsync(scopes);\n}","preventionTips":["Initialize both public and confidential client configurations up front if both flows are used.","Route service-principal workloads to client-credential APIs instead of user APIs.","Assert configuration completeness in a startup validation step."],"tags":["authentication","configuration","public-client","missing-config"],"backgroundTag":"missing-required-config","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"}