From 2dbd2222afd2150de1371a25562b38c42393267b Mon Sep 17 00:00:00 2001 From: josedario87 Date: Sat, 11 Oct 2025 17:52:38 -0600 Subject: [PATCH] Add flat route files with dot notation - Add server/routes/auth.authentik.get.ts - Add server/routes/auth.logout.get.ts - Test if dot notation creates nested routes /auth/authentik - Keep auth/ folder as backup --- nuxt4-app/server/routes/auth.authentik.get.ts | 93 +++++++++++++++++++ nuxt4-app/server/routes/auth.logout.get.ts | 10 ++ 2 files changed, 103 insertions(+) create mode 100644 nuxt4-app/server/routes/auth.authentik.get.ts create mode 100644 nuxt4-app/server/routes/auth.logout.get.ts diff --git a/nuxt4-app/server/routes/auth.authentik.get.ts b/nuxt4-app/server/routes/auth.authentik.get.ts new file mode 100644 index 0000000..022c08c --- /dev/null +++ b/nuxt4-app/server/routes/auth.authentik.get.ts @@ -0,0 +1,93 @@ +import { getQuery } from 'h3' +import { withQuery } from 'ufo' +import { defu } from 'defu' + +/** + * OAuth Authentik Login Handler + * Ruta: /auth/authentik + * + * Este endpoint inicia el flujo OAuth con Authentik + */ +export default defineEventHandler(async (event) => { + const runtimeConfig = useRuntimeConfig(event) + const query = getQuery(event) + + // Configuración de Authentik + const config = { + clientId: runtimeConfig.oauth.authentik.clientId, + clientSecret: runtimeConfig.oauth.authentik.clientSecret, + serverUrl: runtimeConfig.oauth.authentik.serverUrl, + redirectURL: runtimeConfig.oauth.authentik.redirectURL, + scope: ['openid', 'profile', 'email'], + } + + console.log('OAuth Authentik - Iniciando flujo:', { + serverUrl: config.serverUrl, + redirectURL: config.redirectURL, + hasCode: !!query.code + }) + + // Handle OAuth callback + if (query.code) { + try { + // Exchange code for tokens + const tokenUrl = `${config.serverUrl}/application/o/token/` + const tokenResponse = await $fetch(tokenUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: new URLSearchParams({ + grant_type: 'authorization_code', + client_id: config.clientId, + client_secret: config.clientSecret, + code: query.code as string, + redirect_uri: config.redirectURL, + }), + }) + + const tokens = tokenResponse as any + + // Get user info + const userInfoUrl = `${config.serverUrl}/application/o/userinfo/` + const user = await $fetch(userInfoUrl, { + headers: { + Authorization: `Bearer ${tokens.access_token}`, + }, + }) + + // Guardar información del usuario en la sesión + await setUserSession(event, { + user: { + id: (user as any).sub, + email: (user as any).email, + name: (user as any).name || (user as any).preferred_username, + username: (user as any).preferred_username, + picture: (user as any).picture, + groups: (user as any).groups || [] + }, + loggedInAt: Date.now() + }) + + // Redirigir al dashboard después del login + return sendRedirect(event, '/') + } catch (error: any) { + console.error('Authentik OAuth error:', error) + return sendRedirect(event, '/error?message=auth_failed') + } + } + + // Initial redirect to Authentik + const authorizationUrl = withQuery( + `${config.serverUrl}/application/o/authorize/`, + { + client_id: config.clientId, + redirect_uri: config.redirectURL, + response_type: 'code', + scope: config.scope.join(' '), + } + ) + + console.log('Redirecting to:', authorizationUrl) + return sendRedirect(event, authorizationUrl) +}) diff --git a/nuxt4-app/server/routes/auth.logout.get.ts b/nuxt4-app/server/routes/auth.logout.get.ts new file mode 100644 index 0000000..f17fc4a --- /dev/null +++ b/nuxt4-app/server/routes/auth.logout.get.ts @@ -0,0 +1,10 @@ +/** + * Logout Handler + * Ruta: /auth/logout + * + * Limpia la sesión del usuario y redirige a la página de inicio + */ +export default defineEventHandler(async (event) => { + await clearUserSession(event) + return sendRedirect(event, '/') +})