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

You are not authorized to access that location.

Error message

You are not authorized to access that location.

What it means

ForbiddenException (HTTP 403) from assertCanEdit in UsersEditController: a non-admin authenticated user attempted to edit a user other than themselves. The controller enforces that admins can edit all users while regular users may only edit their own record.

Solutions

  1. Use credentials of a user whose id matches the target record, or authenticate as an admin.
  2. Ensure the `id` in the request body equals the authenticated user's id for self-service edits.
  3. Check which account the API client is configured for (wrong passphrase/keys or shared config can silently use the wrong user).
Defensive patterns

Strategy: validation

Validate before calling

function assertSelfEdit(session, targetId) { if (session.role !== 'admin' && session.userId !== targetId) { throw new Error('Refusing edit: non-admin cannot edit another user'); } }

Try / catch

try { await api.editUser(id, data); } catch (e) { if (e.code === 403) { switchToAdminSession(); } else { throw e; } }

Prevention

When it happens

Trigger: PUT /users/{id}.json where the authenticated user's role is not admin and the payload's `id` differs from the logged-in user's id.

Common situations: A client library configured with one user's credentials used to update another user's profile; automated scripts iterating over user ids with a non-admin account; id mismatch after copying payloads between requests.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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

Appendix: source

Thrown at src/Controller/Users/UsersEditController.php:151

        $this->sendAfterUpdateEvent($userEntityWithDirtyState);

        $this->success(__('The user has been updated successfully.'), $user);
    }

    /**
     * Validate if the user is authorized to edit the data
     *
     * @param array $data user data
     * @return void
     * @throws \Cake\Http\Exception\ForbiddenException if the user is not admin or not editing themselves
     * @throws \Cake\Http\Exception\ForbiddenException if the user is not admin and editing role
     */
    protected function assertCanEdit(array $data): void
    {
        // Admin can edit all users, other users can only edit themselves
        if ($this->User->role() !== Role::ADMIN && $data['id'] !== $this->User->id()) {
            throw new ForbiddenException(__('You are not authorized to access that location.'));
        }
        if ($this->User->role() !== Role::ADMIN && (isset($data['role']) || isset($data['role_id']))) {
            throw new ForbiddenException(__('You are not authorized to edit the role.'));
        }
    }

    /**
     * Validate the data coming from the request
     *
     * @param array $data user data
     * @return void
     * @throws \Cake\Http\Exception\BadRequestException if gpgkey is sent (v2 only)
     * @throws \Cake\Http\Exception\BadRequestException if groups data is sent (v2 only)
     * @throws \Cake\Http\Exception\BadRequestException if data is not provided or invalid
     */
    protected function assertRequestData(array $data): void
    {
        if (empty($data) || count($data) < 2) {

View on GitHub (pinned to 31c1bbc10f)