|
1 | 1 |
|
2 | | -import { auth as adminAuth } from 'firebase-admin'; |
| 2 | +import { adminAuth } from '@/lib/firebase-admin'; |
3 | 3 | import { cookies } from 'next/headers'; |
4 | 4 | import { NextRequest, NextResponse } from 'next/server'; |
5 | | -import { initAdmin } from '@/lib/firebase-admin'; |
6 | 5 |
|
7 | | -// Initialize Firebase Admin SDK |
8 | | -initAdmin(); |
| 6 | +const SESSION_COOKIE_NAME = 'session'; |
9 | 7 |
|
10 | 8 | // Define cookie options |
11 | 9 | const getCookieOptions = (expires: number) => ({ |
12 | | - name: 'session', |
| 10 | + name: SESSION_COOKIE_NAME, |
13 | 11 | value: '', |
14 | 12 | httpOnly: true, |
15 | 13 | secure: process.env.NODE_ENV === 'production', |
16 | 14 | path: '/', |
17 | 15 | expires, |
18 | 16 | }); |
19 | 17 |
|
20 | | -export async function POST(request: NextRequest, { params }: { params: { action: string[] } }) { |
21 | | - const action = params.action[0]; |
| 18 | +export async function POST(request: NextRequest) { |
| 19 | + if (!adminAuth) { |
| 20 | + return NextResponse.json({ error: 'Firebase Admin not initialized' }, { status: 500 }); |
| 21 | + } |
22 | 22 |
|
23 | | - if (action === 'login') { |
24 | | - try { |
25 | | - const { idToken } = await request.json(); |
26 | | - if (!idToken) { |
27 | | - return NextResponse.json({ error: 'idToken is required' }, { status: 400 }); |
28 | | - } |
| 23 | + try { |
| 24 | + const { idToken } = await request.json(); |
| 25 | + if (!idToken) { |
| 26 | + return NextResponse.json({ error: 'idToken is required' }, { status: 400 }); |
| 27 | + } |
29 | 28 |
|
30 | | - const expiresIn = 60 * 60 * 24 * 14 * 1000; // 14 days |
31 | | - const decodedIdToken = await adminAuth().verifyIdToken(idToken); |
32 | | - const sessionCookie = await adminAuth().createSessionCookie(idToken, { expiresIn }); |
| 29 | + const expiresIn = 60 * 60 * 24 * 14 * 1000; // 14 days |
| 30 | + const sessionCookie = await adminAuth.createSessionCookie(idToken, { expiresIn }); |
33 | 31 |
|
34 | | - const options = getCookieOptions(Date.now() + expiresIn); |
35 | | - options.value = sessionCookie; |
| 32 | + const options = getCookieOptions(Date.now() + expiresIn); |
| 33 | + options.value = sessionCookie; |
36 | 34 |
|
37 | | - cookies().set(options.name, options.value, options); |
| 35 | + cookies().set(options.name, options.value, options); |
38 | 36 |
|
39 | | - return NextResponse.json({ status: 'success' }, { status: 200 }); |
40 | | - } catch (error: any) { |
41 | | - console.error('Session login error:', error); |
42 | | - return NextResponse.json({ error: error.message }, { status: 401 }); |
| 37 | + return NextResponse.json({ status: 'success' }, { status: 200 }); |
| 38 | + } catch (error: any) { |
| 39 | + console.error('Session login error:', error); |
| 40 | + let errorMessage = 'An unexpected error occurred.'; |
| 41 | + if (error.code === 'auth/id-token-revoked') { |
| 42 | + errorMessage = 'The ID token has been revoked. Please re-authenticate.'; |
| 43 | + } else if (error.code === 'auth/argument-error') { |
| 44 | + errorMessage = 'Invalid ID token provided.'; |
43 | 45 | } |
| 46 | + return NextResponse.json({ error: errorMessage }, { status: 401 }); |
44 | 47 | } |
45 | | - |
46 | | - return NextResponse.json({ error: 'Invalid action' }, { status: 400 }); |
47 | 48 | } |
48 | 49 |
|
49 | | -export async function GET(request: NextRequest, { params }: { params: { action: string[] } }) { |
50 | | - const action = params.action[0]; |
51 | | - |
52 | | - if (action === 'logout') { |
53 | | - try { |
54 | | - const sessionCookie = cookies().get('session')?.value; |
55 | | - if (sessionCookie) { |
56 | | - const decodedClaims = await adminAuth().verifySessionCookie(sessionCookie).catch(() => null); |
57 | | - if (decodedClaims) { |
58 | | - await adminAuth().revokeRefreshTokens(decodedClaims.sub); |
59 | | - } |
60 | | - } |
61 | | - |
62 | | - const options = getCookieOptions(0); // Expire the cookie |
63 | | - cookies().set(options.name, '', options); |
| 50 | +export async function GET(request: NextRequest) { |
| 51 | + if (!adminAuth) { |
| 52 | + return NextResponse.json({ error: 'Firebase Admin not initialized' }, { status: 500 }); |
| 53 | + } |
64 | 54 |
|
65 | | - return NextResponse.json({ status: 'success' }, { status: 200 }); |
66 | | - } catch (error: any) { |
67 | | - console.error('Session logout error:', error); |
68 | | - return NextResponse.json({ error: error.message }, { status: 500 }); |
| 55 | + try { |
| 56 | + const sessionCookie = cookies().get(SESSION_COOKIE_NAME)?.value; |
| 57 | + if (sessionCookie) { |
| 58 | + // It's good practice to verify the cookie before revoking tokens |
| 59 | + const decodedClaims = await adminAuth.verifySessionCookie(sessionCookie).catch(() => null); |
| 60 | + if (decodedClaims) { |
| 61 | + await adminAuth.revokeRefreshTokens(decodedClaims.sub); |
69 | 62 | } |
70 | 63 | } |
71 | | - |
72 | | - return NextResponse.json({ error: 'Invalid action' }, { status: 400 }); |
| 64 | + |
| 65 | + const options = getCookieOptions(0); // Expire the cookie immediately |
| 66 | + cookies().set(options.name, '', options); |
| 67 | + |
| 68 | + return NextResponse.json({ status: 'success' }, { status: 200 }); |
| 69 | + } catch (error: any) { |
| 70 | + console.error('Session logout error:', error); |
| 71 | + return NextResponse.json({ error: 'Failed to log out.' }, { status: 500 }); |
73 | 72 | } |
| 73 | +} |
0 commit comments