Skip to Content

Basic Authentication and Authorization for Password Protection

The app implements a simple authentication mechanism with an optional PASSWORD stored in the .env file. Once the user enters the password, a session cookie is created that authorizes the user for subsequent requests. The userId is a hashed version of the password, which allows all sessions to be invalidated by changing the PASSWORD env variable in production.

The authentication flow is a simplified version of the solution provided in the official Next.js authentication documentation . It implements a login page  with a form that invokes a login server action . The session is created in src/lib/session.ts , and the Data Access Layer file is defined in src/lib/dal.ts .

The DAL file exports the verifySession function, which is invoked in page.tsx  and redirects the user to the login page if the session is invalid.

src/lib/dal.ts
import { cookies } from "next/headers"; import { cache } from "react"; import { redirect } from "next/navigation"; import crypto from "crypto"; import { decrypt } from "./session"; const getSession = async () => { const cookie = (await cookies()).get("session")?.value; const session = await decrypt(cookie); return session; }; export const isLoggedIn = async () => { if (!process.env.PASSWORD) return true; const session = await getSession(); const userId = crypto .createHash("md5") .update(process.env.PASSWORD) .digest("hex"); return session?.userId === userId; }; export const verifySession = cache(async () => { if (!(await isLoggedIn())) { redirect("/login"); } });

The code above is fetched from GitHub repository. 

src/app/page.tsx
import { verifySession } from "@/lib/dal"; export default async function Home() { await verifySession(); // ...

It also exports the isLoggedIn function, which is used by the sessionGuard decorator to check if the user is logged in when invoking procedures.

src/decorators/sessionGuard.ts
import { createDecorator, HttpException, HttpStatus } from "vovk"; import { isLoggedIn } from "@/lib/dal"; export const sessionGuard = createDecorator(async (req, next) => { if (typeof req.url !== "undefined" && !(await isLoggedIn())) { throw new HttpException(HttpStatus.UNAUTHORIZED, "Unauthorized"); } return next(); });

The code above is fetched from GitHub repository. 

The sessionGuard decorator is applied to all procedures. The typeof req.url !== 'undefined' check is required to distinguish between HTTP requests and fn invocations.

Last updated on