{"record":{"id":"64f3b1dbff31cbf3","repo":"passbolt/passbolt_api","slug":"the-authentication-failed-the-credentials-are-invalid","errorCode":null,"errorMessage":"The authentication failed. The credentials are invalid.","messagePattern":"The authentication failed\\. The credentials are invalid\\.","errorType":"exception","errorClass":"Cake\\Http\\Exception\\BadRequestException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltCe/JwtAuthentication/src/Controller/JwtLoginController.php","lineNumber":80,"sourceCode":"            $uac = new UserAccessControl($user['role']['name'], $user['id']);\n            UserAction::getInstance()->setUserAccessControl($uac);\n\n            $event = new Event(UpdateUserLastLoggedInListener::EVENT_USER_LOGIN_SUCCESS, $this, ['user' => $user]);\n            $this->getEventManager()->dispatch($event);\n\n            $this->success(__('The authentication was a success.'), compact('challenge'));\n        } else {\n            $message = __('The authentication failed.') . ' ';\n            switch ($result->getStatus()) {\n                case Result::FAILURE_CREDENTIALS_MISSING:\n                    $message .= __('The credentials are missing.');\n                    throw new BadRequestException($message);\n                case Result::FAILURE_IDENTITY_NOT_FOUND:\n                    $message = __('The user does not exist or is not active or has been deleted.');\n                    throw new NotFoundException($message);\n                case Result::FAILURE_CREDENTIALS_INVALID:\n                    $message = __('The credentials are invalid.');\n                    throw new BadRequestException($message);\n                default:\n                case Result::FAILURE_OTHER:\n                    $message = __('An internal error occurred.');\n                    throw new InternalErrorException($message);\n            }\n        }\n    }\n}\n","sourceCodeStart":62,"sourceCodeEnd":89,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/JwtAuthentication/src/Controller/JwtLoginController.php#L62-L89","documentation":"Thrown by JwtLoginController::loginPost when the authentication result status is FAILURE_CREDENTIALS_INVALID, raised as a 400 BadRequestException. Credentials were present but failed verification (bad signature, bad token, wrong key).","triggerScenarios":"POST /auth/jwt/login with a GPG challenge token whose signature cannot be verified against the user's public key, or an otherwise invalid credential payload.","commonSituations":"Client signed with a key that doesn't match the registered public key; corrupted or tampered token; clock skew affecting token validity; wrong user keyring on the client.","solutions":["Confirm the client's private key matches the public key registered for the user on the server","Re-run the full GPGAuth handshake (fresh challenge) instead of reusing stale tokens","Synchronize clocks between client and server","Check for body mangling by proxies/middleware (encoding, line endings in armored keys)"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// ensure signature is made with the key whose fingerprint is registered for the user\nconst fingerprint = await keyring.getFingerprint(username);\nif (fingerprint !== registeredFingerprint) failFast('key mismatch');","typeGuard":null,"tryCatchPattern":"try { await login(sign(token)); } catch (e) { if (String(e.message).includes('credentials are invalid')) { refreshChallengeAndRetryOnce(); } }","preventionTips":["Register the exact public key the client signs with","Always use a fresh server challenge; never replay tokens","Keep clocks synchronized (NTP)"],"tags":["authentication","invalid-credentials","gpg","signature"],"backgroundTag":"invalid-credentials","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"}