{"record":{"id":"b4155810f916e33d","repo":"passbolt/passbolt_api","slug":"ssorecover-plugin-is-disabled","errorCode":null,"errorMessage":"SsoRecover plugin is disabled.","messagePattern":"SsoRecover plugin is disabled\\.","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltEe/Sso/src/Controller/AbstractSso2Stage2Controller.php","lineNumber":172,"sourceCode":"                    // To map 500(internal error/provider specific exceptions) to 4xx exception\n                    if (isset($event->getResult()['customException'])) {\n                        $e = $event->getResult()['customException'];\n                    }\n\n                    throw $e;\n                }\n\n                // Create SSO auth token for next step, e.g. get keys\n                $ssoAuthToken = $service->createAuthTokenToGetKey($uac, $service->getSettings()->id);\n                $successUrl = Router::url(\"/sso/login/success?token={$ssoAuthToken->token}\", true);\n\n                // Triggers a successful user login event\n                $event = new Event(self::EVENT_USER_LOGIN_SUCCESS, $this, ['ssoService' => $service]);\n                $this->getEventManager()->dispatch($event);\n                break;\n            case SsoState::TYPE_SSO_RECOVER:\n                if (!$this->isFeaturePluginEnabled('SsoRecover')) {\n                    throw new BadRequestException(__('SsoRecover plugin is disabled.'));\n                }\n\n                $ssoRecoverAssertService = new SsoRecoverAssertService();\n\n                try {\n                    $successUrl = $ssoRecoverAssertService->assertAndGetRedirectUrl(\n                        $service,\n                        $ssoState,\n                        $code,\n                        $this->User->ip(),\n                        $this->User->userAgent(),\n                        $this->getProviderName()\n                    );\n                } catch (Exception $e) {\n                    $event = new Event(self::EVENT_PROVIDER_ERROR_RESOURCE_OWNER, $this, ['exception' => $e]);\n                    $this->getEventManager()->dispatch($event);\n                    // To map 500(internal error/provider specific exceptions) to 4xx exception\n                    if (isset($event->getResult()['customException'])) {","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/Sso/src/Controller/AbstractSso2Stage2Controller.php#L154-L190","documentation":"During stage-2 SSO processing, if the SSO state type is TYPE_SSO_RECOVER (account recovery flow), the controller requires the separate SsoRecover plugin to be enabled. When isFeaturePluginEnabled('SsoRecover') is false, it throws BadRequestException 'SsoRecover plugin is disabled.' (HTTP 400).","triggerScenarios":"A user following an SSO recovery link while the SsoRecover plugin is not enabled on the server (missing from passbolt.plugins loaded / config, or EE license tier without it); recovery state created on an instance where the plugin was later disabled.","commonSituations":"Admin enabled SSO but forgot to enable SsoRecover; plugin disabled after a license downgrade; load balancer with mixed node configs where one node lacks the plugin; users clicking old recovery emails after the plugin was turned off.","solutions":["Enable the SsoRecover plugin in config/passbolt.php (plugins.SsoRecover.enabled = true, assuming EE license supports it) and clear cache.","Re-run the SSO setup/health check to confirm the plugin loads: `ddev refresh` or passbolt healthcheck.","If SsoRecover is not licensed/needed, disable SSO-based recovery flows and use the standard username-based recovery process.","Ensure all nodes in a cluster have identical plugin configuration."],"exampleFix":"// before (config/passbolt.php)\n'plugins' => ['Sso' => ['enabled' => true]]\n// after\n'plugins' => ['Sso' => ['enabled' => true], 'SsoRecover' => ['enabled' => true]]","handlingStrategy":"validation","validationCode":"// Admin precheck\nbin/cake passbolt healthcheck | grep -i sso\n// or config check\n// config/passbolt.php must contain: 'SsoRecover' => ['enabled' => true]","typeGuard":null,"tryCatchPattern":"try {\n  await ssoRecoverCallback(url);\n} catch (e) {\n  if (e.response && e.response.status === 400 && /SsoRecover plugin is disabled/.test(e.response.data?.detail ?? '')) {\n    fallbackToStandardRecovery();\n  }\n}","preventionTips":["Enable SsoRecover in config/passbolt.php whenever SSO is enabled and recovery via SSO is offered.","Run the passbolt healthcheck after enabling SSO to catch missing plugin config.","Keep plugin configuration identical across all cluster nodes.","Send users the standard recovery flow if SsoRecover is not licensed."],"tags":["sso","plugin-disabled","recover"],"backgroundTag":"feature-not-enabled","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"}