Clean up authentication troubleshooting artifacts
All checks were successful
Build And Push Image / docker (push) Successful in 3m1s
All checks were successful
Build And Push Image / docker (push) Successful in 3m1s
- Remove debug files: debug-login.js, LOGIN_FIX_SUMMARY.md, CUSTOM_LOGIN_IMPLEMENTATION.md - Remove sequential-thinking directory (temporary MCP setup) - Clean up verbose console logging in auth middleware - Reduce debug output in direct login API while keeping essential logs - Streamline session management logging - Update .gitignore to prevent future debug file commits - Maintain essential error logging and security logs All authentication functionality remains intact and working.
This commit is contained in:
@@ -83,18 +83,9 @@ const getClientIP = (event: any): string => {
|
||||
};
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
console.log('🔐 Direct login endpoint called at:', new Date().toISOString());
|
||||
|
||||
try {
|
||||
const { username, password, rememberMe } = await readBody(event);
|
||||
const clientIP = getClientIP(event) || 'unknown';
|
||||
|
||||
console.log('📝 Login attempt:', {
|
||||
username: username ? 'present' : 'missing',
|
||||
hasPassword: !!password,
|
||||
rememberMe,
|
||||
ip: clientIP
|
||||
});
|
||||
|
||||
// Input validation
|
||||
const validationErrors = validateLoginInput(username, password);
|
||||
@@ -127,11 +118,6 @@ export default defineEventHandler(async (event) => {
|
||||
});
|
||||
}
|
||||
|
||||
console.log('🔧 Using Keycloak config:', {
|
||||
issuer: config.keycloak.issuer,
|
||||
clientId: config.keycloak.clientId,
|
||||
hasSecret: !!config.keycloak.clientSecret
|
||||
});
|
||||
|
||||
// Direct authentication with Keycloak using Resource Owner Password Credentials flow
|
||||
const tokenResponse = await fetch(`${config.keycloak.issuer}/protocol/openid-connect/token`, {
|
||||
@@ -178,15 +164,13 @@ export default defineEventHandler(async (event) => {
|
||||
}
|
||||
|
||||
const tokens = await tokenResponse.json();
|
||||
console.log('✅ Token exchange successful');
|
||||
|
||||
// Decode the access token to see what's inside
|
||||
// Decode the access token to extract user information
|
||||
let tokenPayload = null;
|
||||
try {
|
||||
const tokenParts = tokens.access_token.split('.');
|
||||
const payload = JSON.parse(Buffer.from(tokenParts[1], 'base64').toString());
|
||||
tokenPayload = payload;
|
||||
console.log('🔍 Access token payload:', JSON.stringify(payload, null, 2));
|
||||
} catch (err) {
|
||||
console.warn('⚠️ Could not decode access token:', err);
|
||||
}
|
||||
@@ -208,7 +192,6 @@ export default defineEventHandler(async (event) => {
|
||||
}
|
||||
|
||||
const userInfo = await userResponse.json();
|
||||
console.log('✅ User info retrieved:', JSON.stringify(userInfo, null, 2));
|
||||
|
||||
// Extract groups/roles from multiple possible locations
|
||||
const extractGroups = (tokenPayload: any, userInfo: any): string[] => {
|
||||
@@ -217,19 +200,16 @@ export default defineEventHandler(async (event) => {
|
||||
// Check userInfo for groups (from userinfo endpoint)
|
||||
if (userInfo.groups && Array.isArray(userInfo.groups)) {
|
||||
allGroups.push(...userInfo.groups);
|
||||
console.log('📋 Found groups in userInfo.groups:', userInfo.groups);
|
||||
}
|
||||
|
||||
// Check userInfo for roles
|
||||
if (userInfo.roles && Array.isArray(userInfo.roles)) {
|
||||
allGroups.push(...userInfo.roles);
|
||||
console.log('📋 Found roles in userInfo.roles:', userInfo.roles);
|
||||
}
|
||||
|
||||
// Check token payload for realm_access.roles
|
||||
if (tokenPayload?.realm_access?.roles && Array.isArray(tokenPayload.realm_access.roles)) {
|
||||
allGroups.push(...tokenPayload.realm_access.roles);
|
||||
console.log('📋 Found roles in token realm_access.roles:', tokenPayload.realm_access.roles);
|
||||
}
|
||||
|
||||
// Check token payload for resource_access roles
|
||||
@@ -238,7 +218,6 @@ export default defineEventHandler(async (event) => {
|
||||
const clientRoles = tokenPayload.resource_access[clientId]?.roles;
|
||||
if (clientRoles && Array.isArray(clientRoles)) {
|
||||
allGroups.push(...clientRoles);
|
||||
console.log(`📋 Found roles in token resource_access.${clientId}.roles:`, clientRoles);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -246,7 +225,6 @@ export default defineEventHandler(async (event) => {
|
||||
// Check token payload for groups claim
|
||||
if (tokenPayload?.groups && Array.isArray(tokenPayload.groups)) {
|
||||
allGroups.push(...tokenPayload.groups);
|
||||
console.log('📋 Found groups in token.groups:', tokenPayload.groups);
|
||||
}
|
||||
|
||||
// Remove duplicates and filter out default Keycloak roles
|
||||
@@ -254,22 +232,17 @@ export default defineEventHandler(async (event) => {
|
||||
!['default-roles-monacousa', 'offline_access', 'uma_authorization'].includes(group)
|
||||
);
|
||||
|
||||
console.log('📋 Final extracted groups:', uniqueGroups);
|
||||
return uniqueGroups;
|
||||
};
|
||||
|
||||
// Tier determination logic - admin > board > user priority
|
||||
const determineTier = (groups: string[]): 'user' | 'board' | 'admin' => {
|
||||
console.log('🎯 Determining tier from groups:', groups);
|
||||
if (groups.includes('admin')) {
|
||||
console.log('🎯 User has admin tier');
|
||||
return 'admin';
|
||||
}
|
||||
if (groups.includes('board')) {
|
||||
console.log('🎯 User has board tier');
|
||||
return 'board';
|
||||
}
|
||||
console.log('🎯 User has default user tier');
|
||||
return 'user'; // Default tier
|
||||
};
|
||||
|
||||
@@ -301,12 +274,6 @@ export default defineEventHandler(async (event) => {
|
||||
lastActivity: Date.now()
|
||||
};
|
||||
|
||||
console.log('📊 Session data size check:', {
|
||||
userTier,
|
||||
groupCount: userGroups.length,
|
||||
sessionSize: JSON.stringify(sessionData).length
|
||||
});
|
||||
|
||||
// Create session with server-side storage
|
||||
const sessionManager = createSessionManager();
|
||||
|
||||
@@ -318,9 +285,6 @@ export default defineEventHandler(async (event) => {
|
||||
const cookieParts = cookieString.split(';')[0].split('=');
|
||||
const sessionId = cookieParts[1];
|
||||
|
||||
console.log(`🍪 Setting session cookie (Remember Me: ${!!rememberMe}), session ID: ${sessionId.substring(0, 8)}...`);
|
||||
console.log(`📏 Cookie size: ${sessionId.length} chars (much smaller!)`);
|
||||
|
||||
// Set the cookie using Nuxt's setCookie helper
|
||||
const maxAge = !!rememberMe ? 60 * 60 * 24 * 30 : 60 * 60 * 24 * 7; // 30 days vs 7 days
|
||||
setCookie(event, 'monacousa-session', sessionId, {
|
||||
@@ -331,8 +295,6 @@ export default defineEventHandler(async (event) => {
|
||||
path: '/',
|
||||
});
|
||||
|
||||
console.log('✅ Session cookie set successfully');
|
||||
|
||||
} catch (cookieError) {
|
||||
console.error('❌ Failed to set session cookie:', cookieError);
|
||||
throw createError({
|
||||
@@ -345,8 +307,6 @@ export default defineEventHandler(async (event) => {
|
||||
clearFailedAttempts(clientIP);
|
||||
|
||||
console.log('✅ Login successful for user:', userInfo.email);
|
||||
console.log('🎯 User tier assigned:', userTier);
|
||||
console.log('📋 User groups assigned:', userGroups);
|
||||
|
||||
// Add a small delay to ensure cookie is set
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
@@ -355,8 +315,6 @@ export default defineEventHandler(async (event) => {
|
||||
setResponseStatus(event, 200);
|
||||
setHeader(event, 'Content-Type', 'application/json');
|
||||
|
||||
console.log('📤 Sending success response');
|
||||
|
||||
// Return a minimal response to prevent 502 errors
|
||||
return {
|
||||
success: true,
|
||||
|
||||
@@ -12,12 +12,16 @@ const sessionStore = new Map<string, {
|
||||
// Cleanup expired sessions every 5 minutes
|
||||
setInterval(() => {
|
||||
const now = Date.now();
|
||||
let cleanedCount = 0;
|
||||
for (const [sessionId, session] of sessionStore.entries()) {
|
||||
if (now > session.expiresAt) {
|
||||
sessionStore.delete(sessionId);
|
||||
console.log('🧹 Cleaned up expired session:', sessionId.substring(0, 8) + '...');
|
||||
cleanedCount++;
|
||||
}
|
||||
}
|
||||
if (cleanedCount > 0) {
|
||||
console.log(`🧹 Cleaned up ${cleanedCount} expired sessions`);
|
||||
}
|
||||
}, 5 * 60 * 1000);
|
||||
|
||||
export class SessionManager {
|
||||
@@ -43,9 +47,6 @@ export class SessionManager {
|
||||
rememberMe
|
||||
});
|
||||
|
||||
console.log(`🍪 Creating session cookie (Remember Me: ${rememberMe}) with session ID: ${sessionId.substring(0, 8)}...`);
|
||||
console.log(`📊 Session store size: ${sessionStore.size} sessions`);
|
||||
|
||||
return serialize(this.cookieName, sessionId, {
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
@@ -57,7 +58,6 @@ export class SessionManager {
|
||||
|
||||
getSession(cookieHeader?: string): SessionData | null {
|
||||
if (!cookieHeader) {
|
||||
console.log('❌ No cookie header provided');
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -65,21 +65,16 @@ export class SessionManager {
|
||||
const sessionId = cookies[this.cookieName];
|
||||
|
||||
if (!sessionId) {
|
||||
console.log('❌ No session cookie found');
|
||||
return null;
|
||||
}
|
||||
|
||||
console.log(`🔍 Looking up session: ${sessionId.substring(0, 8)}...`);
|
||||
|
||||
const sessionEntry = sessionStore.get(sessionId);
|
||||
if (!sessionEntry) {
|
||||
console.log('❌ Session not found in store');
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if session is expired
|
||||
if (Date.now() > sessionEntry.expiresAt) {
|
||||
console.log('❌ Session expired, removing from store');
|
||||
sessionStore.delete(sessionId);
|
||||
return null;
|
||||
}
|
||||
@@ -87,7 +82,6 @@ export class SessionManager {
|
||||
// Update last activity
|
||||
sessionEntry.data.lastActivity = Date.now();
|
||||
|
||||
console.log('✅ Session found and valid for user:', sessionEntry.data.user.email);
|
||||
return sessionEntry.data;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user