Skip to Content
🤖 Realtime UIBasic Authentication and Authorization (Password Protection)

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 crypto from 'node:crypto'; import { cookies } from 'next/headers'; import { redirect } from 'next/navigation'; import { cache } from 'react'; 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