Skip to main content

If you are using our backend SDK that is lesser than the following versions, please visit the older documentation link here.

Which UI do you use?
Custom UI
Pre built UI

6. Making requests from Server Components

Lets modify the Home page we made in a previous step to make a call to this API

app/components/home.tsx
import { cookies } from "next/headers";
import { redirect } from "next/navigation";
import { TryRefreshComponent } from "./tryRefreshClientComponent";
import { SessionAuthForNextJS } from "./sessionAuthForNextJS";
import jwksClient from "jwks-rsa";
import JsonWebToken from "jsonwebtoken";
import type { JwtHeader, JwtPayload, SigningKeyCallback } from "jsonwebtoken";

const client = jwksClient({
jwksUri: "/.well-known/jwks.json",
});

function getAccessToken(): string | undefined {
return cookies().get("sAccessToken")?.value;
}

function getPublicKey(header: JwtHeader, callback: SigningKeyCallback) {
client.getSigningKey(header.kid, (err, key) => {
if (err) {
callback(err);
} else {
const signingKey = key?.getPublicKey();
callback(null, signingKey);
}
});
}

async function verifyToken(token: string): Promise<JwtPayload> {
return new Promise((resolve, reject) => {
JsonWebToken.verify(token, getPublicKey, {}, (err, decoded) => {
if (err) {
reject(err);
} else {
resolve(decoded as JwtPayload);
}
});
});
}

/**
* A helper function to retrieve session details on the server side.
*
* NOTE: This function does not use the getSession / verifySession function from the supertokens-node SDK
* because those functions may update the access token. These updated tokens would not be
* propagated to the client side properly, as request interceptors do not run on the server side.
* So instead, we use regular JWT verification library
*/
async function getSSRSessionHelper(): Promise<{
accessTokenPayload: JwtPayload | undefined;
hasToken: boolean;
error: Error | undefined;
}> {
const accessToken = getAccessToken();
const hasToken = !!accessToken;
try {
if (accessToken) {
const decoded = await verifyToken(accessToken);
return { accessTokenPayload: decoded, hasToken, error: undefined };
}
return { accessTokenPayload: undefined, hasToken, error: undefined };
} catch (error) {
if (error instanceof JsonWebToken.TokenExpiredError) {
return { accessTokenPayload: undefined, hasToken, error: undefined };
}
return { accessTokenPayload: undefined, hasToken, error: error as Error };
}
}

export async function HomePage() {
const { accessTokenPayload, hasToken, error } = await getSSRSessionHelper();

if (error) {
return <div>Something went wrong while trying to get the session. Error - {error.message}</div>;
}

// `accessTokenPayload` will be undefined if it the session does not exist or has expired
if (accessTokenPayload === undefined) {
if (!hasToken) {
/**
* This means that the user is not logged in. If you want to display some other UI in this
* case, you can do so here.
*/
return redirect("/auth");
}

/**
* This means that the session does not exist but we have session tokens for the user. In this case
* the `TryRefreshComponent` will try to refresh the session.
*
* To learn about why the 'key' attribute is required refer to: https://github.com/supertokens/supertokens-node/issues/826#issuecomment-2092144048
*/
return <TryRefreshComponent key={Date.now()} />;
}

const userInfoResponse = await fetch('http://localhost:3000/api/user', {
headers: {
/**
* We read the access token from the cookies and use that as a Bearer token when
* making network requests.
*/
Authorization: 'Bearer ' + getAccessToken(),
},
});

let message = "";

if (userInfoResponse.status === 200) {
message = `Your user id is: ${accessTokenPayload.sub}`
} else if (userInfoResponse.status === 500) {
message = "Something went wrong"
} else if (userInfoResponse.status === 401) {
// The TryRefreshComponent will try to refresh the session
// To learn about why the 'key' attribute is required refer to: https://github.com/supertokens/supertokens-node/issues/826#issuecomment-2092144048
return <TryRefreshComponent key={Date.now()} />
} else if (userInfoResponse.status === 403) {
// SessionAuthForNextJS will redirect based on which claim is invalid
return <SessionAuthForNextJS />;
}

// You can use `userInfoResponse` to read the users session information

return (
<SessionAuthForNextJS>
<div>
{message}
</div>
</SessionAuthForNextJS>
);
}

We read the access token of the user from cookies. We can then send the access token as a header to the API. When the API calls withSession it will try to read the access token from the headers and if a session exists it will return the session information.

Looking for older versions of the documentation?
Which UI do you use?
Custom UI
Pre built UI