port-nimara-client-portal/server/api/auth/session.ts

135 lines
4.6 KiB
TypeScript

export default defineEventHandler(async (event) => {
console.log('[SESSION] Checking authentication session...')
// Check OIDC/Keycloak authentication only
try {
const oidcSessionCookie = getCookie(event, 'nuxt-oidc-auth')
if (!oidcSessionCookie) {
console.log('[SESSION] No OIDC session cookie found')
return { user: null, authenticated: false, groups: [] }
}
console.log('[SESSION] OIDC session cookie found, parsing...')
let sessionData
try {
// Parse the session data
sessionData = JSON.parse(oidcSessionCookie)
console.log('[SESSION] Session data parsed successfully:', {
hasUser: !!sessionData.user,
hasAccessToken: !!sessionData.accessToken,
hasIdToken: !!sessionData.idToken,
expiresAt: sessionData.expiresAt,
createdAt: sessionData.createdAt,
timeUntilExpiry: sessionData.expiresAt ? sessionData.expiresAt - Date.now() : 'unknown'
})
} catch (parseError) {
console.error('[SESSION] Failed to parse session cookie:', parseError)
// Clear invalid session
const cookieDomain = process.env.COOKIE_DOMAIN || '.portnimara.dev';
deleteCookie(event, 'nuxt-oidc-auth', {
domain: cookieDomain,
path: '/'
})
return { user: null, authenticated: false, groups: [] }
}
// Validate session structure
if (!sessionData.user || !sessionData.accessToken) {
console.error('[SESSION] Invalid session structure:', {
hasUser: !!sessionData.user,
hasAccessToken: !!sessionData.accessToken
})
const cookieDomain = process.env.COOKIE_DOMAIN || '.portnimara.dev';
deleteCookie(event, 'nuxt-oidc-auth', {
domain: cookieDomain,
path: '/'
})
return { user: null, authenticated: false, groups: [] }
}
// Check if session is still valid
if (sessionData.expiresAt && Date.now() > sessionData.expiresAt) {
console.log('[SESSION] Session expired:', {
expiresAt: sessionData.expiresAt,
currentTime: Date.now(),
expiredSince: Date.now() - sessionData.expiresAt
})
// Session expired, clear cookie
const cookieDomain = process.env.COOKIE_DOMAIN || '.portnimara.dev';
deleteCookie(event, 'nuxt-oidc-auth', {
domain: cookieDomain,
path: '/'
})
return { user: null, authenticated: false, groups: [] }
}
// Extract groups from ID token
let userGroups: string[] = [];
if (sessionData.idToken) {
try {
// Parse JWT payload (base64 decode the middle section)
const tokenParts = sessionData.idToken.split('.');
if (tokenParts.length >= 2) {
const payload = JSON.parse(atob(tokenParts[1]));
userGroups = payload.groups || [];
console.log('[SESSION] Groups extracted from token:', userGroups);
}
} catch (tokenError) {
console.error('[SESSION] Failed to parse ID token:', tokenError);
// Continue without groups - not a fatal error
}
}
// Also check access token for groups as fallback
if (userGroups.length === 0 && sessionData.accessToken) {
try {
const tokenParts = sessionData.accessToken.split('.');
if (tokenParts.length >= 2) {
const payload = JSON.parse(atob(tokenParts[1]));
userGroups = payload.groups || [];
console.log('[SESSION] Groups extracted from access token:', userGroups);
}
} catch (tokenError) {
console.error('[SESSION] Failed to parse access token:', tokenError);
}
}
// Default group assignment if no groups found
if (userGroups.length === 0) {
console.log('[SESSION] No groups found in token, assigning default "user" group');
userGroups = ['user'];
}
console.log('[SESSION] Valid session found for user:', {
id: sessionData.user.id,
email: sessionData.user.email,
username: sessionData.user.username,
groups: userGroups
})
return {
user: {
id: sessionData.user.id,
email: sessionData.user.email,
username: sessionData.user.username,
name: sessionData.user.name,
authMethod: sessionData.user.authMethod || 'keycloak',
groups: userGroups
},
authenticated: true,
groups: userGroups
}
} catch (error) {
console.error('[SESSION] OIDC session check error:', error)
// Clear invalid session
const cookieDomain = process.env.COOKIE_DOMAIN || '.portnimara.dev';
deleteCookie(event, 'nuxt-oidc-auth', {
domain: cookieDomain,
path: '/'
})
return { user: null, authenticated: false, groups: [] }
}
})