BookStackApp/BookStack · error · OidcException
errors.oidc_already_logged_in
Error message
errors.oidc_already_logged_in
What it means
BookStack throws this when an OIDC callback/authorization flow is processed while a user is already authenticated (auth()->check() is true). The OIDC login flow is only meant to run for logged-out users, so it refuses to proceed to avoid hijacking or corrupting the existing session.
Source
Thrown at app/Access/Oidc/OidcService.php:218
}
try {
$idToken->validate($settings->clientId);
} catch (OidcInvalidTokenException $exception) {
throw new OidcException("ID token validation failed with error: {$exception->getMessage()}");
}
$userDetails = $this->getUserDetailsFromToken($idToken, $accessToken, $settings);
if (empty($userDetails->email)) {
throw new OidcException(trans('errors.oidc_no_email_address'));
}
if (empty($userDetails->name)) {
$userDetails->name = $userDetails->externalId;
}
$isLoggedIn = auth()->check();
if ($isLoggedIn) {
throw new OidcException(trans('errors.oidc_already_logged_in'));
}
try {
$user = $this->registrationService->findOrRegister(
$userDetails->name,
$userDetails->email,
$userDetails->externalId
);
} catch (UserRegistrationException $exception) {
throw new OidcException($exception->getMessage());
}
if ($this->config()['fetch_avatar'] && !$user->avatar()->exists() && $userDetails->picture) {
$this->userAvatars->assignToUserFromUrl($user, $userDetails->picture);
}
if ($this->shouldSyncGroups()) {
$detachExisting = $this->config()['remove_from_groups'];View on GitHub (pinned to 18f8469a1c)
Solutions
- Log out of BookStack before initiating OIDC login (visit /logout or let session expire)
- Start the OIDC flow from the BookStack login page rather than saved/deep links to the callback
- Clear stale BookStack session cookies (XSRF-TOKEN, session cookie) in the browser
- If it happens for all users after an IdP change, verify the OIDC login entry point is not being embedded in authenticated pages
Defensive patterns
Strategy: try-catch
Validate before calling
// Client-side guard: don't start OIDC flow when a session exists
if (document.cookie.includes(document.getElementById('session-cookie-name')?.value)) {
// already logged in — skip the /oidc/login redirect
} Try / catch
// Server-side: detect and treat as a no-op redirect
try {
auth()->attemptOidcLogin();
} catch (BookStack\Access\Oidc\OidcException $e) {
if (trans('errors.oidc_already_logged_in') === $e->getMessage()) {
return redirect('/'); // already authenticated; just send home
}
throw $e;
} Prevention
- Never bookmark or share OIDC callback URLs; start flows from the login page
- Clear stale session cookies when switching accounts
- Avoid IdP-initiated SSO directly into the callback endpoint
- Purge old authorize links from emails/notifications
When it happens
Trigger: processAccessTokenCallback runs and auth()->check() returns true — e.g. an already-logged-in user hits the OIDC callback URL (/social/oidc/callback or /oidc/callback) directly, retries an old authorize URL from a bookmark, or a second browser tab completes the OIDC flow after they logged in another way.
Common situations: User bookmarks the callback URL, opens the login URL while already logged in, session cookies persist across an IdP-initiated SSO redirect, or stale authorize-link emails are clicked.
Related errors
- ID token validation failed with error: {$exception->getMessa
- errors.saml_already_logged_in
- 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/2a613eeac0f2abef.
Report an issue: GitHub.