muthuk1's picture
Rebrand: OpenMAIC → MultiMind Classroom — rename in all source, DB name, cookie name, zip extension, prompts, docs, skills
ed07c96 verified
import { cookies } from 'next/headers';
import { createHmac, timingSafeEqual } from 'crypto';
import { apiError, apiSuccess } from '@/lib/server/api-response';
/** Create an HMAC-signed token: `timestamp.signature` */
function createAccessToken(accessCode: string): string {
const timestamp = Date.now().toString();
const signature = createHmac('sha256', accessCode).update(timestamp).digest('hex');
return `${timestamp}.${signature}`;
}
/** Verify an HMAC-signed token against the access code */
export function verifyAccessToken(token: string, accessCode: string): boolean {
const dotIndex = token.indexOf('.');
if (dotIndex === -1) return false;
const timestamp = token.substring(0, dotIndex);
const signature = token.substring(dotIndex + 1);
const expected = createHmac('sha256', accessCode).update(timestamp).digest('hex');
const sigBuf = Buffer.from(signature, 'hex');
const expBuf = Buffer.from(expected, 'hex');
if (sigBuf.length !== expBuf.length) return false;
return timingSafeEqual(sigBuf, expBuf);
}
export async function POST(request: Request) {
const accessCode = process.env.ACCESS_CODE;
if (!accessCode) {
return apiSuccess({ valid: true });
}
let body: { code?: string };
try {
body = await request.json();
} catch {
return apiError('INVALID_REQUEST', 400, 'Invalid JSON body');
}
// Constant-time comparison
if (!body.code) {
return apiError('INVALID_REQUEST', 401, 'Invalid access code');
}
const encoder = new TextEncoder();
const a = encoder.encode(body.code);
const b = encoder.encode(accessCode);
if (a.byteLength !== b.byteLength || !timingSafeEqual(a, b)) {
return apiError('INVALID_REQUEST', 401, 'Invalid access code');
}
const token = createAccessToken(accessCode);
const cookieStore = await cookies();
cookieStore.set('multimind_access', token, {
httpOnly: true,
sameSite: 'lax',
path: '/',
maxAge: 60 * 60 * 24 * 7, // 7 days
secure: process.env.NODE_ENV === 'production',
});
return apiSuccess({ valid: true });
}