passbolt/passbolt_api · error · BadRequestException

This is not a valid Ajax/Json request.

Error message

This is not a valid Ajax/Json request.

What it means

Thrown by RecoverStartController::start when the request is NOT a JSON/Ajax request. Unlike the success endpoints, the recover-start endpoint is part of the programmatic API and requires the JSON request marker (Accept: application/json with X-Requested-With per CakePHP/Passbolt conventions).

Solutions

  1. Send headers Accept: application/json and X-Requested-With: XMLHttpRequest with the request
  2. Use the passbolt JS SDK or an HTTP client configured for JSON when calling this endpoint
  3. Ensure Content-Type: application/json when posting the form data
  4. Do not open the endpoint directly in a browser address bar for POST flows

Example fix

// before
curl -X POST https://host/sso/recover/start -d 'username=...'
// after
curl -X POST https://host/sso/recover/start \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -H 'X-Requested-With: XMLHttpRequest' \
  -d '{"username":"..."}'
Defensive patterns

Strategy: validation

Validate before calling

const jsonHeaders = {
  'Accept': 'application/json',
  'Content-Type': 'application/json',
  'X-Requested-With': 'XMLHttpRequest'
};
await fetch('/sso/recover/start', {method: 'POST', headers: jsonHeaders, body});

Prevention

When it happens

Trigger: Calling POST /sso/recover/start from a plain HTML form, curl without JSON headers, or a browser address-bar navigation; missing Accept: application/json header.

Common situations: API consumers forget the JSON headers passbolt requires on all /json endpoints; testing in a browser; proxy strips Accept headers.

Related errors


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

Appendix: source

Thrown at plugins/PassboltEe/SsoRecover/src/Controller/RecoverStartController.php:53

    /**
     * @inheritDoc
     */
    public function beforeFilter(EventInterface $event)
    {
        parent::beforeFilter($event);

        $this->Authentication->allowUnauthenticated(['start']);
    }

    /**
     * Exchange authentication token for recover URL.
     *
     * @return void
     */
    public function start(): void
    {
        if (!$this->request->is('json')) {
            throw new BadRequestException(__('This is not a valid Ajax/Json request.'));
        }

        $this->User->assertNotLoggedIn();

        // Make sure SSO settings are set.
        try {
            $settingsDto = (new SsoSettingsGetService())->getActiveOrFail();
        } catch (RecordNotFoundException $e) {
            throw new BadRequestException(__('No valid SSO settings found.'), null, $e);
        }

        $form = new SsoRecoverStartForm();
        if (!$form->execute($this->getRequest()->getData())) {
            throw new FormValidationException(__('Could not validate the SSO recover request.'), $form);
        }

        // Assert & consume sso auth token
        $ssoAuthService = new SsoAuthenticationTokenGetService();

View on GitHub (pinned to 31c1bbc10f)