{"record":{"id":"50b19552b523d59f","repo":"bitwarden/server","slug":"duo-configuration-settings-are-not-valid-please-r","errorCode":null,"errorMessage":"Duo configuration settings are not valid. Please re-check the Duo Admin panel.","messagePattern":"Duo configuration settings are not valid\\. Please re-check the Duo Admin panel\\.","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"src/Api/Auth/Controllers/TwoFactorController.cs","lineNumber":250,"sourceCode":"    }\n\n    [HttpDelete(\"duo\")]\n    [ProducesResponseType(StatusCodes.Status204NoContent)]\n    public async Task<IActionResult> DeleteDuo([FromBody] TwoFactorDuoDeleteRequestModel model)\n    {\n        var user = await ValidateUserVerificationTokenAsync(model.UserVerificationToken, TwoFactorProviderType.Duo);\n        await _userService.DisableTwoFactorProviderAsync(user, TwoFactorProviderType.Duo);\n        return NoContent();\n    }\n\n    [HttpPut(\"duo\")]\n    public async Task<TwoFactorDuoUpdateResponseModel> PutDuo([FromBody] TwoFactorDuoUpdateRequestModel model)\n    {\n        var user = await ValidateUserVerificationTokenAsync(model.UserVerificationToken, TwoFactorProviderType.Duo);\n        await ValidateUserHasPremiumAsync(user);\n        if (!await _duoUniversalTokenService.ValidateDuoConfiguration(model.ClientSecret, model.ClientId, model.Host))\n        {\n            throw new BadRequestException(\n                \"Duo configuration settings are not valid. Please re-check the Duo Admin panel.\");\n        }\n\n        model.ToUser(user);\n        await _userService.UpdateTwoFactorProviderAsync(user, TwoFactorProviderType.Duo);\n        return new TwoFactorDuoUpdateResponseModel(user);\n    }\n\n    [HttpPost(\"duo\")]\n    [Obsolete(\"This endpoint is deprecated. Use PUT /duo instead.\")]\n    public async Task<TwoFactorDuoUpdateResponseModel> PostDuo([FromBody] TwoFactorDuoUpdateRequestModel model)\n    {\n        return await PutDuo(model);\n    }\n\n    [HttpPost(\"~/organizations/{id}/two-factor/get-duo\")]\n    public async Task<TwoFactorOrganizationDuoResponseModel> GetOrganizationDuo(string id,\n        [FromBody] SecretVerificationRequestModel model)","sourceCodeStart":232,"sourceCodeEnd":268,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/src/Api/Auth/Controllers/TwoFactorController.cs#L232-L268","documentation":"BadRequestException is thrown in PUT /duo (PutDuo) when _duoUniversalTokenService.ValidateDuoConfiguration(clientSecret, clientId, host) returns false. The Duo configuration triple must be reachable and internally consistent (credentials match a real Duo Admin panel integration); otherwise the provider cannot issue or verify Universal prompts.","triggerScenarios":"PUT /api/users/two-factor/duo (TwoFactorController line 250) submitted with a ClientId/ClientSecret/Host that fail Duo-side validation (wrong secret, wrong integration type, unreachable host, malformed host like missing .duosecurity.com).","commonSituations":"Copying the wrong integration's credentials, using Duo Classic (Web SDK) credentials instead of a Universal Prompt application, a typo in the host, network egress blocking api-*.duosecurity.com, or the Duo application being suspended/deleted.","solutions":["In the Duo Admin Panel, open the correct 'Univers2 / Universal Prompt' application and copy its Client ID, Client Secret, and API Hostname exactly.","Ensure the host includes the full domain (e.g. api-XXXX.duosecurity.com).","Confirm outbound network access from the server to the Duo API hostname.","Regenerate the client secret if it may have been rotated/expired."],"exampleFix":"// before\napi.put('/users/two-factor/duo', { clientId: 'di-xxx', clientSecret: 'dh-yyy', host: 'XXXX' })\n// after\napi.put('/users/two-factor/duo', { clientId: 'di-xxx', clientSecret: 'dh-yyy', host: 'api-XXXX.duosecurity.com' });","handlingStrategy":"validation","validationCode":"function validDuoConfig(c) { return /^di-/.test(c.clientId) && /^dh-/.test(c.clientSecret) && /^api-[a-z0-9]+\\.duosecurity\\.com$/i.test(c.host); }\nif (!validDuoConfig(model)) throw new Error('Invalid Duo configuration');","typeGuard":"function isDuoConfig(c): c is DuoConfig { return typeof c?.clientId === 'string' && typeof c?.clientSecret === 'string' && typeof c?.host === 'string'; }","tryCatchPattern":"try { await api.put('/users/two-factor/duo', model); }\ncatch (e) {\n  if (e.response?.status === 400 && /Duo configuration/.test(e.response.data?.message)) {\n    throw new UserFacingError('Re-check the Duo Admin panel for the correct Client ID, Secret, and Host.');\n  }\n  throw e;\n}","preventionTips":["Use a Universal Prompt Duo application, not Duo Classic.","Copy the full api-*.duosecurity.com hostname.","Verify server egress to the Duo API."],"tags":["two-factor","duo","configuration","sso"],"backgroundTag":null,"analyzedSha":"e93b962371d80964556f5590c6615f5160a437a1","analyzedAt":"2026-08-13T14:22:19.382Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}