passbolt/passbolt_api · error · Cake\Http\Exception\BadRequestException

The authentication failed. The credentials are missing.

Error message

The authentication failed. The credentials are missing.

What it means

Thrown by JwtLoginController::loginPost when the authentication result status is FAILURE_CREDENTIALS_MISSING, meaning the authenticator found no credentials to verify at all (HTTP 400). The full message is 'The authentication failed. The credentials are missing.'

Solutions

  1. Include a valid GPGAuth challenge token in the request (headers/body as the client protocol requires)
  2. Complete the GPGAuth handshake stages in order (verify server, then login)
  3. Inspect the request body actually received server-side for missing fields
  4. Compare against a working passbolt CLI request to spot the missing credential field
Defensive patterns

Strategy: validation

Validate before calling

if (!challengeToken || !Object.keys(gpgAuthHeaders).length) throw new Error('refusing to call login: no GPGAuth credentials assembled');

Try / catch

try { await login(token); } catch (e) { if (String(e.message).includes('credentials are missing')) { restartGpgAuthHandshake(); } }

Prevention

When it happens

Trigger: POST /auth/jwt/login where the request body/headers contain no recognizable GPG challenge token, so the GpgJwtAuthenticator has nothing to authenticate.

Common situations: Client sent an empty or malformed JSON body; missing X-GPGAuth-* headers on stage 1 of the login; sending the token in the wrong field; skipping the server-verification step and posting directly.

Understand the failure class

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/7d3ce321a8af6e63. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltCe/JwtAuthentication/src/Controller/JwtLoginController.php:74

        }

        $result = $this->Authentication->getResult();
        if ($result->isValid()) {
            $challenge = $result->getData()['challenge'];
            $user = $result->getData()['user'];
            $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)