Skip to content

Commit

Permalink
Fix next boilerplates to not use getSSRSession util method
Browse files Browse the repository at this point in the history
  • Loading branch information
deepjyoti30-st committed Nov 1, 2024
1 parent 6bcb6bd commit dfd535d
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { CelebrateIcon, SeparatorLine } from "../../assets/images";
import { CallAPIButton } from "./callApiButton";
import { LinksComponent } from "./linksComponent";
import { SessionAuthForNextJS } from "./sessionAuthForNextJS";
import { getSSRSession } from "supertokens-node/nextjs";
import { getSessionForSSR } from "../util";

export async function HomePage() {
const cookiesFromReq = await cookies();
Expand All @@ -17,7 +17,7 @@ export async function HomePage() {
value,
})
);
const { accessTokenPayload, hasToken, error } = await getSSRSession(cookiesArray);
const { accessTokenPayload, hasToken, error } = await getSessionForSSR(cookiesArray);

if (error) {
return <div>Something went wrong while trying to get the session. Error - {error.message}</div>;
Expand Down
59 changes: 59 additions & 0 deletions boilerplate/fullstack/next-app-dir-multitenancy/app/util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import JsonWebToken from "jsonwebtoken";
import type { JwtHeader, JwtPayload, SigningKeyCallback } from "jsonwebtoken";
import jwksClient from "jwks-rsa";
import { appInfo } from "./config/appInfo";

const client = jwksClient({
jwksUri: `${appInfo.apiDomain}${appInfo.apiBasePath}/jwt/jwks.json`,
});

async function verifyToken(token: string): Promise<JwtPayload> {
const getPublicKey = (header: JwtHeader, callback: SigningKeyCallback) => {
client.getSigningKey(header.kid, (err, key) => {
if (err) {
callback(err);
} else {
const signingKey = key?.getPublicKey();
callback(null, signingKey);
}
});
};

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 function from the supertokens-node SDK
* because getSession can update the access token. These updated tokens would not be
* propagated to the client side, as request interceptors do not run on the server side.
*/
export async function getSessionForSSR(cookies: Array<{ name: string; value: string }>): Promise<{
accessTokenPayload: JwtPayload | undefined;
hasToken: boolean;
error: Error | undefined;
}> {
let accessToken = cookies.find((cookie) => cookie.name === "sAccessToken")?.value;
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 };
}
}
4 changes: 2 additions & 2 deletions boilerplate/fullstack/next-app-dir/app/components/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { CelebrateIcon, SeparatorLine } from "../../assets/images";
import { CallAPIButton } from "./callApiButton";
import { LinksComponent } from "./linksComponent";
import { SessionAuthForNextJS } from "./sessionAuthForNextJS";
import { getSSRSession } from "supertokens-node/nextjs";
import { getSessionForSSR } from "../util";

export async function HomePage() {
const cookiesFromReq = await cookies();
Expand All @@ -17,7 +17,7 @@ export async function HomePage() {
value,
})
);
const { accessTokenPayload, hasToken, error } = await getSSRSession(cookiesArray);
const { accessTokenPayload, hasToken, error } = await getSessionForSSR(cookiesArray);

if (error) {
return <div>Something went wrong while trying to get the session. Error - {error.message}</div>;
Expand Down
59 changes: 59 additions & 0 deletions boilerplate/fullstack/next-app-dir/app/util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import JsonWebToken from "jsonwebtoken";
import type { JwtHeader, JwtPayload, SigningKeyCallback } from "jsonwebtoken";
import jwksClient from "jwks-rsa";
import { appInfo } from "./config/appInfo";

const client = jwksClient({
jwksUri: `${appInfo.apiDomain}${appInfo.apiBasePath}/jwt/jwks.json`,
});

async function verifyToken(token: string): Promise<JwtPayload> {
const getPublicKey = (header: JwtHeader, callback: SigningKeyCallback) => {
client.getSigningKey(header.kid, (err, key) => {
if (err) {
callback(err);
} else {
const signingKey = key?.getPublicKey();
callback(null, signingKey);
}
});
};

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 function from the supertokens-node SDK
* because getSession can update the access token. These updated tokens would not be
* propagated to the client side, as request interceptors do not run on the server side.
*/
export async function getSessionForSSR(cookies: Array<{ name: string; value: string }>): Promise<{
accessTokenPayload: JwtPayload | undefined;
hasToken: boolean;
error: Error | undefined;
}> {
let accessToken = cookies.find((cookie) => cookie.name === "sAccessToken")?.value;
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 };
}
}

0 comments on commit dfd535d

Please sign in to comment.