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

  1. Confirm the client's private key matches the public key registered for the user on the server
  2. Re-run the full GPGAuth handshake (fresh challenge) instead of reusing stale tokens
  3. Synchronize clocks between client and server
  4. 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

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

Related errors


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)