feat: implement full authentication system with CSRF protection and email verification flow
All checks were successful
Build and Push App / build (push) Successful in 5m59s

This commit is contained in:
2026-04-30 23:46:34 +02:00
parent 4e881bcbe6
commit 9c003d1b7d
21 changed files with 762 additions and 19 deletions

47
lib/csrf.ts Normal file
View File

@@ -0,0 +1,47 @@
import { NextRequest, NextResponse } from 'next/server';
import { cookies } from 'next/headers';
import crypto from 'crypto';
const CSRF_COOKIE_NAME = 'csrf_token';
const CSRF_HEADER_NAME = 'x-csrf-token';
export async function generateCsrfToken() {
const token = crypto.randomBytes(32).toString('hex');
const cookieStore = await cookies();
cookieStore.set(CSRF_COOKIE_NAME, token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
path: '/',
});
return token;
}
export async function verifyCsrfToken(request: NextRequest) {
const cookieStore = await cookies();
const cookieToken = cookieStore.get(CSRF_COOKIE_NAME)?.value;
const headerToken = request.headers.get(CSRF_HEADER_NAME);
if (!cookieToken || !headerToken || cookieToken !== headerToken) {
return false;
}
return true;
}
/**
* Basic Origin check as an additional layer of defense
*/
export function verifyOrigin(request: NextRequest) {
const origin = request.headers.get('origin');
const host = request.headers.get('host');
if (!origin || !host) return false;
// Remove protocol from origin for comparison if host doesn't have it
const originHost = origin.replace(/^https?:\/\//, '');
return originHost === host || originHost.startsWith(host + ':');
}

17
lib/sanitize.ts Normal file
View File

@@ -0,0 +1,17 @@
import DOMPurify from 'isomorphic-dompurify';
/**
* Sanitizes HTML content to prevent XSS attacks.
* Use this before passing content to dangerouslySetInnerHTML.
*/
export function sanitizeHTML(html: string): string {
return DOMPurify.sanitize(html, {
USE_PROFILES: { html: true },
ALLOWED_TAGS: [
'p', 'br', 'b', 'i', 'em', 'strong', 'a', 'ul', 'ol', 'li',
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'span', 'div',
'img', 'table', 'thead', 'tbody', 'tr', 'th', 'td'
],
ALLOWED_ATTR: ['href', 'target', 'rel', 'src', 'alt', 'class', 'style']
});
}