2c001df322
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.
56 lines
1.7 KiB
TypeScript
56 lines
1.7 KiB
TypeScript
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 });
|
|
}
|
|
};
|