passbolt/passbolt_api · error · ForbiddenException

This operation is not allowed for this user.

Error message

This operation is not allowed for this user.

What it means

Thrown by TransfersUpdateService::assertOperationIsAllowed when the authenticated user (UserAccessControl) is not the owner of the transfer being updated (transfer.user_id !== uac.getId()). Only the user who initiated a mobile transfer may update it.

Solutions

  1. Log in as the user who created the transfer before updating it
  2. Abort and create a fresh transfer for the current user
  3. Verify the transfer id belongs to the authenticated account
Defensive patterns

Strategy: validation

Validate before calling

const me = await api.getLoggedInUser();
if (transfer.userId !== me.id) {
  throw new Error('Transfer belongs to another user; create a new transfer');
}

Try / catch

try {
  await api.updateTransfer(transferId, payload);
} catch (e) {
  if (e.code === 403 && e.message.includes('not allowed for this user')) {
    // re-authenticate as transfer owner or recreate the transfer
  }
}

Prevention

When it happens

Trigger: PUT/PATCH to /transfers/{id}.json while logged in as a user different from the transfer's creator — e.g. reusing a transfer id from another account, or a token/account switch on the mobile device mid-transfer.

Common situations: Switching passbolt accounts on a mobile device without restarting the transfer flow; copy-pasting a transfer UUID from another user's logs; server-side admin testing with a different session than the one that created the transfer.

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/1943b8b326bf9bcd. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltCe/Mobile/src/Service/Transfers/TransfersUpdateService.php:161

            $msg .= __('The current page does not match the total number of pages.');
            throw new ForbiddenException($msg);
        }
    }

    /**
     * Check if operation is allowed
     *
     * @param \Passbolt\Mobile\Model\Entity\Transfer $transfer entity
     * @param \App\Utility\UserAccessControl $uac user access control object
     * @throws \Cake\Http\Exception\ForbiddenException if operation is not allowed for example:
     * - Transfer or AuthToken is for another user
     * - Authentication token is expired
     * @return void
     */
    private function assertOperationIsAllowed(Transfer $transfer, UserAccessControl $uac): void
    {
        if ($transfer->user_id !== $uac->getId()) {
            throw new ForbiddenException(__('This operation is not allowed for this user.'));
        }
        if (!isset($transfer->authentication_token)) {
            throw new ForbiddenException(__('The authentication token is missing.'));
        }
        if ($transfer->authentication_token->user_id !== $uac->getId()) {
            throw new ForbiddenException(__('The authentication token is not valid for this user.'));
        }
        if ($transfer->authentication_token->type !== AuthenticationToken::TYPE_MOBILE_TRANSFER) {
            throw new ForbiddenException(__('The authentication token type is invalid.'));
        }
        if ($transfer->authentication_token->active !== true) {
            throw new ForbiddenException(__('The authentication token is not active.'));
        }
        if ($transfer->authentication_token->isExpired()) {
            throw new ForbiddenException(__('The authentication token is expired.'));
        }
    }

View on GitHub (pinned to 31c1bbc10f)