{"record":{"id":"4bd531eebd1c36d7","repo":"passbolt/passbolt_api","slug":"the-sso-state-type-is-invalid","errorCode":null,"errorMessage":"The SSO state type is invalid.","messagePattern":"The SSO state type is invalid\\.","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"warning","filePath":"plugins/PassboltEe/Sso/src/Controller/AbstractSso2Stage2Controller.php","lineNumber":199,"sourceCode":"                        $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'])) {\n                        $e = $event->getResult()['customException'];\n                    }\n\n                    throw $e;\n                }\n\n                break;\n            default:\n                throw new BadRequestException(__('The SSO state type is invalid.'));\n        }\n\n        $this->response = $this->getResponse()->withCookie($service->clearStateCookie());\n        $this->redirect($successUrl);\n    }\n\n    /**\n     * @param \\App\\Service\\Cookie\\AbstractSecureCookieService $cookieService Cookie service\n     * @param \\Passbolt\\Sso\\Model\\Entity\\SsoState $ssoState SSO state.\n     * @param string $code jwt\n     * @return void\n     */\n    protected function stage2AsAdmin(AbstractSecureCookieService $cookieService, SsoState $ssoState, string $code): void\n    {\n        try {\n            // Get the draft settings\n            $settingsDto = (new SsoSettingsGetService())->getDraftByIdOrFail($ssoState->sso_settings_id, true);\n        } catch (Exception $exception) {","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/Sso/src/Controller/AbstractSso2Stage2Controller.php#L181-L217","documentation":"Thrown in the default arm of the switch in stage2 of the SSO controller when the SSO state's type is not one of the recognized values (e.g. the expected mfa/recover/register/login state types). The state cookie is exchanged for an SsoState entity, and its 'type' field must match a branch the controller knows how to handle. This is a server-side guard against corrupted or forged state cookies.","triggerScenarios":"A user hits the SSO stage2 callback URL with a state cookie whose decrypted SsoState entity carries a 'type' value outside the set the switch statement handles (e.g. an old or invalid serialized state).","commonSituations":"Stale SSO cookies left over from a previous passbolt version whose state type no longer exists; a truncated/corrupted cookie; a user replaying an old callback URL with a cookie from a different flow; plugin upgrades between CE/EE SSO v1 and v2 that changed state types.","solutions":["Clear the passbolt SSO state cookie in the browser and restart the SSO flow from the beginning (login/recover/register).","Inspect the SsoState entity produced from the cookie (plugins/PassboltEe/Sso) and confirm the 'type' value matches one of the SsoState::TYPE_* constants handled in stage2.","Verify the browser is using the correct server version — mismatched plugin versions can produce unknown state types; run 'ddev refresh' to sync migrations and cache.","Check for a proxy/CDN serving an old cached callback page with an outdated state."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const stateTypes = ['mfa','recover','register','login'];\nif (!stateTypes.includes(ssoState.type)) { throw new Error('Unsupported SSO state type: ' + ssoState.type); }","typeGuard":"function isKnownSsoStateType(t) { return typeof t === 'string' && ['mfa','recover','register','login'].includes(t); }","tryCatchPattern":"try { await completeStage2(state); } catch (e) { if (e.status === 400 && /state type is invalid/.test(e.message)) { clearSsoCookies(); restartSsoFlow(); } else { throw e; } }","preventionTips":["Always restart the full SSO flow rather than reusing old callback URLs","Clear passbolt SSO cookies when upgrading server versions","Avoid multiple concurrent SSO flows in the same browser"],"tags":["sso","bad-request","state-cookie","csrf"],"backgroundTag":"invalid-enum-value","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"}