passbolt/passbolt_api · error · ForbiddenException

You are not authorized to access that location.

Error message

You are not authorized to access that location.

What it means

ForbiddenException thrown by DirectoryIgnoreController::toggle when the authenticated user's role is not Role::ADMIN. The ignore/un-ignore endpoint that controls which directory records are skipped during sync is admin-only; any non-admin (or unauthenticated) request is rejected with the standard CakePHP 'not authorized' message before the foreign model is even validated.

Solutions

  1. Authenticate as a user with the admin role, or grant the admin role to the account performing the operation.
  2. Check the auth token/cookie used by the client corresponds to the intended admin (inspect User->role() via /me.json).
  3. If this must be automated, run the equivalent server-side command (e.g. `passbolt directory_sync ignore-delete`) as a root/admin server operator instead of the HTTP endpoint.
  4. Ensure the session didn't expire and the role lookup isn't failing silently (re-login to refresh the identity).
Defensive patterns

Strategy: validation

Validate before calling

$me = $apiClient->get('/me.json');
if (($me['role']['name'] ?? null) !== 'admin') {
    throw new RuntimeException('Directory ignore toggle requires an admin account');
}

Type guard

function isAdmin(array $me): bool { return ($me['role']['name'] ?? '') === 'admin'; }

Try / catch

try {
    $apiClient->put('/directoryignore/' . $model . '/' . $id . '.json');
} catch (HttpException $e) {
    if ($e->getCode() === 403) {
        // switch to an admin-authenticated client or run server-side command
    }
}

Prevention

When it happens

Trigger: Calling PUT/POST to the directory ignore toggle route (e.g. /directoryignore/<model>/<id>.json) while logged in as a non-admin user, or with missing/invalid authentication (User->role() not resolving to admin), or with a CSRF/auth token mismatch causing the identity to fall back to a lower role.

Common situations: UI automation or scripts run under a regular user account; stale session after the admin role was revoked; API token registered to a non-admin user; testing the endpoint unauthenticated.

Understand the failure class

Background: "You do not have permission" / 403 Forbidden errors: authenticated but not allowed — causes and fixes across open-source libraries — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at plugins/PassboltEe/DirectorySync/src/Controller/DirectoryIgnoreController.php:63

        $this->directoryOrgSettings = DirectoryOrgSettings::get();

        $this->DirectoryIgnore = $this->fetchTable('Passbolt/DirectorySync.DirectoryIgnore');
    }

    /**
     * Check if a record is ignored
     *
     * @param string $foreignModel foreign model
     * @param string $foreignKey foreign key
     * @throws \App\Error\Exception\ValidationException If the model name or id is not valid
     * @throws \Cake\Http\Exception\ForbiddenException if the current user is not an admin
     * @return void
     */
    public function toggle(string $foreignModel, string $foreignKey): void
    {
        if ($this->User->role() !== Role::ADMIN) {
            throw new ForbiddenException(__('You are not authorized to access that location.'));
        }
        $this->assertDirectoryEnabled();
        $foreignModel = $this->normalizeForeignModel($foreignModel);
        if (!Validation::inList($foreignModel, ['Groups', 'Users', 'DirectoryEntries'])) {
            throw new BadRequestException(__('The record model is not valid.'));
        }

        $ignored = null;
        try {
            $ignored = $this->DirectoryIgnore->get($foreignKey);
            $this->DirectoryIgnore->delete($ignored);
        } catch (RecordNotFoundException $exception) {
        }
        $this->success(__('The record is currently ignored as part of directory synchronization.'), $ignored);
    }

    /**
     * Check if a record is ignored

View on GitHub (pinned to 31c1bbc10f)