diff --git a/examples/nextjs-csr/README.md b/examples/nextjs-csr/README.md index 6b662a6..50fbb8c 100644 --- a/examples/nextjs-csr/README.md +++ b/examples/nextjs-csr/README.md @@ -12,10 +12,10 @@ Before you can run the development server, you will have to register your client Copy the `.env.example` file, rename it to `.env`, and fill in your credentials obtained during registration. -Then, run the server by running: +Then, run the development server by running: ```bash -npm run start:dev +npm run dev ``` Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. diff --git a/examples/nextjs-csr/package.json b/examples/nextjs-csr/package.json index 8217f2f..ef20165 100644 --- a/examples/nextjs-csr/package.json +++ b/examples/nextjs-csr/package.json @@ -3,10 +3,9 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "NEXT_ENV=development next dev", + "dev": "next dev", "build": "next build", "start": "next start", - "start:dev": "next build && NEXT_ENV=development next start", "lint": "next lint" }, "dependencies": { diff --git a/examples/nextjs-csr/src/lib/sgidClient.ts b/examples/nextjs-csr/src/lib/sgidClient.ts index 058e413..9877aaf 100644 --- a/examples/nextjs-csr/src/lib/sgidClient.ts +++ b/examples/nextjs-csr/src/lib/sgidClient.ts @@ -1,13 +1,10 @@ -import { SgidClient } from "@opengovsg/sgid-client"; +import { SgidClient } from '@opengovsg/sgid-client' const sgidClient = new SgidClient({ - clientId: String(process.env.SGID_CLIENT_ID) || "", - clientSecret: String(process.env.SGID_CLIENT_SECRET) || "", - privateKey: String(process.env.SGID_PRIVATE_KEY).replace(/\\n/g, "\n") || "", - redirectUri: - process.env.NEXT_ENV !== "development" - ? "https://sgid-nextjs-csr-demo.vercel.app/api/callback" - : "http://localhost:3000/api/callback", -}); + clientId: String(process.env.SGID_CLIENT_ID), + clientSecret: String(process.env.SGID_CLIENT_SECRET), + privateKey: String(process.env.SGID_PRIVATE_KEY), + redirectUri: 'http://localhost:3000/api/callback', +}) -export { sgidClient }; +export { sgidClient } diff --git a/examples/nextjs-csr/src/lib/store.ts b/examples/nextjs-csr/src/lib/store.ts index 9737311..a0ad6c8 100644 --- a/examples/nextjs-csr/src/lib/store.ts +++ b/examples/nextjs-csr/src/lib/store.ts @@ -1,3 +1,13 @@ +type Global = typeof global + +interface GlobalWithStore extends Global { + store: Map +} + +/** + * We place the store in the global object to prevent it from being cleared whenever compilation happens + * https://stackoverflow.com/questions/75272877/how-to-prevent-next-js-from-instantiating-a-singleton-class-object-multiple-time + */ type Session = { state?: string codeVerifier?: string @@ -7,6 +17,16 @@ type Session = { userInfo?: Record } -const store = new Map() +let store: Map + +if (process.env.NODE_ENV === 'production') { + store = new Map() +} else { + // If the store does not exist, initialize it + if (!(global as GlobalWithStore).store) { + ;(global as GlobalWithStore).store = new Map() + } + store = (global as GlobalWithStore).store +} export { store } diff --git a/examples/nextjs-csr/src/pages/api/auth-url.ts b/examples/nextjs-csr/src/pages/api/auth-url.ts index d1d7eab..7701a22 100644 --- a/examples/nextjs-csr/src/pages/api/auth-url.ts +++ b/examples/nextjs-csr/src/pages/api/auth-url.ts @@ -1,27 +1,27 @@ // Next.js API route support: https://nextjs.org/docs/api-routes/introduction -import type { NextApiRequest, NextApiResponse } from "next"; -import { v4 as uuidv4 } from "uuid"; -import { store } from "../../lib/store"; -import { sgidClient } from "../../lib/sgidClient"; -import { setCookie } from "cookies-next"; -import { generatePkcePair } from "@opengovsg/sgid-client"; +import type { NextApiRequest, NextApiResponse } from 'next' +import { v4 as uuidv4 } from 'uuid' +import { store } from '../../lib/store' +import { sgidClient } from '../../lib/sgidClient' +import { setCookie } from 'cookies-next' +import { generatePkcePair } from '@opengovsg/sgid-client' export default function handler(req: NextApiRequest, res: NextApiResponse) { - let { state } = req.query; - state = String(state); + let { state } = req.query + state = String(state) - const sessionId = uuidv4(); + const sessionId = uuidv4() - const { codeChallenge, codeVerifier } = generatePkcePair(); + const { codeChallenge, codeVerifier } = generatePkcePair() const { url, nonce } = sgidClient.authorizationUrl({ state, codeChallenge, - }); + }) - store.set(sessionId, { state, nonce, codeVerifier }); + store.set(sessionId, { state, nonce, codeVerifier }) - setCookie("sessionId", sessionId, { req, res }); + setCookie('sessionId', sessionId, { req, res, httpOnly: true, secure: true }) - res.redirect(url); + res.redirect(url) }