passbolt/passbolt_api · warning · BadRequestException
The server verify token is missing or invalid.
Error message
The server verify token is missing or invalid.
What it means
Thrown by GpgAuthenticatorTrait::assertGpgMessageIsValid(), a generic guard that raises BadRequestException (HTTP 400) with the caller-supplied message when the GPG message is absent, not a string, or fails OpenPGPBackend::isValidMessage(). For this specific message the caller is GpgAuthenticator around line 200, where the decrypted server verify token from the client must be present and cryptographically valid during GPGAuth stage2 (token verification).
Solutions
- Check the stage2 request payload: the token field must be a non-empty string containing a valid armored GPG message.
- Re-run the GPGAuth flow from stage0 with a compliant client (passbolt CLI/extension) instead of hand-crafted requests.
- Verify the client encrypted the token to the correct server key (same fingerprint as passbolt.gpg.serverKey.fingerprint) and that the message was not modified in transit.
- If validating input server-side in custom code, call assertGpgMessageIsValid() early so the failure surfaces as a 400 with a clear message.
Example fix
// before: sending a raw JSON token
{"token": {"data": "abc"}}
// after: send the armored GPG message string
{"token": "-----BEGIN PGP MESSAGE-----\n...\n-----END PGP MESSAGE-----"} Defensive patterns
Strategy: type-guard
Validate before calling
$token = $request->getData('token') ?? $request->getData('gpg_auth.token');
if (!is_string($token) || $token === '' || !str_contains($token, 'BEGIN PGP MESSAGE')) {
// reject before calling assertGpgMessageIsValid
} Type guard
function isArmoredMessage(mixed $msg): bool {
return is_string($msg)
&& str_contains($msg, '-----BEGIN PGP MESSAGE-----');
} Try / catch
try {
$this->assertGpgMessageIsValid($gpg, $token, __('The server verify token is missing or invalid.'));
} catch (BadRequestException $e) {
return $this->error(400, $e->getMessage());
} Prevention
- Use a maintained passbolt client (CLI/extension) rather than hand-crafted stage2 requests.
- Always send the token as a single armored string field; never pre-parse it into JSON objects.
- Ensure TLS/proxies do not truncate large POST bodies containing armored messages.
- Log the failing request payload shape (not content) to spot malformed integrations early.
When it happens
Trigger: GPGAuth stage2 request where the client posts a token/verify payload that is missing (null), is not a string (e.g. JSON-decoded object), or is an armored message the backend cannot validate (tampered, truncated, encrypted to the wrong key, or not signed correctly).
Common situations: Client sending an empty or malformed token field in the stage2 request body; man-in-the-middle or replay attempts with altered tokens; client and server key versions mismatched so decryption produces garbage; custom scripts/integrations posting raw JSON instead of the armored message; buggy proxy stripping the payload field.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- A Duo state cookie is required.
- A Duo state cookie is required.
- A value for the theme should be provided.
- Account recovery case must be a string.
- Account recovery is disabled.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/f877345e46f1f340.
Report an issue: GitHub.
Appendix: source
Thrown at src/Authenticator/GpgAuthenticatorTrait.php:38
use Cake\Http\Exception\BadRequestException;
trait GpgAuthenticatorTrait
{
/**
* @param \App\Utility\OpenPGP\OpenPGPBackendInterface|null $gpg GPG instance
* @param mixed $gpgMessage GPG message
* @param string $errorMessage Error message to throw if GPG message is not valid
* @throws \Cake\Http\Exception\BadRequestException If GPG message is not valid
* @return void
*/
public function assertGpgMessageIsValid(?OpenPGPBackendInterface $gpg, mixed $gpgMessage, string $errorMessage): void // phpcs:ignore
{
if (
!isset($gpgMessage) ||
!is_string($gpgMessage) ||
!$gpg->isValidMessage($gpgMessage)
) {
throw new BadRequestException($errorMessage);
}
}
}
View on GitHub (pinned to 31c1bbc10f)