passbolt/passbolt_api · error · BadRequestException
The SSO state is invalid. User id mismatch.
Error message
The SSO state is invalid. User id mismatch.
What it means
Thrown by SsoStatesAssertService::assert when the user_id stored in the SSO state does not match the authenticated user performing the assertion (ExtendedUserAccessControl), or the stored user_id is not a valid UUID. This prevents a state generated for one user from being consumed by another.
Solutions
- Retry the SSO login while logged in as the intended user only.
- Clear SSO state cookies/storage and start a fresh flow.
- Ensure your client doesn't reuse a state value across sessions or users.
Defensive patterns
Strategy: validation
Validate before calling
if ($stateRecord->user_id !== $currentUserId) { /* discard state and restart login */ } Try / catch
try { $svc->assertAndConsume($state, $settingsId, $uac); } catch (BadRequestException $e) { if (str_contains($e->getMessage(), 'User id mismatch')) { /* restart flow as the same user */ } throw $e; } Prevention
- Don't switch user sessions between starting and completing SSO login.
- Avoid shared browsers mixing accounts during SSO flows.
- Generate one state per user session and never share it.
When it happens
Trigger: Completing the SSO callback while logged in as a different user than the one who initiated the SSO flow; multiple browser profiles/accounts sharing and mixing state cookies; a corrupted/tampered state record with a malformed user_id.
Common situations: Shared computers where two users start SSO login in the same browser; session switch mid-flow; automated tests reusing state fixtures across users.
Related errors
- The SSO state is invalid. User IP mismatch.
- CSRF issue. The state in request data does not match with…
- CSRF issue. The state in URL and Cookies do not match.
- Service provider invalid.
- Service provider missing.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/55222ce96e18269f.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltEe/Sso/src/Service/SsoStates/SsoStatesAssertService.php:97
* @param \Passbolt\Sso\Model\Entity\SsoState $ssoState SSO state entity.
* @param string $ssoSettingsId SSO Settings ID.
* @param \App\Utility\ExtendedUserAccessControl $uac UAC object.
* @return void
*/
private function assert(SsoState $ssoState, string $ssoSettingsId, ExtendedUserAccessControl $uac): void
{
$errorMsg = __('The SSO state is invalid.') . ' ';
if (!SsoState::isValidState($ssoState->state)) {
throw new BadRequestException(trim($errorMsg));
}
if ($ssoState->isExpired()) {
throw new BadRequestException($errorMsg . __('The SSO state is expired.'));
}
if ($ssoState->user_id !== $uac->getId() || !Validation::uuid($ssoState->user_id)) {
throw new BadRequestException($errorMsg . __('User id mismatch.'));
}
if (Configure::read('passbolt.security.userIp')) {
if ($ssoState->ip !== $uac->getUserIp()) {
throw new BadRequestException($errorMsg . __('User IP mismatch.'));
}
}
if (Configure::read('passbolt.security.userAgent')) {
if ($ssoState->user_agent !== $uac->getUserAgent()) {
throw new BadRequestException($errorMsg . __('User agent mismatch.'));
}
}
if ($ssoState->sso_settings_id !== $ssoSettingsId || !Validation::uuid($ssoState->sso_settings_id)) {
throw new BadRequestException($errorMsg . __('Settings mismatch.'));
}
}View on GitHub (pinned to 31c1bbc10f)