passbolt/passbolt_api · error · Cake\Http\Exception\BadRequestException
The authentication failed. The credentials are invalid.
Error message
The authentication failed. The credentials are invalid.
What it means
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).
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)
Defensive patterns
Strategy: retry
Validate before calling
// ensure signature is made with the key whose fingerprint is registered for the user
const fingerprint = await keyring.getFingerprint(username);
if (fingerprint !== registeredFingerprint) failFast('key mismatch'); Try / catch
try { await login(sign(token)); } catch (e) { if (String(e.message).includes('credentials are invalid')) { refreshChallengeAndRetryOnce(); } } Prevention
- Register the exact public key the client signs with
- Always use a fresh server challenge; never replay tokens
- Keep clocks synchronized (NTP)
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Could not import the user OpenPGP key.
- The authentication failed. The credentials are missing.
- The domain is invalid. Expected
- The user signature could not be verified.
- You need to login to access this location.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/64f3b1dbff31cbf3.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltCe/JwtAuthentication/src/Controller/JwtLoginController.php:80
$uac = new UserAccessControl($user['role']['name'], $user['id']);
UserAction::getInstance()->setUserAccessControl($uac);
$event = new Event(UpdateUserLastLoggedInListener::EVENT_USER_LOGIN_SUCCESS, $this, ['user' => $user]);
$this->getEventManager()->dispatch($event);
$this->success(__('The authentication was a success.'), compact('challenge'));
} else {
$message = __('The authentication failed.') . ' ';
switch ($result->getStatus()) {
case Result::FAILURE_CREDENTIALS_MISSING:
$message .= __('The credentials are missing.');
throw new BadRequestException($message);
case Result::FAILURE_IDENTITY_NOT_FOUND:
$message = __('The user does not exist or is not active or has been deleted.');
throw new NotFoundException($message);
case Result::FAILURE_CREDENTIALS_INVALID:
$message = __('The credentials are invalid.');
throw new BadRequestException($message);
default:
case Result::FAILURE_OTHER:
$message = __('An internal error occurred.');
throw new InternalErrorException($message);
}
}
}
}
View on GitHub (pinned to 31c1bbc10f)