passbolt/passbolt_api · error · ForbiddenException

Only administrators can update the subscription details.

Error message

Only administrators can update the subscription details.

What it means

SubscriptionKeySaveService::save() requires an administrator UserAccessControl; non-admin callers get ForbiddenException 'Only administrators can update the subscription details.' Updating/importing a subscription key is an admin-only operation in Passbolt EE.

Solutions

  1. Use an administrator account/token to import the subscription key
  2. Grant the admin role to the service user in Passbolt administration
  3. Restrict license automation to admin credentials only

Example fix

// before
await fetch('/subscription/key.json', {method: 'POST', headers: userAuth, body: key});
// after
if (!isAdmin(user)) throw new Error('Admin role required to set subscription key');
await fetch('/subscription/key.json', {method: 'POST', headers: adminAuth, body: key});
Defensive patterns

Strategy: try-catch

Validate before calling

if (!$uac->isAdmin()) { throw new Error('Admin role required to update subscription'); }

Type guard

function canManageSubscription(uac) { return uac?.isAdmin?.() === true; }

Try / catch

try { await updateSubscriptionKey(key); } catch (e) { if (e.status === 403) { /* admin required */ } else throw e; }

Prevention

When it happens

Trigger: POST/PUT to the subscription update endpoint (or calling save() directly) while logged in as a non-admin user.

Common situations: CI or provisioning scripts using a non-admin API account to install the license; testing the endpoint with a regular user session; role demotion after credentials were generated.

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

Appendix: source

Thrown at plugins/PassboltEe/Subscription/src/Service/Subscriptions/SubscriptionKeySaveService.php:58

     * @param \Passbolt\Subscription\Model\Table\SubscriptionsTable|null $Subscriptions subscriptions table
     */
    public function __construct(?SubscriptionsTable $Subscriptions = null)
    {
        $this->SubscriptionsTable = $Subscriptions
            ?? TableRegistry::getTableLocator()->get('Passbolt/Subscription.Subscriptions');
        $this->SubscriptionKeyValidateService = new SubscriptionKeyValidateService();
    }

    /**
     * @param string|null $keyString key
     * @param \App\Utility\UserAccessControl $uac user access control object
     * @return \Passbolt\Subscription\Model\Dto\SubscriptionKeyDto
     * @throws \Passbolt\Subscription\Error\Exception\Subscriptions\SubscriptionException if key format or signature or content is invalid
     */
    public function save(?string $keyString, UserAccessControl $uac): SubscriptionKeyDto
    {
        if (!$uac->isAdmin()) {
            throw new ForbiddenException(__('Only administrators can update the subscription details.'));
        }
        $keyDto = $this->SubscriptionKeyValidateService->validate($keyString);
        $this->SubscriptionsTable->createOrUpdate($keyDto->data, $uac);

        return $keyDto;
    }
}

View on GitHub (pinned to 31c1bbc10f)