{"record":{"id":"2be3802f3a196d33","repo":"bitwarden/server","slug":"invalid-password","errorCode":null,"errorMessage":"Invalid password.","messagePattern":"Invalid password\\.","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"src/Api/AdminConsole/Controllers/OrganizationsController.cs","lineNumber":406,"sourceCode":"            {\n                throw new NotFoundException();\n            }\n        }\n\n        var organizationApiKey = await _getOrganizationApiKeyQuery\n                                     .GetOrganizationApiKeyAsync(organization.Id, model.Type) ??\n                                 await _createOrganizationApiKeyCommand.CreateAsync(organization.Id, model.Type);\n\n        var user = await _userService.GetUserByPrincipalAsync(User);\n        if (user == null)\n        {\n            throw new UnauthorizedAccessException();\n        }\n\n        if (!await _userService.VerifySecretAsync(user, model.Secret))\n        {\n            await Task.Delay(2000);\n            throw new BadRequestException(\"MasterPasswordHash\", \"Invalid password.\");\n        }\n\n        var response = new ApiKeyResponseModel(organizationApiKey);\n        return response;\n    }\n\n    [HttpGet(\"{id}/api-key-information/{type?}\")]\n    public async Task<ListResponseModel<OrganizationApiKeyInformation>> ApiKeyInformation(Guid id,\n        [FromRoute] OrganizationApiKeyType? type)\n    {\n        if (!await HasApiKeyAccessAsync(id, type))\n        {\n            throw new NotFoundException();\n        }\n\n        var apiKeys = await _organizationApiKeyRepository.GetManyByOrganizationIdTypeAsync(id, type);\n\n        return new ListResponseModel<OrganizationApiKeyInformation>(","sourceCodeStart":388,"sourceCodeEnd":424,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/src/Api/AdminConsole/Controllers/OrganizationsController.cs#L388-L424","documentation":"Thrown as a 400 BadRequestException(\"MasterPasswordHash\", \"Invalid password.\") from the organization API-key retrieval endpoint. After resolving the user and the organization API key, the caller's secret (model.Secret) is verified via _userService.VerifySecretAsync; on failure a 2-second delay runs and the error is keyed under MasterPasswordHash. This guards retrieval of an organization API key (e.g., SCIM key) behind master-password re-verification.","triggerScenarios":"POST to get/create an organization API key with a valid session and existing API key record, but model.Secret does not verify against the current user. Occurs when the admin's stored master-password hash differs from the supplied hash.","commonSituations":"Admin entered the wrong master password in the 'verify to view API key' prompt; client derived the hash with outdated KDF iterations after a server-side KDF change; password was changed elsewhere and the local session still holds the old derived hash.","solutions":["Re-derive MasterPasswordHash with the user's current KDF configuration and resubmit model.Secret.","If the password was recently changed, sign out and back in so the client recomputes the hash.","Confirm the field sent is the secret the endpoint expects (Secret) and that it is the derived hash, not plaintext.","Verify the authenticated principal is the account whose secret is being checked."],"exampleFix":"// before\nbody.Secret = oldHash;\n// after\nbody.Secret = await crypto.hashPassword(masterPassword, user.kdf);\nawait api.post(`organizations/${id}/api-key`, body);","handlingStrategy":"try-catch","validationCode":"function validSecret(secret) {\n  return typeof secret === 'string' && 0 < secret.length && secret.length < 1024;\n}","typeGuard":"function isSecretModel(v): v is { secret: string } {\n  return !!v && typeof v.secret === 'string' && v.secret.length > 0;\n}","tryCatchPattern":"try {\n  await api.post(`organizations/${id}/api-key`, body);\n} catch (e) {\n  if (e?.response?.status === 400 && e.response.data?.ValidationErrors?.['MasterPasswordHash']?.some(m => /Invalid password/i.test(m))) {\n    promptForMasterPasswordAgain();\n  } else throw e;\n}","preventionTips":["Derive the master-password hash with the current KDF before sending.","Re-authenticate after a password or KDF change.","Send the derived hash, never plaintext."],"tags":["bitwarden","authentication","secret-verification","api-key","aspnet"],"backgroundTag":null,"analyzedSha":"e93b962371d80964556f5590c6615f5160a437a1","analyzedAt":"2026-08-13T14:22:19.382Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}