bitwarden/server · error · BadRequestException
Duo configuration settings are not valid. Please re-check th
Error message
Duo configuration settings are not valid. Please re-check the Duo Admin panel.
What it means
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.
Source
Thrown at src/Api/Auth/Controllers/TwoFactorController.cs:250
}
[HttpDelete("duo")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task<IActionResult> DeleteDuo([FromBody] TwoFactorDuoDeleteRequestModel model)
{
var user = await ValidateUserVerificationTokenAsync(model.UserVerificationToken, TwoFactorProviderType.Duo);
await _userService.DisableTwoFactorProviderAsync(user, TwoFactorProviderType.Duo);
return NoContent();
}
[HttpPut("duo")]
public async Task<TwoFactorDuoUpdateResponseModel> PutDuo([FromBody] TwoFactorDuoUpdateRequestModel model)
{
var user = await ValidateUserVerificationTokenAsync(model.UserVerificationToken, TwoFactorProviderType.Duo);
await ValidateUserHasPremiumAsync(user);
if (!await _duoUniversalTokenService.ValidateDuoConfiguration(model.ClientSecret, model.ClientId, model.Host))
{
throw new BadRequestException(
"Duo configuration settings are not valid. Please re-check the Duo Admin panel.");
}
model.ToUser(user);
await _userService.UpdateTwoFactorProviderAsync(user, TwoFactorProviderType.Duo);
return new TwoFactorDuoUpdateResponseModel(user);
}
[HttpPost("duo")]
[Obsolete("This endpoint is deprecated. Use PUT /duo instead.")]
public async Task<TwoFactorDuoUpdateResponseModel> PostDuo([FromBody] TwoFactorDuoUpdateRequestModel model)
{
return await PutDuo(model);
}
[HttpPost("~/organizations/{id}/two-factor/get-duo")]
public async Task<TwoFactorOrganizationDuoResponseModel> GetOrganizationDuo(string id,
[FromBody] SecretVerificationRequestModel model)View on GitHub (pinned to e93b962371)
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.
Example fix
// before
api.put('/users/two-factor/duo', { clientId: 'di-xxx', clientSecret: 'dh-yyy', host: 'XXXX' })
// after
api.put('/users/two-factor/duo', { clientId: 'di-xxx', clientSecret: 'dh-yyy', host: 'api-XXXX.duosecurity.com' }); Defensive patterns
Strategy: validation
Validate before calling
function validDuoConfig(c) { return /^di-/.test(c.clientId) && /^dh-/.test(c.clientSecret) && /^api-[a-z0-9]+\.duosecurity\.com$/i.test(c.host); }
if (!validDuoConfig(model)) throw new Error('Invalid Duo configuration'); Type guard
function isDuoConfig(c): c is DuoConfig { return typeof c?.clientId === 'string' && typeof c?.clientSecret === 'string' && typeof c?.host === 'string'; } Try / catch
try { await api.put('/users/two-factor/duo', model); }
catch (e) {
if (e.response?.status === 400 && /Duo configuration/.test(e.response.data?.message)) {
throw new UserFacingError('Re-check the Duo Admin panel for the correct Client ID, Secret, and Host.');
}
throw e;
} Prevention
- Use a Universal Prompt Duo application, not Duo Classic.
- Copy the full api-*.duosecurity.com hostname.
- Verify server egress to the Duo API.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- NoDomainHintProvided
- InvalidSsoToken
- ExternalAuthenticationError
- OrganizationOrSsoConfigNotFound
- AcrMissingOrInvalid
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/50b19552b523d59f.
Report an issue: GitHub.