Autenticación
| Decisión | Opción |
|---|---|
| Librería | NextAuth v5 (next-auth@beta) |
| Providers | Google OAuth (GitHub planificado) |
| Adapter | @auth/prisma-adapter + Prisma 7 |
| Estrategia | JWT (por defecto) |
| Base de datos | Neon PostgreSQL (cloud) / Local Docker |
Estructura
Sección titulada «Estructura»lib/├── auth/│ ├── auth.ts ← Configuración de NextAuth (providers, adapter, callbacks)│ └── client.ts ← Re-export de signIn / signOut para componentes cliente├── prisma.ts ← Singleton de PrismaClient con adapter PrismaPgArchivos clave
Sección titulada «Archivos clave»| Archivo | Propósito |
|---|---|
lib/auth/auth.ts |
Configuración central de NextAuth (Google provider, PrismaAdapter, JWT strategy) |
lib/auth/client.ts |
Wrapper de signIn/signOut de next-auth/react |
lib/prisma.ts |
Singleton PrismaClient con PrismaPg adapter |
app/api/auth/[...nextauth]/route.ts |
API route de NextAuth (GET/POST) |
middleware.ts |
Solo next-intl (sin auth en edge runtime) |
Variables de entorno
Sección titulada «Variables de entorno»# .env — defaults compartidos (gitignored)DATABASE_URL="postgresql://syncro:syncro@localhost:5432/syncro?schema=public"AUTH_URL="http://localhost:3000"
# .env.local — secretos (gitignored)AUTH_SECRET="..."AUTH_GOOGLE_ID="..."AUTH_GOOGLE_SECRET="..."Para producción (Vercel + Neon)
Sección titulada «Para producción (Vercel + Neon)»En Vercel → Project Settings → Environment Variables, añadir:
DATABASE_URL="postgresql://neondb_owner:...@ep-xxx.eu-west-2.aws.neon.tech/neondb?sslmode=require"AUTH_URL="https://syncro.vercel.app"AUTH_SECRET="..."AUTH_GOOGLE_ID="..."AUTH_GOOGLE_SECRET="..."En Google Cloud Console → Credenciales → OAuth 2.0 Client ID, los Authorized redirect URIs deben incluir:
http://localhost:3000/api/auth/callback/googlehttps://syncro.vercel.app/api/auth/callback/googleFlujo de autenticación
Sección titulada «Flujo de autenticación»- Usuario hace clic en “Google” en login/register
signIn("google", { redirectTo: "/home" })redirige a Google- Google redirige a
/api/auth/callback/google - NextAuth recibe el código, intercambia por tokens, crea/encuentra usuario en DB
- Sesión JWT creada, redirige a
/home(sin locale) - Middleware de
next-intldetecta cookieNEXT_LOCALEy redirige a/[locale]/home
El locale se preserva a través del OAuth
Sección titulada «El locale se preserva a través del OAuth»- El middleware de
next-intlsetea la cookieNEXT_LOCALEal visitar cualquier página - Google OAuth redirige a
/home(sin prefijo de locale) - El middleware lee la cookie y completa la ruta:
/es/homeo/en/home
Decisiones técnicas
Sección titulada «Decisiones técnicas»| Decisión | Motivo |
|---|---|
| NextAuth vs Lucia/Clerk | Integración nativa con Prisma, OAuth out-of-the-box |
| JWT strategy vs database sessions | Más simple para solo OAuth |
| SessionProvider separado | El layout [locale] es servidor; SessionProvider necesita ser cliente |
| Sin auth en middleware | Prisma falla en edge runtime |
redirectTo: "/home" |
Separar landing (pública) de dashboard (autenticada) |
Errores comunes
Sección titulada «Errores comunes»redirect_uri_mismatch (400)
Sección titulada «redirect_uri_mismatch (400)»La URL de callback no está registrada en Google Cloud Console.
Fix: Agregar la URL completa en Google Cloud Console → Credenciales → OAuth 2.0 Client ID → “Authorized redirect URIs”.
Para local: http://localhost:3000/api/auth/callback/google
Para producción: https://syncro.vercel.app/api/auth/callback/google
Autenticación con credentials (email + contraseña)
Sección titulada «Autenticación con credentials (email + contraseña)»Además de Google OAuth, la aplicación soporta registro e inicio de sesión con email y contraseña mediante el Credentials provider de NextAuth.
Nota histórica: durante el desarrollo inicial, el
Credentialsprovider devolvía un usuario de desarrollo hardcodeado (dev@syncro.app) para que el flujo de login funcionara sin base de datos real. Actualmente se validan credenciales reales contra la base de datos.
Archivos clave
Sección titulada «Archivos clave»| Archivo | Propósito |
|---|---|
lib/auth/auth.ts |
Configuración del Credentials provider y callbacks de NextAuth |
server/user/actions/user-actions.ts |
Server action registerAccountAction con validación de Zod |
server/user/service/user-service.ts |
registerUser y verifyCredentials (hashing y verificación) |
server/user/repository/user-repository.ts |
Acceso a base de datos para usuarios |
server/workspace/service/workspace-service.ts |
Creación del workspace personal |
app/[locale]/(auth)/register/page.tsx |
Formulario de registro con auto-login |
app/[locale]/(auth)/login/page.tsx |
Formulario de login |
Decisiones técnicas
Sección titulada «Decisiones técnicas»| Decisión | Motivo |
|---|---|
bcryptjs para hashing |
No requiere compilación nativa, funciona en Windows sin herramientas adicionales y es suficiente para el MVP |
| Hashing en la capa de servicio | Mantiene la lógica de negocio fuera de la UI y las server actions |
| Sin verificación de email | Se omite en el MVP para agilizar el flujo de desarrollo. En producción se debería añadir verificación por email o magic links |
| Auto-login tras registro | Después de crear la cuenta, el cliente llama a signIn("credentials") automáticamente para evitar un paso extra al usuario |
| Normalización de email | email.toLowerCase().trim() antes de consultar o guardar en base de datos |
Flujo de registro
Sección titulada «Flujo de registro»- El usuario rellena el formulario de registro.
- La server action valida los datos con Zod v4.
- Si la validación pasa, se llama a
registerUseren el servicio. registerUserhashea la contraseña y crea el usuario dentro de una transacción de Prisma.- En la misma transacción se crea un workspace personal para el usuario.
- Si todo sale bien, el cliente hace auto-login con las credenciales recién creadas.
Validación con Zod v4
Sección titulada «Validación con Zod v4»La server action registerAccountAction usa Zod para validar:
name: no vacío, máximo 100 caracteresemail: formato válidopassword: mínimo 8 caracteresconfirmPassword: debe coincidir conpassword
Los errores de Zod se mapean a códigos (INVALID_EMAIL, PASSWORD_TOO_SHORT, etc.) que el cliente traduce a través de next-intl. Esto mantiene el schema puro y desacoplado de los mensajes de UI.
Seguridad y limitaciones conocidas
Sección titulada «Seguridad y limitaciones conocidas»- No hay rate limiting en login/register. Se recomienda añadirlo antes de producción.
- No hay verificación de email. Cualquier email válido puede registrarse sin confirmar.
- La fortaleza de la contraseña solo valida longitud mínima. En producción se debería exigir mayúsculas, números o símbolos.
- Email enumeration: el mensaje de error para email duplicado es genérico (
REGISTRATION_FAILED) para no revelar si un email ya está registrado.
Próximos pasos posibles
Sección titulada «Próximos pasos posibles»- GitHub OAuth provider
- Verificación de email (confirmación por correo o magic link)
- Rate limiting para login/register
- Role-based access control (admin, member)
- Magic link (email sin contraseña)
- Fortalecer reglas de contraseña (mayúsculas, números, símbolos)