passbolt/passbolt_api · error · ForbiddenException

Only administrators can delete the subscription.

Error message

Only administrators can delete the subscription.

What it means

SubscriptionKeyDeleteService::delete() throws ForbiddenException when the provided UserAccessControl does not belong to an administrator, refusing to delete the subscription key. Only admins may remove the subscription record from the server.

Solutions

  1. Authenticate as or impersonate an admin user when calling DELETE /subscription or the service.
  2. Check the user's role: `SELECT role_id FROM users WHERE id = '<id>';` must be the admin role id.
  3. Update the service account / automation user to hold the admin role if deletion via automation is intended.

Example fix

// before: delete with a plain user UAC
$uac = new UserAccessControl(ROLE_USER, $userId);
$this->SubscriptionKeyDeleteService->delete($uac);
// after
$uac = new UserAccessControl(ROLE_ADMIN, $adminUserId);
$this->SubscriptionKeyDeleteService->delete($uac);
Defensive patterns

Strategy: validation

Validate before calling

if (!$uac->isAdmin()) {
    throw new \Cake\Http\Exception\ForbiddenException('Subscription deletion requires admin');
}
$service->delete($uac);

Try / catch

try {
    $service->delete($uac);
} catch (\Cake\Http\Exception\ForbiddenException $e) {
    // surface 403: only administrators can delete the subscription
}

Prevention

When it happens

Trigger: Calling delete() (backing the DELETE /subscription endpoint) with a UAC of a non-admin user role — !uac->isAdmin() — regardless of the subscription's existence.

Common situations: A non-admin user (or API client with user role credentials) attempting to remove the license; automation running with service-account credentials that lack the admin role; misconfigured role assignment for the executing user.

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/7022af204bf7f3db. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltEe/Subscription/src/Service/Subscriptions/SubscriptionKeyDeleteService.php:43

 * Removes the persisted subscription key from `organization_settings`.
 *
 * Intended to be called from EditionDowngradeService as the first step of
 * the in-product downgrade flow. Idempotent: succeeds without error when
 * no subscription row exists.
 */
class SubscriptionKeyDeleteService
{
    use LocatorAwareTrait;

    /**
     * @param \App\Utility\UserAccessControl $uac User access control.
     * @return void
     * @throws \Cake\Http\Exception\ForbiddenException When the UAC is not admin.
     */
    public function delete(UserAccessControl $uac): void
    {
        if (!$uac->isAdmin()) {
            throw new ForbiddenException(__('Only administrators can delete the subscription.'));
        }

        /** @var \Passbolt\Subscription\Model\Table\SubscriptionsTable $Subscriptions */
        $Subscriptions = $this->fetchTable('Passbolt/Subscription.Subscriptions');
        $row = $Subscriptions->find()->first();
        if ($row instanceof EntityInterface) {
            $Subscriptions->deleteOrFail($row);
        }
    }
}

View on GitHub (pinned to 31c1bbc10f)