2025-06-15 16:13:22 +02:00
|
|
|
/**
|
2025-06-15 17:37:14 +02:00
|
|
|
* Check if the request is authenticated via Keycloak OIDC session
|
2025-06-15 16:13:22 +02:00
|
|
|
*/
|
|
|
|
|
export const isAuthenticated = async (event: any): Promise<boolean> => {
|
2025-06-15 17:37:14 +02:00
|
|
|
console.log('[auth] Checking authentication for:', event.node.req.url);
|
2025-06-15 17:03:42 +02:00
|
|
|
|
2025-06-15 16:58:45 +02:00
|
|
|
// Check OIDC session authentication
|
2025-06-15 16:13:22 +02:00
|
|
|
try {
|
2025-06-15 16:58:45 +02:00
|
|
|
const oidcSession = getCookie(event, 'nuxt-oidc-auth');
|
2025-06-15 17:37:14 +02:00
|
|
|
console.log('[auth] OIDC session cookie:', oidcSession ? 'present' : 'not found');
|
2025-06-15 17:06:01 +02:00
|
|
|
|
2025-06-15 17:37:14 +02:00
|
|
|
if (!oidcSession) {
|
|
|
|
|
console.log('[auth] No OIDC session found');
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Parse and validate session data
|
|
|
|
|
let sessionData;
|
|
|
|
|
try {
|
|
|
|
|
sessionData = JSON.parse(oidcSession);
|
|
|
|
|
} catch (parseError) {
|
|
|
|
|
console.error('[auth] Failed to parse session cookie:', parseError);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Validate session structure
|
|
|
|
|
if (!sessionData.user || !sessionData.accessToken) {
|
|
|
|
|
console.error('[auth] Invalid session structure:', {
|
|
|
|
|
hasUser: !!sessionData.user,
|
|
|
|
|
hasAccessToken: !!sessionData.accessToken
|
|
|
|
|
});
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if session is still valid
|
|
|
|
|
if (sessionData.expiresAt && Date.now() > sessionData.expiresAt) {
|
|
|
|
|
console.log('[auth] Session expired:', {
|
|
|
|
|
expiresAt: sessionData.expiresAt,
|
|
|
|
|
currentTime: Date.now(),
|
|
|
|
|
expiredSince: Date.now() - sessionData.expiresAt
|
|
|
|
|
});
|
|
|
|
|
return false;
|
2025-06-15 16:13:22 +02:00
|
|
|
}
|
2025-06-15 17:37:14 +02:00
|
|
|
|
|
|
|
|
console.log('[auth] Valid OIDC session found for user:', {
|
|
|
|
|
id: sessionData.user.id,
|
|
|
|
|
email: sessionData.user.email
|
|
|
|
|
});
|
|
|
|
|
return true;
|
|
|
|
|
|
2025-06-15 16:13:22 +02:00
|
|
|
} catch (error) {
|
2025-06-15 17:37:14 +02:00
|
|
|
console.error('[auth] OIDC session check failed:', error);
|
|
|
|
|
return false;
|
2025-06-15 16:13:22 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const requireAuth = async (event: any) => {
|
|
|
|
|
const authenticated = await isAuthenticated(event);
|
|
|
|
|
if (!authenticated) {
|
2025-06-15 16:53:20 +02:00
|
|
|
console.log('[requireAuth] Authentication failed for:', event.node.req.url);
|
|
|
|
|
console.log('[requireAuth] Available cookies:', Object.keys(event.node.req.headers.cookie ? parseCookies(event.node.req.headers.cookie) : {}));
|
2025-06-15 16:13:22 +02:00
|
|
|
throw createError({
|
|
|
|
|
statusCode: 401,
|
2025-06-15 17:37:14 +02:00
|
|
|
statusMessage: "Authentication required. Please login with Keycloak."
|
2025-06-15 16:13:22 +02:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-06-15 16:53:20 +02:00
|
|
|
|
2025-06-15 17:37:14 +02:00
|
|
|
/**
|
|
|
|
|
* Get the authenticated user from the session
|
|
|
|
|
*/
|
|
|
|
|
export const getAuthenticatedUser = async (event: any): Promise<any | null> => {
|
|
|
|
|
try {
|
|
|
|
|
const oidcSession = getCookie(event, 'nuxt-oidc-auth');
|
|
|
|
|
|
|
|
|
|
if (!oidcSession) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const sessionData = JSON.parse(oidcSession);
|
|
|
|
|
|
|
|
|
|
// Validate session
|
|
|
|
|
if (!sessionData.user || !sessionData.accessToken) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if session is still valid
|
|
|
|
|
if (sessionData.expiresAt && Date.now() > sessionData.expiresAt) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return sessionData.user;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('[getAuthenticatedUser] Error:', error);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-15 16:53:20 +02:00
|
|
|
function parseCookies(cookieString: string): Record<string, string> {
|
|
|
|
|
return cookieString.split(';').reduce((cookies: Record<string, string>, cookie) => {
|
|
|
|
|
const [name, value] = cookie.trim().split('=');
|
|
|
|
|
if (name && value) {
|
|
|
|
|
cookies[name] = value;
|
|
|
|
|
}
|
|
|
|
|
return cookies;
|
|
|
|
|
}, {});
|
|
|
|
|
}
|