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

  1. Log out of BookStack before initiating OIDC login (visit /logout or let session expire)
  2. Start the OIDC flow from the BookStack login page rather than saved/deep links to the callback
  3. Clear stale BookStack session cookies (XSRF-TOKEN, session cookie) in the browser
  4. 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

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


AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02). Data as JSON: /api/errors/2a613eeac0f2abef. Report an issue: GitHub.