Sistema de Autenticación

Cannahub utiliza un sistema de autenticación avanzado basado en JWT tokens con soporte para múltiples roles de usuario y arquitectura multi-tenant. Esta guía explica cómo funciona la autenticación y cómo implementar diferentes flujos de acceso.

Arquitectura de Autenticación

Cannahub implementa un sistema de autenticación de múltiples capas que soporta diferentes tipos de usuarios y organizaciones:

Flujo de Autenticación

Loading diagram...

Tipos de Autenticación por Rol

1. Autenticación de Miembros (Customers)

Los miembros utilizan el flujo estándar de registro y login:

Login de Miembro

POST
/auth/customer/emailpass
curl -X POST https://api.cannahub.tech/auth/customer/emailpass \
  -H "Content-Type: application/json" \
  -d '{
    "email": "miembro@ejemplo.com",
    "password": "contraseña_segura"
  }'

2. Autenticación de Administradores

Los administradores y staff utilizan un endpoint separado:

Login de Admin

POST
/auth/user/emailpass
curl -X POST https://api.cannahub.tech/auth/user/emailpass \
  -H "Content-Type: application/json" \
  -d '{
    "email": "admin@club.com",
    "password": "admin_password"
  }'

Gestión de Tokens JWT

Estructura de Tokens

Cannahub utiliza dos tipos de tokens JWT almacenados como cookies HTTP-only:

Configuración de Tokens

{
  "adminToken": {
    "name": "cannahubAdminToken",
    "expires": 604800,  // 7 días en segundos
    "httpOnly": true,
    "secure": true,
    "sameSite": "lax"
  },
  "memberToken": {
    "name": "cannahubToken", 
    "expires": 604800,  // 7 días en segundos
    "httpOnly": true,
    "secure": true,
    "sameSite": "lax"
  }
}

Payload del Token

Estructura del JWT

{
  "sub": "user_id_123",
  "email": "usuario@ejemplo.com",
  "role": "member",
  "organization": "high-up",
  "iat": 1634567890,
  "exp": 1635172690
}

Roles de Usuario y Permisos

Jerarquía de Roles

{
  "root": {
    "level": 0,
    "description": "Super administrador de plataforma",
    "access": "Acceso completo a todas las funcionalidades"
  },
  "admin": {
    "level": 1,
    "description": "Administrador de club",
    "access": "Gestión de miembros, pedidos, productos y analytics"
  },
  "doctor": {
    "level": 2,
    "description": "Profesional médico",
    "access": "Gestión de pacientes, prescripciones y consultas"
  },
  "member": {
    "level": 3,
    "description": "Miembro del club",
    "access": "Acceso al dispensario, crear pedidos, actualizar perfil"
  }
}

Middleware de Protección de Rutas

El middleware de Next.js intercepta todas las solicitudes antes de que lleguen a las páginas, validando autenticación, organización y permisos.

Diagrama del Middleware

Loading diagram...

Rutas Excluidas de Autenticación

Las siguientes rutas no requieren autenticación:

Rutas Públicas

const excludedPaths = [
  '/login',
  '/register',
  '/onboarding',
  '/forgot-password',
  '/api/health',
  '/_next',
  '/favicon.ico',
  '/images',
]

Validación en el Middleware

Middleware de Autenticación

export async function middleware(request: NextRequest) {
  const { pathname } = request.nextUrl
  
  // 1. Validación de organización
  const organization = extractOrganization(request)
  if (!organization || !isValidOrganization(organization)) {
    return redirectTo404(request)
  }
  
  // 2. Extracción de tokens
  const memberToken = request.cookies.get('cannahubToken')?.value
  const adminToken = request.cookies.get('cannahubAdminToken')?.value
  
  // 3. Rutas excluidas de autenticación
  if (isExcludedPath(pathname)) {
    return NextResponse.next()
  }
  
  // 4. Validación de tokens
  const token = adminToken || memberToken
  if (!token) {
    return redirectToLogin(request, organization)
  }
  
  // 5. Verificación del perfil
  const profile = await verifyTokenAndGetProfile(token)
  if (!profile) {
    return redirectToLogin(request, organization)
  }
  
  // 6. Verificación de completitud del perfil
  if (!profile.isComplete) {
    return redirectToOnboarding(request, organization)
  }
  
  // 7. Control de acceso basado en roles
  if (!hasPermission(profile.role, pathname)) {
    return redirectToUnauthorized(request)
  }
  
  return NextResponse.next()
}

Integración Multi-Tenant

Validación de Organización

Validación de Organización

const supportedOrganizations = [
  'high-up',
  'don-marcelino', 
  'circulo-rojo',
  'superfly',
  'blow',
  'weplant'
]

function extractOrganization(request: NextRequest): string | null {
  // Extraer de subdomain, header, o path
  const host = request.headers.get('host')
  const subdomain = host?.split('.')[0]
  
  if (supportedOrganizations.includes(subdomain)) {
    return subdomain
  }
  
  // Fallback a path-based org
  const pathOrg = request.nextUrl.pathname.split('/')[1]
  return supportedOrganizations.includes(pathOrg) ? pathOrg : null
}

Seguridad y Mejores Prácticas

Características de Seguridad

  • Cookies HTTP-Only: Previenen ataques XSS al no permitir acceso desde JavaScript
  • Protección CSRF: Integrada en Next.js
  • Expiración de Tokens: Los tokens expiran después de 7 días
  • Aislamiento Multi-Tenant: Separación completa de datos por organización
  • Control de Acceso por Roles: Acceso basado en el rol del usuario

Comportamiento de Sesión

Cuando un token expira después de 7 días:

  1. El usuario es redirigido automáticamente a /login
  2. Las cookies de sesión son eliminadas
  3. El usuario debe volver a iniciar sesión para continuar

Variables de Entorno de Seguridad

Configuración de Seguridad

# JWT Configuration
JWT_SECRET=tu_clave_secreta_muy_larga_y_segura
COOKIE_DOMAIN=.tudominio.com

# Session Configuration
SESSION_TIMEOUT=604800  # 7 días en segundos

# Security Headers
FORCE_HTTPS=true
SECURE_COOKIES=true
SAME_SITE_POLICY=lax

# Development Override (NUNCA en producción)
BYPASS_AUTH=false

Manejo de Errores de Autenticación

Códigos de Error Comunes

Respuestas de Error

{
  "unauthorized": {
    "code": 401,
    "message": "Credenciales inválidas o token expirado",
    "action": "Redirigir a /login"
  },
  "forbidden": {
    "code": 403,
    "message": "No tienes permiso para acceder a este recurso",
    "action": "Mostrar página de acceso denegado"
  },
  "profile_incomplete": {
    "code": 302,
    "message": "Perfil incompleto",
    "action": "Redirigir a /onboarding"
  }
}

Testing y Desarrollo

Modo de Desarrollo

Para facilitar el desarrollo, Cannahub incluye un bypass de autenticación. Ambas variables deben estar activas para que funcione:

Variables de Desarrollo

# Solo para desarrollo local - AMBAS son requeridas
BYPASS_AUTH=true
IS_MOCKED=true

Cuando ambas están activas:

  • El middleware omite la validación de tokens
  • Se utiliza un usuario mock predefinido
  • Las rutas protegidas son accesibles sin login

Recuperación de Contraseña

Actualmente no existe un flujo de recuperación de contraseña self-service. Si un usuario olvida su contraseña:

  1. Debe contactar al administrador del club
  2. El administrador puede resetear la contraseña desde el panel de gestión de miembros
  3. El usuario recibirá instrucciones para establecer una nueva contraseña

La implementación del sistema de autenticación de Cannahub proporciona seguridad robusta mientras mantiene la flexibilidad necesaria para soportar múltiples organizaciones y roles de usuario complejos.

Was this page helpful?