cdf4d60038
- Create (auth) route group with standalone layout (no sidebar/header, D-04) - Create (portal) route group wrapping children with AppShell - Move dashboard page into (portal) route group - Add Next.js middleware for JWT-based route protection using jose - Create session.ts with verifySession/getSessionFromCookies helpers - Create auth-actions.ts server actions: login, logout, fetchCurrentUser - Create Zustand auth-store for client-side user state - Install jose and zod dependencies Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
40 lines
1.1 KiB
TypeScript
40 lines
1.1 KiB
TypeScript
import { jwtVerify } from 'jose';
|
|
import type { RequestCookies } from 'next/dist/compiled/@edge-runtime/cookies';
|
|
|
|
/**
|
|
* JWT secret for verifying session tokens.
|
|
* Must match the secret used by the NestJS API to sign JWTs.
|
|
*/
|
|
function getSecret() {
|
|
const secret = process.env.JWT_SECRET || process.env.SESSION_SECRET;
|
|
if (!secret) {
|
|
throw new Error('JWT_SECRET or SESSION_SECRET environment variable is required');
|
|
}
|
|
return new TextEncoder().encode(secret);
|
|
}
|
|
|
|
/**
|
|
* Verify a JWT session token using jose (Edge-compatible).
|
|
* Returns the decoded payload or null if verification fails.
|
|
*/
|
|
export async function verifySession(token: string) {
|
|
try {
|
|
const { payload } = await jwtVerify(token, getSecret(), {
|
|
algorithms: ['HS256'],
|
|
});
|
|
return payload;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Read the "session" cookie value from a cookies object.
|
|
* Works with Next.js middleware request cookies.
|
|
*/
|
|
export function getSessionFromCookies(
|
|
cookies: RequestCookies | { get: (name: string) => { value: string } | undefined },
|
|
) {
|
|
return cookies.get('session')?.value ?? null;
|
|
}
|