{"record":{"id":"57fdf7fe3dec1ea0","repo":"passbolt/passbolt_api","slug":"the-key-provided-does-not-belong-to-given-user","errorCode":null,"errorMessage":"The key provided does not belong to given user.","messagePattern":"The key provided does not belong to given user\\.","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"src/Service/Setup/RecoverCompleteService.php","lineNumber":97,"sourceCode":"    }\n\n    /**\n     * Validate the user and the gpgkey\n     *\n     * @param string $userId User ID\n     * @return \\App\\Model\\Entity\\User\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the data provided is not valid\n     */\n    protected function validateData(string $userId): User\n    {\n        // Check request sanity\n        $user = $this->getAndAssertUser($userId);\n        $gpgkey = $this->getAndAssertGpgkey($userId);\n\n        // Check that the \"new\" gpg key match the old one\n        $userKey = $this->Gpgkeys->getByFingerprintAndUserId($gpgkey->fingerprint, $userId);\n        if (empty($userKey)) {\n            throw new BadRequestException(__('The key provided does not belong to given user.'));\n        }\n\n        return $user;\n    }\n\n    /**\n     * Return the user for matching the requesting id\n     *\n     * @param string $userId the user uuid\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the user id is not a valid uuid\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the user was deleted or has not completed the setup\n     * @return \\App\\Model\\Entity\\User\n     */\n    protected function getAndAssertUser(string $userId): User\n    {\n        try {\n            return (new UserGetService())->getActiveNotDeletedNotDisabledOrFail($userId);\n        } catch (NotFoundException $exception) {","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/src/Service/Setup/RecoverCompleteService.php#L79-L115","documentation":"Thrown by validateData in RecoverCompleteService when the fingerprint of the OpenPGP key submitted with the recovery does not match any stored key for that user. Recovery re-registers the user's ORIGINAL key, so a different key is rejected to prevent an attacker swapping keys.","triggerScenarios":"POST /setup/recover/complete/{userId}/{token} with gpgkey.armored_key whose fingerprint differs from the user's stored Gpgkeys row; user regenerated/lost their key and tries to recover with the new one.","commonSituations":"User lost their private key and generated a new pair hoping to recover; importing the wrong key file (another account's key); key with multiple subkeys where the wrong primary fingerprint is derived; typo when pasting the armored key.","solutions":["Use the exact key pair originally registered for this account (fingerprint must match the stored gpgkeys.fingerprint)","If the key is truly lost, an administrator must delete the user's account key / re-invite the user so a new key can be registered","Compare fingerprints locally before calling: gpg --show-keys <file> and diff against the stored fingerprint","Ensure only the primary key's armored block is sent, not a subkey-only export"],"exampleFix":"// before: recovering with a freshly generated key\nconst armor = await generateAndExportNewKey();\nawait recoverComplete(userId, token, armor);\n// after: use the original registered key\nconst armor = await exportOriginalRegisteredKey();\nawait recoverComplete(userId, token, armor);","handlingStrategy":"validation","validationCode":"const fp = await getFingerprint(armoredKey);\nconst stored = await getStoredFingerprint(userId);\nif (fp !== stored) throw new Error('key does not match account');","typeGuard":null,"tryCatchPattern":"try { await recoverComplete(userId, token, armoredKey); }\ncatch (e) { if (isKeyMismatch(e)) { /* contact admin — original key required */ } else throw e; }","preventionTips":["Always use the originally registered key pair for recovery","Compare fingerprints (gpg --show-keys) before submitting","Never regenerate a key expecting recovery to accept it","Export the primary key, not a subkey-only block"],"tags":["recover","openpgp","fingerprint-mismatch"],"backgroundTag":"invalid-identifier","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}