feat(mvp): phase 3 - authentication system
Implement local auth flow: login, registration, logout, JWT access/refresh tokens in HTTP-only cookies, hooks.server.ts middleware, guest mode support, Superforms + Zod validation, and reusable auth/authorize middleware.
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
import { json } from '@sveltejs/kit';
|
||||
import type { RequestHandler } from './$types.js';
|
||||
import * as authService from '$lib/server/services/authService.js';
|
||||
import * as userService from '$lib/server/services/userService.js';
|
||||
import { error as apiError } from '$lib/server/utils/response.js';
|
||||
|
||||
const COOKIE_BASE = {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
sameSite: 'lax' as const,
|
||||
path: '/'
|
||||
};
|
||||
|
||||
export const POST: RequestHandler = async ({ cookies }) => {
|
||||
const refreshToken = cookies.get('refresh_token');
|
||||
const userId = cookies.get('refresh_user_id');
|
||||
|
||||
if (!refreshToken || !userId) {
|
||||
return json(apiError('No refresh token provided'), { status: 401 });
|
||||
}
|
||||
|
||||
try {
|
||||
const isValid = await authService.validateRefreshToken(userId, refreshToken);
|
||||
if (!isValid) {
|
||||
// Clear stale cookies
|
||||
cookies.delete('access_token', { path: '/' });
|
||||
cookies.delete('refresh_token', { path: '/' });
|
||||
cookies.delete('refresh_user_id', { path: '/' });
|
||||
return json(apiError('Invalid or expired refresh token'), { status: 401 });
|
||||
}
|
||||
|
||||
const user = await userService.findById(userId);
|
||||
const tokens = await authService.rotateTokens(user.id, user.email, user.role);
|
||||
|
||||
cookies.set('access_token', tokens.accessToken, {
|
||||
...COOKIE_BASE,
|
||||
maxAge: 900
|
||||
});
|
||||
cookies.set('refresh_token', tokens.refreshToken, {
|
||||
...COOKIE_BASE,
|
||||
maxAge: 604800
|
||||
});
|
||||
|
||||
return json({
|
||||
success: true,
|
||||
data: { expiresIn: 900 },
|
||||
error: null
|
||||
});
|
||||
} catch {
|
||||
cookies.delete('access_token', { path: '/' });
|
||||
cookies.delete('refresh_token', { path: '/' });
|
||||
cookies.delete('refresh_user_id', { path: '/' });
|
||||
return json(apiError('Token refresh failed'), { status: 401 });
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user