bitwarden/server · error · BadRequestException
Unable to complete WebAuthn registration.
Error message
Unable to complete WebAuthn registration.
What it means
BadRequestException 'Unable to complete WebAuthn registration.' is thrown in POST /webauthn (WebAuthnController.Post) when _createWebAuthnLoginCredentialCommand.CreateWebAuthnLoginCredentialAsync returns null. The command performs fido2 attestation verification and persistence; null means attestation failed, the device response did not match the options, or the credential could not be saved.
Source
Thrown at src/Api/Auth/Controllers/WebAuthnController.cs:117
}
[Authorize(Policies.Application)]
[HttpPost("")]
public async Task<WebAuthnCredentialResponseModel> Post([FromBody] WebAuthnLoginCredentialCreateRequestModel model)
{
var user = await GetUserAsync();
await ValidateIfUserCanUsePasskeyLogin(user.Id);
var tokenable = _createOptionsDataProtector.Unprotect(model.Token);
if (!tokenable.TokenIsValid(user))
{
throw new BadRequestException("The token associated with your request is expired. A valid token is required to continue.");
}
var credential = await _createWebAuthnLoginCredentialCommand.CreateWebAuthnLoginCredentialAsync(user, model.Name, tokenable.Options, model.DeviceResponse, model.SupportsPrf, model.EncryptedUserKey, model.EncryptedPublicKey, model.EncryptedPrivateKey);
if (credential == null)
{
throw new BadRequestException("Unable to complete WebAuthn registration.");
}
return new WebAuthnCredentialResponseModel(credential);
}
private async Task ValidateIfUserCanUsePasskeyLogin(Guid userId)
{
var requireSsoPolicyRequirement = await _policyRequirementQuery.GetAsyncVNext<RequireSsoPolicyRequirement>(userId);
if (!requireSsoPolicyRequirement.CanUsePasskeyLogin)
{
throw new BadRequestException("Passkeys cannot be created for your account. SSO login is required.");
}
}
[Authorize(Policies.Application)]
[HttpPut()]
public async Task UpdateCredential([FromBody] WebAuthnLoginCredentialUpdateRequestModel model)View on GitHub (pinned to e93b962371)
Solutions
- Regenerate creation options and complete the ceremony in one flow without delay.
- Verify the calling origin matches the server's fido2 RP id configuration.
- Ensure EncryptedUserKey/EncryptedPublicKey/EncryptedPrivateKey are correctly encrypted for the user.
- Avoid registering the same passkey twice; delete the old one first if needed.
Example fix
// before
api.post('/webauthn', { token, name, deviceResponse, supportsPrf: false, encryptedUserKey: null })
// after
const encryptedUserKey = await cryptoService.encrypt(userKey);
api.post('/webauthn', { token, name, deviceResponse, supportsPrf, encryptedUserKey, encryptedPublicKey, encryptedPrivateKey }); Defensive patterns
Strategy: validation
Validate before calling
if (!model.token || !model.deviceResponse) throw new Error('Token and deviceResponse are required');
if (model.supportsPrf && !model.encryptedUserKey) throw new Error('EncryptedUserKey required with PRF'); Type guard
function isWebAuthnCreateModel(m): m is WebAuthnCreateModel { return !!m?.token && !!m?.deviceResponse && typeof m.name === 'string'; } Try / catch
try { await api.post('/webauthn', model); }
catch (e) {
if (e.response?.status === 400 && /WebAuthn registration/.test(e.response.data?.message)) {
throw new RetryableError('Restart the WebAuthn flow with fresh options');
}
throw e;
} Prevention
- Match the origin/RP id to server fido2 config.
- Provide all encrypted key fields when supportsPrf is true.
- Avoid registering the same credential twice.
When it happens
Trigger: POST /webauthn (passkey creation, line 117) where model.DeviceResponse fails fido2 attestation/challenge verification against tokenable.Options, or the credential already exists (duplicate credential id).
Common situations: Device response generated against different options/origin/RP id, unsupported authenticator, expired challenge, duplicate registration of the same credential, or PRF/encrypted-key payload issues (model.EncryptedUserKey/EncryptedPublicKey/EncryptedPrivateKey malformed).
Related errors
- Unable to complete WebAuthn registration.
- Cannot edit item. Update to the latest version of Bitwarden
- The token associated with your request is expired. A valid t
- Passkeys cannot be created for your account. SSO login is re
- The token associated with your request is invalid or has exp
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/daf842a6308a83dc.
Report an issue: GitHub.