2025-11-10 09:38:59 +09:00
|
|
|
import { NextResponse } from 'next/server';
|
|
|
|
|
import type { NextRequest } from 'next/server';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Auth Check Route Handler
|
|
|
|
|
*
|
|
|
|
|
* Purpose:
|
|
|
|
|
* - Check if user is authenticated (HttpOnly cookie validation)
|
|
|
|
|
* - Prevent browser back button cache issues
|
|
|
|
|
* - Real-time authentication validation
|
|
|
|
|
*/
|
|
|
|
|
export async function GET(request: NextRequest) {
|
|
|
|
|
try {
|
2025-11-10 17:25:56 +09:00
|
|
|
// Get tokens from HttpOnly cookies
|
|
|
|
|
const accessToken = request.cookies.get('access_token')?.value;
|
|
|
|
|
const refreshToken = request.cookies.get('refresh_token')?.value;
|
2025-11-10 09:38:59 +09:00
|
|
|
|
2025-11-10 17:25:56 +09:00
|
|
|
// No tokens at all - not authenticated
|
|
|
|
|
if (!accessToken && !refreshToken) {
|
2025-11-10 09:38:59 +09:00
|
|
|
return NextResponse.json(
|
|
|
|
|
{ error: 'Not authenticated', authenticated: false },
|
|
|
|
|
{ status: 401 }
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-10 17:25:56 +09:00
|
|
|
// Has access token - authenticated
|
|
|
|
|
if (accessToken) {
|
|
|
|
|
return NextResponse.json(
|
|
|
|
|
{ authenticated: true },
|
|
|
|
|
{ status: 200 }
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Only has refresh token - try to refresh
|
|
|
|
|
if (refreshToken && !accessToken) {
|
|
|
|
|
console.log('🔄 Access token missing, attempting refresh...');
|
|
|
|
|
|
|
|
|
|
// Attempt token refresh
|
|
|
|
|
try {
|
|
|
|
|
const refreshResponse = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/v1/refresh`, {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
'Accept': 'application/json',
|
|
|
|
|
'Authorization': `Bearer ${refreshToken}`,
|
|
|
|
|
'X-API-KEY': process.env.NEXT_PUBLIC_API_KEY || '',
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (refreshResponse.ok) {
|
|
|
|
|
const data = await refreshResponse.json();
|
|
|
|
|
|
|
|
|
|
// Set new tokens
|
|
|
|
|
const accessTokenCookie = [
|
|
|
|
|
`access_token=${data.access_token}`,
|
|
|
|
|
'HttpOnly',
|
|
|
|
|
'Secure',
|
|
|
|
|
'SameSite=Strict',
|
|
|
|
|
'Path=/',
|
|
|
|
|
`Max-Age=${data.expires_in || 7200}`,
|
|
|
|
|
].join('; ');
|
|
|
|
|
|
|
|
|
|
const refreshTokenCookie = [
|
|
|
|
|
`refresh_token=${data.refresh_token}`,
|
|
|
|
|
'HttpOnly',
|
|
|
|
|
'Secure',
|
|
|
|
|
'SameSite=Strict',
|
|
|
|
|
'Path=/',
|
|
|
|
|
'Max-Age=604800',
|
|
|
|
|
].join('; ');
|
|
|
|
|
|
|
|
|
|
console.log('✅ Token auto-refreshed in auth check');
|
|
|
|
|
|
|
|
|
|
const response = NextResponse.json(
|
|
|
|
|
{ authenticated: true, refreshed: true },
|
|
|
|
|
{ status: 200 }
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
response.headers.append('Set-Cookie', accessTokenCookie);
|
|
|
|
|
response.headers.append('Set-Cookie', refreshTokenCookie);
|
|
|
|
|
|
|
|
|
|
return response;
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Token refresh failed in auth check:', error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Refresh failed - not authenticated
|
|
|
|
|
return NextResponse.json(
|
|
|
|
|
{ error: 'Token refresh failed', authenticated: false },
|
|
|
|
|
{ status: 401 }
|
|
|
|
|
);
|
|
|
|
|
}
|
2025-11-10 09:38:59 +09:00
|
|
|
|
2025-11-10 17:25:56 +09:00
|
|
|
// Fallback - not authenticated
|
2025-11-10 09:38:59 +09:00
|
|
|
return NextResponse.json(
|
2025-11-10 17:25:56 +09:00
|
|
|
{ error: 'Not authenticated', authenticated: false },
|
|
|
|
|
{ status: 401 }
|
2025-11-10 09:38:59 +09:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Auth check error:', error);
|
|
|
|
|
return NextResponse.json(
|
|
|
|
|
{ error: 'Internal server error', authenticated: false },
|
|
|
|
|
{ status: 500 }
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|