{"record":{"id":"6ee0b2225d1040b6","repo":"passbolt/passbolt_api","slug":"only-administrators-can-view-the-subscription-details","errorCode":null,"errorMessage":"Only administrators can view the subscription details.","messagePattern":"Only administrators can view the subscription details\\.","errorType":"http","errorClass":"ForbiddenException","httpStatus":403,"severity":"error","filePath":"plugins/PassboltEe/Subscription/src/Service/Subscriptions/SubscriptionKeyGetService.php","lineNumber":63,"sourceCode":"    protected SubscriptionsTable $Subscriptions;\n\n    /**\n     * SubscriptionKeyGetService constructor.\n     */\n    public function __construct()\n    {\n        $this->Subscriptions = $this->fetchTable('Passbolt/Subscription.Subscriptions');\n        $this->SubscriptionValidateService = new SubscriptionKeyValidateService();\n    }\n\n    /**\n     * @param \\App\\Utility\\UserAccessControl $uac user access control object\n     * @return \\Passbolt\\Subscription\\Model\\Dto\\SubscriptionKeyDto\n     */\n    public function get(UserAccessControl $uac): SubscriptionKeyDto\n    {\n        if (!$uac->isAdmin()) {\n            throw new ForbiddenException(__('Only administrators can view the subscription details.'));\n        }\n        $keyString = $this->readFromDB();\n        if (!isset($keyString)) {\n            $keyString = $this->readFromFile();\n        }\n        if (!isset($keyString) || empty($keyString)) {\n            throw new SubscriptionRecordNotFoundException();\n        }\n\n        return $this->SubscriptionValidateService->validate($keyString);\n    }\n\n    /**\n     * Try to read the key string from database (OrganizationSettings table)\n     * Try new file name first then legacy name, log warnings if issues.\n     *\n     * @return string|null\n     * @throws \\Passbolt\\Subscription\\Error\\Exception\\Subscriptions\\SubscriptionException if subscription key is invalid","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/Subscription/src/Service/Subscriptions/SubscriptionKeyGetService.php#L45-L81","documentation":"The Passbolt subscription plugin restricts viewing subscription key details to administrators. SubscriptionKeyGetService::get() checks UserAccessControl::isAdmin() before reading the key and throws ForbiddenException when the caller is not an admin. This protects sensitive license data from regular users.","triggerScenarios":"Calling the subscription GET endpoint (SubscriptionKeyGetService::get, invoked by view/check actions) while authenticated as a non-admin user.","commonSituations":"Developers testing the subscription API with a regular user account; automated scripts configured with a non-admin API user; role changes that demoted the account after integration.","solutions":["Authenticate with (or elevate to) an administrator account","Re-issue API credentials for a user with the admin role","Skip this endpoint in non-admin tooling and surface a clear permissions message instead"],"exampleFix":"// before\nconst res = await fetch('/subscription/key.json', {headers: auth});\n// after\nif (!user.isAdmin) throw new Error('Admin role required to read subscription');\nconst res = await fetch('/subscription/key.json', {headers: adminAuth});","handlingStrategy":"try-catch","validationCode":"// client: verify role before calling\nif (!user.role || user.role.name !== 'admin') throw new Error('Admin role required');","typeGuard":"function isAdmin(u) { return !!u && u.role?.name === 'admin'; }","tryCatchPattern":"try { const dto = await getSubscriptionKey(uac); } catch (e) { if (e.status === 403) { /* show admin-required message */ } else throw e; }","preventionTips":["Use admin credentials for subscription endpoints","Check the authenticated user's role before integration","Handle 403 explicitly in subscription tooling"],"tags":["authorization","passbolt","subscription"],"backgroundTag":"permission-denied","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}