Usar Contexto para Autenticación y Autorización

Video
25 min~4 min lectura

Reproductor de video

Concepto clave

El contexto en GraphQL es un objeto que se pasa a todos los resolvers durante la ejecución de una operación. Piensa en el contexto como el "equipaje de mano" que cada resolver lleva consigo durante todo el viaje de una solicitud GraphQL. A diferencia de los argumentos, que son específicos para cada campo, el contexto es compartido globalmente.

En el mundo real, imagina que estás en un hotel: el contexto sería tu llave de habitación. Con ella, puedes acceder a áreas restringidas (autorización) y el personal sabe quién eres (autenticación). Sin ella, solo puedes usar las áreas públicas. En GraphQL, usamos el contexto principalmente para dos propósitos: autenticación (verificar quién es el usuario) y autorización (determinar qué puede hacer ese usuario).

Cómo funciona en la práctica

En Apollo Server con Next.js, configuramos el contexto en la creación del servidor. Este contexto se genera por cada solicitud, permitiéndote inyectar datos como tokens de autenticación, conexiones a bases de datos, o servicios externos. Aquí un ejemplo paso a paso:

  1. Configura Apollo Server en tu API route de Next.js (ejemplo: /pages/api/graphql.js).
  2. Define una función de contexto que extraiga el token del header de la solicitud HTTP.
  3. Verifica el token usando un servicio como JWT (JSON Web Token).
  4. Adjunta el usuario autenticado al objeto contexto.
  5. En tus resolvers, accede al contexto para tomar decisiones de autorización.

Ejemplo de código básico:

const server = new ApolloServer({
  typeDefs,
  resolvers,
  context: async ({ req }) => {
    const token = req.headers.authorization || '';
    const user = await verifyToken(token);
    return { user };
  }
});

Caso de estudio

Imagina que estás construyendo una API para un sistema de blogs. Tienes dos tipos de usuarios: lectores (pueden ver posts) y editores (pueden crear y editar posts). Usaremos contexto para manejar esto. Primero, definimos un esquema GraphQL:

type Mutation {
  createPost(title: String!, content: String!): Post
}

type Query {
  posts: [Post]
}

Luego, en el resolver de createPost, verificamos el contexto:

Mutation: {
  createPost: async (parent, args, context) => {
    if (!context.user) {
      throw new Error('No autenticado');
    }
    if (context.user.role !== 'editor') {
      throw new Error('No autorizado');
    }
    return await createPostInDB(args.title, args.content);
  }
}

En este caso, si un usuario no está en el contexto o no tiene rol de editor, la mutación falla con un error claro. Esto previene accesos no deseados y mantiene la seguridad.

Errores comunes

  • Exponer datos sensibles en el contexto: No almacenes contraseñas o claves privadas directamente. Usa tokens o referencias.
  • No validar el contexto en cada resolver relevante: Asumir que un resolver anterior ya hizo la validación puede llevar a vulnerabilidades. Siempre verifica en el punto de uso.
  • Usar contexto para datos volátiles o de sesión de corta duración: El contexto es por solicitud, no para estado persistente. Para eso, usa bases de datos o caché.
  • Ignorar el manejo de errores en la función de contexto: Si la autenticación falla, debes manejarlo graciosamente, no crashear el servidor.
  • Sobrecargar el contexto con demasiados datos: Mantenlo ligero; solo incluye lo necesario para autenticación y autorización.

Checklist de dominio

  1. Configurar Apollo Server con una función de contexto que extraiga tokens de headers HTTP.
  2. Implementar lógica de autenticación (ej., verificar JWT) y adjuntar usuario al contexto.
  3. Usar el contexto en resolvers para verificar autorización basada en roles o permisos.
  4. Manejar errores de autenticación/autorización con mensajes claros en GraphQL.
  5. Probar la API con diferentes usuarios (autenticados vs. no autenticados, diferentes roles).
  6. Optimizar el contexto para no incluir datos innecesarios que afecten el rendimiento.
  7. Documentar los requisitos de contexto para los consumidores de la API.

Implementar autenticacion y autorizacion en una API de tareas

En este ejercicio, practicaras el uso de contexto para proteger una API GraphQL de tareas. Sigue estos pasos:

  1. Crea un nuevo proyecto Next.js con Apollo Server si no tienes uno.
  2. Define un esquema GraphQL con tipos Task (id, title, description, userId) y mutaciones como createTask y deleteTask.
  3. Configura Apollo Server con una funcion de contexto que simule autenticacion: extrae un header Authorization con un token simple (ej., "user123") y asigna un usuario al contexto.
  4. Implementa resolvers para las mutaciones que verifiquen:
    • Para createTask: el usuario debe estar autenticado (contexto tiene usuario).
    • Para deleteTask: solo el dueno de la tarea (comparar userId en la tarea con contexto.user.id) puede eliminarla.
  5. Prueba la API usando una herramienta como GraphQL Playground o Insomnia, enviando headers con y sin token.
Pistas
  • Usa un objeto simple para simular usuarios, ej., { id: 'user123', role: 'user' } en el contexto.
  • En la mutacion deleteTask, primero recupera la tarea de la base de datos simulada para obtener su userId antes de verificar.

Evalua tu comprension

Completa el quiz interactivo de arriba para ganar XP.