diff --git a/app/api/auth/login/route.ts b/app/api/auth/login/route.ts deleted file mode 100644 index f4b54c4..0000000 --- a/app/api/auth/login/route.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { NextRequest, NextResponse } from 'next/server'; -import { generateAccessToken, generateRefreshToken, validateAdminCredentials, isSecureCookie } from '@/lib/auth/utils'; - -export async function POST(request: NextRequest) { - try { - const body = await request.json(); - const { username, password } = body; - - if (!username || !password) { - return NextResponse.json( - { error: 'Username and password are required' }, - { status: 400 } - ); - } - - // Validate credentials - if (!validateAdminCredentials(username, password)) { - return NextResponse.json( - { error: 'Invalid credentials' }, - { status: 401 } - ); - } - - // Generate tokens - const accessToken = generateAccessToken(username); - const refreshToken = generateRefreshToken(username); - - // Create response - const response = NextResponse.json({ - success: true, - user: { username }, - accessToken, - refreshToken, - }); - - // Set cookies - const cookieOptions = { - httpOnly: true, - secure: isSecureCookie(request), - sameSite: 'lax' as const, - path: '/', - }; - - response.cookies.set('access_token', accessToken, { - ...cookieOptions, - maxAge: 72 * 60 * 60, // 72 hours - }); - - response.cookies.set('refresh_token', refreshToken, { - ...cookieOptions, - maxAge: 30 * 24 * 60 * 60, // 30 days - }); - - return response; - } catch (error) { - console.error('Login error:', error); - return NextResponse.json( - { error: 'Login failed' }, - { status: 500 } - ); - } -} diff --git a/app/api/auth/logout/route.ts b/app/api/auth/logout/route.ts index d152521..095f6ca 100644 --- a/app/api/auth/logout/route.ts +++ b/app/api/auth/logout/route.ts @@ -1,13 +1,10 @@ import { NextRequest, NextResponse } from 'next/server'; +import { ADM_COOKIE, USR_COOKIE, buildClearCookie, isSecureCookie } from '@/lib/auth/cookies'; export async function POST(request: NextRequest) { - const response = NextResponse.json({ - success: true, - message: 'Logged out successfully' - }); - - response.cookies.delete('access_token'); - response.cookies.delete('refresh_token'); - - return response; + const secure = isSecureCookie(request); + const headers = new Headers(); + headers.append('Set-Cookie', buildClearCookie(ADM_COOKIE, secure)); + headers.append('Set-Cookie', buildClearCookie(USR_COOKIE, secure)); + return NextResponse.json({ success: true }, { headers }); } diff --git a/app/api/auth/me/route.ts b/app/api/auth/me/route.ts deleted file mode 100644 index 6220d43..0000000 --- a/app/api/auth/me/route.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { NextRequest, NextResponse } from 'next/server'; -import { verifyAccessToken } from '@/lib/auth/utils'; - -export async function GET(request: NextRequest) { - try { - const token = request.cookies.get('access_token')?.value; - - if (!token) { - return NextResponse.json( - { error: 'Not authenticated' }, - { status: 401 } - ); - } - - const payload = verifyAccessToken(token); - if (!payload) { - return NextResponse.json( - { error: 'Invalid or expired token' }, - { status: 401 } - ); - } - - return NextResponse.json({ - success: true, - user: { username: payload.username }, - }); - } catch (error) { - console.error('Auth error:', error); - return NextResponse.json( - { error: 'Authentication failed' }, - { status: 500 } - ); - } -} diff --git a/app/api/auth/refresh/route.ts b/app/api/auth/refresh/route.ts deleted file mode 100644 index 537461f..0000000 --- a/app/api/auth/refresh/route.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { NextRequest, NextResponse } from 'next/server'; -import { generateAccessToken, generateRefreshToken, verifyRefreshToken, isSecureCookie } from '@/lib/auth/utils'; - -export async function POST(request: NextRequest) { - try { - // Get refresh token from cookie or body - let refreshToken: string | undefined; - - const cookieToken = request.cookies.get('refresh_token')?.value; - if (cookieToken) { - refreshToken = cookieToken; - } else { - try { - const body = await request.json(); - refreshToken = body.refreshToken; - } catch { - // No body or invalid JSON, continue without it - refreshToken = undefined; - } - } - - if (!refreshToken) { - return NextResponse.json( - { error: 'No refresh token provided' }, - { status: 401 } - ); - } - - // Verify refresh token - const payload = verifyRefreshToken(refreshToken); - if (!payload) { - return NextResponse.json( - { error: 'Invalid or expired refresh token' }, - { status: 401 } - ); - } - - // Generate new tokens - const newAccessToken = generateAccessToken(payload.username); - const newRefreshToken = generateRefreshToken(payload.username); - - // Create response - const response = NextResponse.json({ - success: true, - accessToken: newAccessToken, - refreshToken: newRefreshToken, - }); - - // Set new cookies - const cookieOptions = { - httpOnly: true, - secure: isSecureCookie(request), - sameSite: 'lax' as const, - path: '/', - }; - - response.cookies.set('access_token', newAccessToken, { - ...cookieOptions, - maxAge: 72 * 60 * 60, // 72 hours - }); - - response.cookies.set('refresh_token', newRefreshToken, { - ...cookieOptions, - maxAge: 30 * 24 * 60 * 60, // 30 days - }); - - return response; - } catch (error) { - console.error('Refresh error:', error); - return NextResponse.json( - { error: 'Token refresh failed' }, - { status: 500 } - ); - } -} diff --git a/app/api/auth/session/route.ts b/app/api/auth/session/route.ts new file mode 100644 index 0000000..256899e --- /dev/null +++ b/app/api/auth/session/route.ts @@ -0,0 +1,50 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { isAdminTokenValue, isGuestTokenValue, getGuestFromRequest, verifyAdminToken } from '@/lib/auth/tokens'; +import { ADM_COOKIE, USR_COOKIE, buildCookie, isSecureCookie } from '@/lib/auth/cookies'; + +const ONE_YEAR = 60 * 60 * 24 * 365; + +export async function POST(request: NextRequest) { + const body = await request.json().catch(() => ({})); + const { adm, usr } = body as { adm?: string; usr?: string }; + + const headers = new Headers(); + const secure = isSecureCookie(request); + const cookies: string[] = []; + let role: 'admin' | 'guest' | 'none' = 'none'; + let guestId: string | null = null; + + if (adm) { + if (!isAdminTokenValue(adm)) { + return NextResponse.json({ error: 'Invalid admin token' }, { status: 401 }); + } + cookies.push(buildCookie(ADM_COOKIE, adm, secure, ONE_YEAR)); + role = 'admin'; + } + + if (usr) { + const guest = await isGuestTokenValue(usr); + if (!guest) { + return NextResponse.json({ error: 'Invalid guest token' }, { status: 401 }); + } + cookies.push(buildCookie(USR_COOKIE, usr, secure, ONE_YEAR)); + if (role !== 'admin') role = 'guest'; + guestId = guest.id; + } + + if (cookies.length === 0) { + return NextResponse.json({ error: 'No token provided' }, { status: 400 }); + } + + for (const c of cookies) headers.append('Set-Cookie', c); + return NextResponse.json({ success: true, role, guestId }, { headers }); +} + +export async function GET(request: NextRequest) { + const isAdmin = verifyAdminToken(request); + const guest = await getGuestFromRequest(request); + + if (isAdmin) return NextResponse.json({ role: 'admin', guest: guest ? { id: guest.id, name: guest.name } : null }); + if (guest) return NextResponse.json({ role: 'guest', guest: { id: guest.id, name: guest.name } }); + return NextResponse.json({ role: 'none' }); +}