BookStackApp/BookStack · warning · SamlException
errors.saml_already_logged_in
Error message
errors.saml_already_logged_in
What it means
SamlException thrown when the user arriving at the SAML2 ACS callback is already logged into BookStack. processLoginCallback refuses to run the find-or-register flow for an authenticated session, redirecting to /login instead, to avoid hijacking or mixing existing sessions.
Source
Thrown at app/Access/Saml2Service.php:365
if ($this->shouldSyncGroups()) {
$userDetails['groups'] = $this->getUserGroups($samlAttributes);
}
if ($this->config['dump_user_details']) {
throw new JsonDebugException([
'id_from_idp' => $samlID,
'attrs_from_idp' => $samlAttributes,
'attrs_after_parsing' => $userDetails,
]);
}
if (empty($userDetails['email'])) {
throw new SamlException(trans('errors.saml_no_email_address'));
}
if ($isLoggedIn) {
throw new SamlException(trans('errors.saml_already_logged_in'), '/login');
}
$user = $this->registrationService->findOrRegister(
$userDetails['name'],
$userDetails['email'],
$userDetails['external_id']
);
if ($this->shouldSyncGroups()) {
$this->groupSyncService->syncUserWithFoundGroups($user, $userDetails['groups'], $this->config['remove_from_groups']);
}
$this->loginService->login($user, 'saml2');
return $user;
}
}
View on GitHub (pinned to 18f8469a1c)
Solutions
- Simply log out of BookStack (or the browser session) before retrying SAML login, or navigate to /login and choose the normal route
- Guard the SAML login entry point in your app/redirect logic: if the user is already authenticated, skip calling /saml2/login and route them to the dashboard
- If this occurs on every login, check for mismatched session cookies (e.g. APP_URL vs actual host, or multiple BookStack instances sharing a cookie domain) that make BookStack think the user is logged in
- Clear cookies for the BookStack domain to remove stale authenticated sessions
Example fix
// before: blindly linking SAML login <a href="/saml2/login">Login with SAML</a> // after: only initiate SAML for guests @auth <a href="/">Dashboard</a> @else <a href="/saml2/login">Login with SAML</a> @endauth
Defensive patterns
Strategy: validation
Validate before calling
// Only initiate SAML login for guests
if (auth()->check()) {
return redirect('/'); // already logged in; skip /saml2/login
} Type guard
function canInitiateSamlLogin(\Illuminate\Contracts\Auth\Guard $auth): bool
{
return !$auth->check();
} Try / catch
use BookStack\Exceptions\SamlException;
try {
$saml->processLoginCallback();
} catch (SamlException $e) {
if ($e->getMessage() === trans('errors.saml_already_logged_in')) {
return redirect('/'); // or '/login' as the exception suggests
}
throw $e;
} Prevention
- Hide/disable SAML login entry points for already-authenticated users in your theme/redirect logic
- Avoid bookmarking or auto-refreshing the /saml2/login URL
- Keep APP_URL and cookie settings consistent so stale authenticated sessions aren't misdetected
- Clear BookStack cookies if you switch between environments sharing a cookie domain
When it happens
Trigger: A user with an active BookStack session initiates SAML login again (e.g. visits the /saml2/login route or an auto-initiated login while already authenticated) and completes the IdP round-trip; $isLoggedIn is true when processLoginCallback executes.
Common situations: User bookmarks the SAML login URL and clicks it while logged in; session remembered via 'remember me' while the IdP session also persists; an automated/auto-initiated IdP login (IdP-initiated SSO) triggered from an already-authenticated tab.
Related errors
- errors.oidc_already_logged_in
- errors.saml_no_email_address
- errors.login_user_not_found
- errors.social_no_action_defined
- ($isAnonymous ? trans('errors.ldap_fail_anonymous') : trans(
AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02).
Data as JSON: /api/errors/efb30efd9d939626.
Report an issue: GitHub.