feat: improve login process with enhanced session handling and error management
Build And Push Image / docker (push) Successful in 2m55s
Details
Build And Push Image / docker (push) Successful in 2m55s
Details
This commit is contained in:
parent
1b2ce79919
commit
98ef466022
|
|
@ -45,15 +45,36 @@ export const useAuth = () => {
|
||||||
user?: User;
|
user?: User;
|
||||||
}>('/api/auth/direct-login', {
|
}>('/api/auth/direct-login', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: credentials
|
body: credentials,
|
||||||
|
timeout: 30000 // 30 second timeout
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('✅ Login response received:', response);
|
console.log('✅ Login response received:', response);
|
||||||
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
|
// Add a small delay to ensure cookie is set before checking session
|
||||||
|
console.log('⏳ Waiting for cookie to be set...');
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 200));
|
||||||
|
|
||||||
// After successful login, get the user data from the session
|
// After successful login, get the user data from the session
|
||||||
console.log('🔄 Getting user data from session...');
|
console.log('🔄 Getting user data from session...');
|
||||||
const sessionSuccess = await checkAuth();
|
|
||||||
|
// Try multiple times in case of timing issues
|
||||||
|
let sessionSuccess = false;
|
||||||
|
let attempts = 0;
|
||||||
|
const maxAttempts = 3;
|
||||||
|
|
||||||
|
while (!sessionSuccess && attempts < maxAttempts) {
|
||||||
|
attempts++;
|
||||||
|
console.log(`🔄 Session check attempt ${attempts}/${maxAttempts}`);
|
||||||
|
|
||||||
|
sessionSuccess = await checkAuth();
|
||||||
|
|
||||||
|
if (!sessionSuccess && attempts < maxAttempts) {
|
||||||
|
console.log('⏳ Session not ready, waiting 500ms...');
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 500));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (sessionSuccess) {
|
if (sessionSuccess) {
|
||||||
console.log('👤 User data retrieved from session:', user.value);
|
console.log('👤 User data retrieved from session:', user.value);
|
||||||
|
|
@ -65,7 +86,9 @@ export const useAuth = () => {
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} else {
|
} else {
|
||||||
console.warn('❌ Failed to get user data from session after login');
|
console.warn('❌ Failed to get user data from session after login');
|
||||||
return { success: false, error: 'Login succeeded but failed to get user data' };
|
// Still redirect since login was successful on server
|
||||||
|
await navigateTo('/dashboard');
|
||||||
|
return { success: true };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,8 +96,24 @@ export const useAuth = () => {
|
||||||
return { success: false, error: 'Login failed' };
|
return { success: false, error: 'Login failed' };
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.error('❌ Login error caught:', err);
|
console.error('❌ Login error caught:', err);
|
||||||
error.value = err.data?.message || err.message || 'Login failed';
|
|
||||||
return { success: false, error: error.value };
|
// Handle different types of errors
|
||||||
|
let errorMessage = 'Login failed';
|
||||||
|
|
||||||
|
if (err.status === 502) {
|
||||||
|
errorMessage = 'Server temporarily unavailable. Please try again.';
|
||||||
|
} else if (err.status === 401) {
|
||||||
|
errorMessage = 'Invalid username or password';
|
||||||
|
} else if (err.status === 429) {
|
||||||
|
errorMessage = 'Too many login attempts. Please try again later.';
|
||||||
|
} else if (err.data?.message) {
|
||||||
|
errorMessage = err.data.message;
|
||||||
|
} else if (err.message) {
|
||||||
|
errorMessage = err.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
error.value = errorMessage;
|
||||||
|
return { success: false, error: errorMessage };
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -276,7 +276,10 @@ export default defineEventHandler(async (event) => {
|
||||||
// Extract groups from all possible sources
|
// Extract groups from all possible sources
|
||||||
const extractedGroups = extractGroups(tokenPayload, userInfo);
|
const extractedGroups = extractGroups(tokenPayload, userInfo);
|
||||||
|
|
||||||
// Create session data with extended expiry if remember me
|
// Create simplified session data to reduce cookie size
|
||||||
|
const userTier = determineTier(extractedGroups);
|
||||||
|
const userGroups = extractedGroups.length > 0 ? extractedGroups.slice(0, 10) : ['user']; // Limit groups to prevent large cookies
|
||||||
|
|
||||||
const sessionData = {
|
const sessionData = {
|
||||||
user: {
|
user: {
|
||||||
id: userInfo.sub,
|
id: userInfo.sub,
|
||||||
|
|
@ -285,8 +288,8 @@ export default defineEventHandler(async (event) => {
|
||||||
firstName: userInfo.given_name,
|
firstName: userInfo.given_name,
|
||||||
lastName: userInfo.family_name,
|
lastName: userInfo.family_name,
|
||||||
username: userInfo.preferred_username || username,
|
username: userInfo.preferred_username || username,
|
||||||
tier: determineTier(extractedGroups),
|
tier: userTier,
|
||||||
groups: extractedGroups.length > 0 ? extractedGroups : ['user']
|
groups: userGroups
|
||||||
},
|
},
|
||||||
tokens: {
|
tokens: {
|
||||||
accessToken: tokens.access_token,
|
accessToken: tokens.access_token,
|
||||||
|
|
@ -298,37 +301,67 @@ export default defineEventHandler(async (event) => {
|
||||||
lastActivity: Date.now()
|
lastActivity: Date.now()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log('📊 Session data size check:', {
|
||||||
|
userTier,
|
||||||
|
groupCount: userGroups.length,
|
||||||
|
sessionSize: JSON.stringify(sessionData).length
|
||||||
|
});
|
||||||
|
|
||||||
// Create session with appropriate expiration
|
// Create session with appropriate expiration
|
||||||
const sessionManager = createSessionManager();
|
const sessionManager = createSessionManager();
|
||||||
const maxAge = !!rememberMe ? 60 * 60 * 24 * 30 : 60 * 60 * 24 * 7; // 30 days vs 7 days
|
const maxAge = !!rememberMe ? 60 * 60 * 24 * 30 : 60 * 60 * 24 * 7; // 30 days vs 7 days
|
||||||
|
|
||||||
// Create the encrypted session data
|
try {
|
||||||
const sessionData_json = JSON.stringify(sessionData);
|
// Create the encrypted session data
|
||||||
const encrypted = sessionManager.encrypt(sessionData_json);
|
const sessionData_json = JSON.stringify(sessionData);
|
||||||
|
const encrypted = sessionManager.encrypt(sessionData_json);
|
||||||
console.log(`🍪 Setting session cookie (Remember Me: ${!!rememberMe}) without explicit domain`);
|
|
||||||
|
console.log(`🍪 Setting session cookie (Remember Me: ${!!rememberMe}), size: ${encrypted.length} chars`);
|
||||||
// Use Nuxt's setCookie helper directly with the encrypted value
|
|
||||||
setCookie(event, 'monacousa-session', encrypted, {
|
// Use Nuxt's setCookie helper directly with the encrypted value
|
||||||
httpOnly: true,
|
setCookie(event, 'monacousa-session', encrypted, {
|
||||||
secure: process.env.NODE_ENV === 'production',
|
httpOnly: true,
|
||||||
sameSite: 'lax',
|
secure: process.env.NODE_ENV === 'production',
|
||||||
maxAge,
|
sameSite: 'lax',
|
||||||
path: '/',
|
maxAge,
|
||||||
});
|
path: '/',
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('✅ Session cookie set successfully');
|
||||||
|
|
||||||
|
} catch (cookieError) {
|
||||||
|
console.error('❌ Failed to set session cookie:', cookieError);
|
||||||
|
throw createError({
|
||||||
|
statusCode: 500,
|
||||||
|
statusMessage: 'Failed to create session'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Clear failed attempts on successful login
|
// Clear failed attempts on successful login
|
||||||
clearFailedAttempts(clientIP);
|
clearFailedAttempts(clientIP);
|
||||||
|
|
||||||
console.log('✅ Login successful for user:', userInfo.email);
|
console.log('✅ Login successful for user:', userInfo.email);
|
||||||
|
console.log('🎯 User tier assigned:', userTier);
|
||||||
|
console.log('📋 User groups assigned:', userGroups);
|
||||||
|
|
||||||
// Ensure we return a proper response with status
|
// Add a small delay to ensure cookie is set
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 100));
|
||||||
|
|
||||||
|
// Ensure we return a proper response with explicit status
|
||||||
setResponseStatus(event, 200);
|
setResponseStatus(event, 200);
|
||||||
|
setHeader(event, 'Content-Type', 'application/json');
|
||||||
|
|
||||||
|
console.log('📤 Sending success response');
|
||||||
|
|
||||||
// Return a minimal response to prevent 502 errors
|
// Return a minimal response to prevent 502 errors
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
redirectTo: '/dashboard'
|
redirectTo: '/dashboard',
|
||||||
|
user: {
|
||||||
|
email: userInfo.email,
|
||||||
|
name: userInfo.name,
|
||||||
|
tier: userTier
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,39 @@
|
||||||
export default defineEventHandler(async (event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
const sessionManager = createSessionManager();
|
console.log('🔍 Session check requested at:', new Date().toISOString());
|
||||||
const cookieHeader = getHeader(event, 'cookie');
|
|
||||||
const session = sessionManager.getSession(cookieHeader);
|
try {
|
||||||
|
const sessionManager = createSessionManager();
|
||||||
|
const cookieHeader = getHeader(event, 'cookie');
|
||||||
|
|
||||||
|
console.log('🍪 Cookie header present:', !!cookieHeader);
|
||||||
|
console.log('🍪 Cookie header length:', cookieHeader?.length || 0);
|
||||||
|
|
||||||
|
const session = sessionManager.getSession(cookieHeader);
|
||||||
|
|
||||||
if (!session) {
|
if (!session) {
|
||||||
|
console.log('❌ No valid session found');
|
||||||
|
return {
|
||||||
|
authenticated: false,
|
||||||
|
user: null,
|
||||||
|
groups: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('✅ Valid session found for user:', session.user.email);
|
||||||
|
console.log('🎯 User tier:', session.user.tier);
|
||||||
|
console.log('📋 User groups:', session.user.groups);
|
||||||
|
|
||||||
|
return {
|
||||||
|
authenticated: true,
|
||||||
|
user: session.user,
|
||||||
|
groups: session.user.groups || [],
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Session check error:', error);
|
||||||
return {
|
return {
|
||||||
authenticated: false,
|
authenticated: false,
|
||||||
user: null,
|
user: null,
|
||||||
groups: [],
|
groups: [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
|
||||||
authenticated: true,
|
|
||||||
user: session.user,
|
|
||||||
groups: session.user.groups || [],
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue