import { NextRequest, NextResponse } from 'next/server'; import { getServerSession } from 'next-auth/next'; import { authOptions } from '../options'; /** * API endpoint to refresh Keycloak session cookies * This ensures Keycloak session is active before loading iframe applications */ export async function GET(request: NextRequest) { try { // Check if user just logged out (prevent refresh after logout) const logoutCookie = request.cookies.get('logout_in_progress'); if (logoutCookie?.value === 'true') { console.log('Logout in progress, refusing to refresh session'); return NextResponse.json( { error: 'SessionInvalidated', message: 'User is logging out. Please sign in again.' }, { status: 401 } ); } const session = await getServerSession(authOptions); if (!session?.accessToken || !session?.refreshToken) { return NextResponse.json( { error: 'No active session' }, { status: 401 } ); } // Refresh the Keycloak token to renew session cookies // This will also refresh Keycloak session cookies in the browser const keycloakIssuer = process.env.KEYCLOAK_ISSUER; const clientId = process.env.KEYCLOAK_CLIENT_ID; const clientSecret = process.env.KEYCLOAK_CLIENT_SECRET; if (!keycloakIssuer || !clientId || !clientSecret) { return NextResponse.json( { error: 'Keycloak configuration missing' }, { status: 500 } ); } // Use the refresh token to get new tokens // This will also refresh Keycloak session cookies const response = await fetch(`${keycloakIssuer}/protocol/openid-connect/token`, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: new URLSearchParams({ client_id: clientId, client_secret: clientSecret, grant_type: 'refresh_token', refresh_token: session.refreshToken as string, }), }); if (!response.ok) { const error = await response.json().catch(() => ({})); console.error('Failed to refresh Keycloak session:', error); // If token is invalid (user logged out from Keycloak), return specific error if (error.error === 'invalid_grant' || error.error_description?.includes('Token is not active') || error.error_description?.includes('Session not active')) { return NextResponse.json( { error: 'SessionInvalidated', message: 'Keycloak session was invalidated. Please sign in again.', details: error }, { status: 401 } ); } return NextResponse.json( { error: 'Failed to refresh Keycloak session', details: error }, { status: response.status } ); } const tokens = await response.json(); // Return success - the Keycloak session cookies are now refreshed // The new tokens will be stored in NextAuth on next request return NextResponse.json({ success: true, message: 'Keycloak session refreshed', }); } catch (error) { console.error('Error refreshing Keycloak session:', error); return NextResponse.json( { error: 'Internal server error' }, { status: 500 } ); } }