Skip to main content
Which frontend SDK do you use?
supertokens-web-js / mobile
supertokens-auth-react

Session verification during server side rendering

1) Call the backend init function on your web server#

If your web server is a different process than the API server, then you should call the SuperTokens backend SDK init function with the Session recipe initialised.

If the web server domain is on a different sub domain than the api domain, then be sure to enable cookie sharing across backend sub domains

2) Use the getSession function#

For server side rendering, we can utilise the getSession function for session verification. The browser will send session cookies along with the request which will be verified by this function resulting in one of these states:

  • Successful verification: This will yield a session object using which you can get the userId of the user.
  • Try refresh token error: This means that the access token has expired and that you should trigger the refresh flow (more on this below).
  • Unauthorised error: This means that the session does not exist, was revoked, or was compromised. Unintuitively, this should also trigger the refresh flow (more on this below) - which will fail and eventually redirect the user to the login screen.

Below is code for how you can use getSession to achieve SSR and get the user's ID from the session:

import express from "express";import Session from "supertokens-node/recipe/session";import { Error as SuperTokensError } from "supertokens-node";
let app = express();
app.get("/dashboard", async (req, res, next) => {    try {        let session = await Session.getSession(req, res, {            overrideGlobalClaimValidators: () => {                // this makes it so that no custom session claims are checked                return []            }        });
        let userId = session.getUserId();        //...    } catch (err) {        if (SuperTokensError.isErrorFromSuperTokens(err)) {            if (err.type === Session.Error.TRY_REFRESH_TOKEN || err.type === Session.Error.UNAUTHORISED) {                res.redirect("/refresh-session?redirectBack=/dashboard");            } else {                next(err);            }        } else {            next(err)        }    }});
important

On successful verification, please do not update the access token payload during SSR because:

  • This is GET request, which usually means no state change.
  • The change to the access token (due to payload update) will not be correctly reflected on the frontend.

3) Implementing the refresh session flow#

From the above code snippets, if the getSession function throws an unauthorised or try refresh token error, we redirect the user to the /refresh-session path on the client side. On this path, we want to attempt refreshing the session which can yield:

  • Success: The frontend will get new access and refresh tokens. Post this, we want to redirect the user to the path mentioned on the redirectBack query param.
  • Failure: This would happen if the session has expired or has been revoked from the backend. Either way, you want to redirect the user to the login page.

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

import React from "react";import Session from "supertokens-auth-react/recipe/session"import SuperTokens from "supertokens-auth-react";
export function AttemptRefresh(props: any) {    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);                window.location.href = urlParams.get('redirectBack')!;            } else {                // we redirect to the login page since the user                // is now logged out                SuperTokens.redirectToAuth();            }        })        return () => {            cancel = true;        }    }, []);    return null;}

Why do we trigger the refresh session flow on UNAUTHORISED error?#

There are two reasons why getSession throws an UNAUTHORISED error:

  • The session tokens were not passed from the frontend: This can happen if the route is called when the user has logged out.
  • The session tokens are passed from the frontend, but has been revoked from the backend: This can happen if the session was somehow revoked in offline mode. Here, whilst the frontend "thinks" that the session exists, it doesn't actually exist.

When this error is thrown, if we redirect the user to the login page directly, then in the second case, the frontend will redirect the user back to the current route (since it thinks that the session exists) causing an infinite loop. To counteract this issue, we redirect the user to refreshing a session page which will attempt a session refresh and fail. On failure, we will then redirect the user to the login page on the frontend. This will also cause the frontend state to be corrected so that it knows that the session doesn't exist anymore.

How can I do optional session verification during SSR?#

Checkout this section on how to pass the optional config when calling the getSession function.