Skip to main content

5b. Session verification in getServerSideProps


This is applicable for when verifying a session in getServerSideProps or getInitialProps.

For this guide, we will assume that we want to pass the logged in user's ID as a prop to a protected route. An easier method to achieve this would be to directly get the user ID from the frontend, but for this example, we will pass it from the server side.

1) We use getSession in getServerSideProps#


If using getInitialProps, the method described below applies as well. The only difference is the way the props are returned (see comments in the code).

An example of this can be found here.

import Session from 'supertokens-node/recipe/session'import supertokensNode from 'supertokens-node'import { backendConfig } from '../config/backendConfig'
export async function getServerSideProps(context: any) {
    // this runs on the backend, so we must call init on supertokens-node SDK    supertokensNode.init(backendConfig())
    // this will contain the session object post verification    let session
    try {        // getSession will do session verification for us        session = await Session.getSession(context.req, context.res)    } catch (err: any) {        if (err.type === Session.Error.TRY_REFRESH_TOKEN) {
            // in this case, the session is still valid, only the access token has expired.            // The refresh token is not sent to this route as it's tied to the /api/auth/session/refresh API paths.            // So we must send a "signal" to the frontend which will then call the             // refresh API and reload the page.
            return { props: { fromSupertokens: 'needs-refresh' } }            // or return {fromSupertokens: 'needs-refresh'} in case of getInitialProps        } else if (err.type === Session.Error.UNAUTHORISED || err.type === Session.Error.INVALID_CLAIMS) {            // The user is logged out or missing some required claim.             // Since this is for a protected route, we can simple send an empty prop object.             // Alternatively, you can pass anything else you would like here, e.g.: the missing claim.            return { props: {} }            // or return {} in case of getInitialProps        } else {            throw err        }    }
    // session verification is successful and we can pass    // the user's ID to the frontend.
    return {        props: { userId: session!.getUserId() },    }    // or return {userId: session.getUserId()} in case of getInitialProps}

Do not use the verifySession function here. The reason is that this will send a reply to the client in case of TRY_REFRESH_TOKEN, and here, we want to catch that error and send a custom reply.

2) Doing manual refresh on the frontend#

  • The following will refresh a session if needed, for all your website pages
  • This goes in the /pages/_app.js file
  • An example of this can be found here.
import React, { useEffect } from "react";import Session from 'supertokens-auth-react/recipe/session'import { redirectToAuth } from 'supertokens-auth-react'import { AppProps } from "next/app";
function MyApp({ Component, pageProps }: AppProps<{fromSupertokens: string}>) {    useEffect(() => {
        async function doRefresh() {            // pageProps.fromSupertokens === 'needs-refresh' will be true            // when in getServerSideProps, getSession throws a TRY_REFRESH_TOKEN            // error.
            if (pageProps.fromSupertokens === 'needs-refresh') {                if (await Session.attemptRefreshingSession()) {                    // post session refreshing, we reload the page. This will                    // send the new access token to the server, and then                     // getServerSideProps will succeed                    location.reload()                } else {                    // the user's session has expired. So we redirect                    // them to the login page                    redirectToAuth()                }            }        }        doRefresh()
    }, [pageProps.fromSupertokens])
    if (pageProps.fromSupertokens === 'needs-refresh') {        // in case the frontend needs to refresh, we show nothing.        // Alternatively, you can show a spinner.
        return null    }
    // the below is already there by default    return <Component {...pageProps} />}
export default MyApp

3) Consume the userId returned by getServerSideProps in your component#

On success, getServerSideProps returns

{    // Refer to Step 1)    props: { userId: session.getUserId() }}

Therefore, the associated page can access the userId like:

export default function Home(props: any) {    let userId = props.userId;}