6. Making requests from Server Components
Learn to make API requests from server components using access tokens in Next.js.
Let’s modify the Home page from the route protection step to call this API.
import { cookies } from "next/headers";
import { redirect } from "next/navigation";
import { getSSRSession } from "supertokens-node/nextjs";
import { TryRefreshComponent } from "./tryRefreshClientComponent";
import { SessionAuthForNextJS } from "./sessionAuthForNextJS";
import { appInfo } from "../config/appInfo";
import { ensureSuperTokensInit } from "../config/backend";
ensureSuperTokensInit();
async function getAccessToken() {
const cookiesStore = await cookies();
return cookiesStore.get("sAccessToken")?.value;
}
export async function HomePage() {
const cookieStore = await cookies();
const { accessTokenPayload, hasToken, error } = await getSSRSession(cookieStore.getAll());
const accessToken = await getAccessToken();
if (error) {
console.error("Unable to read the SSR session", { component: "HomePage" });
return <div role="alert">Unable to verify your session. Please try again.</div>;
}
// `accessTokenPayload` is undefined if 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(new URL("/api/user", appInfo.websiteDomain), {
headers: {
/**
* We read the access token from the cookies and use it as a Bearer token when
* making network requests.
*/
Authorization: "Bearer " + accessToken,
},
});
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 user's 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.
import { cookies } from "next/headers";
import { redirect } from "next/navigation";
import { getSSRSession } from "supertokens-node/nextjs";
import { TryRefreshComponent } from "./tryRefreshClientComponent";
import { appInfo } from "../config/appInfo";
import { ensureSuperTokensInit } from "../config/backend";
ensureSuperTokensInit();
async function getAccessToken() {
const cookiesStore = await cookies();
return cookiesStore.get("sAccessToken")?.value;
}
export async function HomePage() {
const cookieStore = await cookies();
const { accessTokenPayload, hasToken, error } = await getSSRSession(cookieStore.getAll());
const accessToken = await getAccessToken();
if (error) {
console.error("Unable to read the SSR session", { component: "HomePage" });
return <div role="alert">Unable to verify your session. Please try again.</div>;
}
// `accessTokenPayload` is undefined if 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(new URL("/api/user", appInfo.websiteDomain), {
headers: {
/**
* We read the access token from the cookies and use it as a Bearer token when
* making network requests.
*/
Authorization: "Bearer " + accessToken,
},
});
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) {
/**
* This means that one of the session claims is invalid. You should redirect the user to
* the appropriate page depending on which claim is invalid.
*/
return <div>Invalid Session Claims</div>;
}
// You can use `userInfoResponse` to read the user's session information
return <div>{message}</div>;
}APIs that require sessions will return status:
401if there is no valid session or if the session has expired. In this case, we return theTryRefreshComponentcomponent, which tries to refresh the session or redirects to the login page if the session can’t be refreshed.403if one or more session claims fail validation. In this case, check which session claim failed and redirect the user accordingly. For example, refer to protecting routes with email verification to check the email verification claim.