export default defineEventHandler(async (event) => { try { const { token } = getQuery(event); if (!token || typeof token !== 'string') { throw createError({ statusCode: 400, statusMessage: 'Verification token is required' }); } console.log('[verify-email] Processing verification token...'); // Verify the token const { verifyEmailToken } = await import('~/server/utils/email-tokens'); const { userId, email } = await verifyEmailToken(token); // Update user verification status in Keycloak const { createKeycloakAdminClient } = await import('~/server/utils/keycloak-admin'); const keycloak = createKeycloakAdminClient(); try { await keycloak.updateUserProfile(userId, { emailVerified: true, attributes: { lastLoginDate: new Date().toISOString() } }); console.log('[verify-email] Successfully verified user:', userId, 'email:', email); // Redirect to success page return sendRedirect(event, '/auth/verify-success?email=' + encodeURIComponent(email), 302); } catch (keycloakError: any) { console.error('[verify-email] Keycloak update failed:', keycloakError.message); // Even if Keycloak update fails, consider verification successful if token was valid // This prevents user frustration due to backend issues return sendRedirect(event, '/auth/verify-success?email=' + encodeURIComponent(email) + '&warning=partial', 302); } } catch (error: any) { console.error('[verify-email] Verification failed:', error.message); // Handle different error types with appropriate redirects if (error.message?.includes('expired')) { return sendRedirect(event, '/auth/verify-expired', 302); } else if (error.message?.includes('already used') || error.message?.includes('not found')) { return sendRedirect(event, '/auth/verify-expired?reason=used', 302); } else { // For other errors, show a generic error page throw createError({ statusCode: 400, statusMessage: error.message || 'Invalid verification link' }); } } });