BREAKING CHANGE: Auth routes moved from /auth/* to /api/auth/* - Move server/routes/auth/ to server/api/auth/ - Update login.vue to use /api/auth/authentik - Update UserMenu.vue to use /api/auth/logout - Remove old server/routes/ structure - server/api/ is better supported in Nuxt 4 IMPORTANT: Update these in Gitea: - Variable NUXT_OAUTH_AUTHENTIK_REDIRECT_URL to: https://seguidordelotes.nucleoriofrio.com/api/auth/authentik - Update Authentik redirect URI to: https://seguidordelotes.nucleoriofrio.com/api/auth/authentik
93 lines
2.7 KiB
TypeScript
93 lines
2.7 KiB
TypeScript
import { getQuery } from 'h3'
|
|
import { withQuery } from 'ufo'
|
|
|
|
/**
|
|
* OAuth Authentik Login Handler
|
|
* Ruta: /api/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=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)
|
|
})
|