Skip to content
Esc
navigateopen⌘Jpreview
Dashboard
On this page

Session verification during server-side rendering

Enable secure session verification during server-side rendering with cookie-based sessions.

Overview

In Server Side Rendering (SSR) scenarios, the session verification process is slightly different. Check the following guide to understand how to adjust the flow to work with SSR.

Before you start

For an ordinary browser navigation, the browser can send cookie-based session tokens to the server performing SSR. It cannot add SuperTokens’ header-transfer token to that navigation. Cookie transfer is the default; the cookie’s domain, path, SameSite, and Secure attributes must allow it to reach the SSR server.

Steps

1. Enable sharing of cookies across subdomains

If your API layer and website are on different subdomains (like example.com and api.example.com), then by default, the session tokens attach only to api.example.com. Change this to ensure that the session tokens attach to .example.com and the access token cookie goes to your web server on example.com. Enable this by setting the cookieDomain configuration on the backend.

2. Verify the session

Prefer the released session verification API for your backend framework. For example, the Node.js Next.js integration exports getSSRSession, which accepts the request’s cookies and validates the access-token signature, expiry, and payload shape. It does not run global claim validators or perform an authoritative database check for session revocation. Treat its payload as authenticated claims, not as a complete authorization decision: explicitly validate every claim required by the page, such as tenant, role, permission, email verification, or MFA state.

Before rendering sensitive protected data for which immediate revocation matters, call an authoritative backend/API endpoint that verifies the session with database checking enabled. Other backend frameworks can use getSession or verifySession, provided the SSR response propagates any token updates that the session API attaches. If your platform has no released SuperTokens SDK, follow the strict requirements in the manual verification fallback, not signature-only JWT verification.

If the access token is missing, invalid, or expired, redirect the user to a /refresh-session?redirectBack=<current route> page. You can use another local path on your website instead.

On the /refresh-session page, you want to call the attemptRefreshingSession function (from the client side). This function attempts to refresh the session. If it succeeds, it returns true. If it fails, it returns false. If it returns true, you want to redirect the user back to the page they were on. If it returns false, you want to redirect the user to the login page.

3. Implement the refresh-session flow (/refresh-session page)

On this path, attempt to refresh the session. This can produce either result:

  • Success: The frontend gets new access and refresh tokens. Redirect the user to the validated local path in the redirectBack query parameter.
  • Failure: The session has expired or the backend has revoked it. Redirect the user to the login page.

Below is the code snippet that you can use on the /refresh-session path on the frontend

UI type
import React from "react";
import Session from "supertokens-auth-react/recipe/session";
import SuperTokens from "supertokens-auth-react";

export function AttemptRefresh() {
  React.useEffect(() => {
    let cancel = false;
    Session.attemptRefreshingSession().then((success) => {
      if (cancel) {
        // component has unmounted somehow..
        return;
      }
      if (success) {
        // we have new session tokens, so we redirect the user back
        // to where they were.
        const urlParams = new URLSearchParams(window.location.search);
        const redirectBack = new URL(urlParams.get("redirectBack") ?? "/", window.location.origin);
        window.location.href =
          redirectBack.origin === window.location.origin
            ? `${redirectBack.pathname}${redirectBack.search}${redirectBack.hash}`
            : "/";
      } else {
        // we redirect to the login page since the user
        // is now logged out
        SuperTokens.redirectToAuth();
      }
    });
    return () => {
      cancel = true;
    };
  }, []);
  return null;
}
import Session from "supertokens-web-js/recipe/session";

function attemptRefresh() {
  Session.attemptRefreshingSession().then((success) => {
    if (success) {
      // we have new session tokens, so we redirect the user back
      // to where they were.
      const urlParams = new URLSearchParams(window.location.search);
      const redirectBack = new URL(urlParams.get("redirectBack") ?? "/", window.location.origin);
      window.location.href =
        redirectBack.origin === window.location.origin
          ? `${redirectBack.pathname}${redirectBack.search}${redirectBack.hash}`
          : "/";
    } else {
      // we redirect to the login page since the user
      // is now logged out
      window.location.href = "/login";
    }
  });
}

Why trigger the refresh session flow instead of redirecting the user to the login page directly?

Two reasons why JWT verification can fail are:

  • The session tokens were not passed from the frontend: This can happen if the route is accessed when the user has logged out.
  • The session tokens pass from the frontend, but the JWT has expired.

If the user goes to the login page directly, then in the second case, the frontend redirects the user back to the current route (since the refresh token is still valid), causing an infinite loop. To counteract this issue, redirect the user to a refresh page, which creates a new access token. In the first case, when the user is actually logged out, the refreshing fails, and they go to the login page anyway.

Can verifySession or getSession be used during SSR?

Yes. A released, read-only SSR helper such as Node.js Next.js getSSRSession can authenticate the access token, but the application must still validate the authorization claims required by the page. The helper does not run global claim validators or authoritatively check database revocation. For sensitive data that requires immediate revocation, verify the session through an authoritative backend/API endpoint with database checking before rendering.

You can also use verifySession or getSession, but those APIs may attach rotated or updated tokens to the response. The SSR server must propagate those updates because frontend SDK network interceptors do not run for the browser’s navigation request. If the SSR process should not receive SuperTokens Core credentials, use the read-only helper for authentication and an authoritative backend/API check for sensitive authorization, or use a manual verifier that meets every requirement in the linked fallback guide.


See also

API reference

API schema and response details