En este módulo, aprenderemos cómo implementar autenticación y autorización en un servidor GraphQL. Estos conceptos son fundamentales para asegurar que solo los usuarios autorizados puedan acceder a ciertos datos y realizar ciertas acciones en tu aplicación.

Conceptos Clave

Autenticación

La autenticación es el proceso de verificar la identidad de un usuario. En otras palabras, es cómo sabemos quién es el usuario. Esto generalmente se realiza mediante el uso de credenciales como nombres de usuario y contraseñas, tokens de acceso, etc.

Autorización

La autorización es el proceso de verificar si un usuario autenticado tiene permiso para realizar una acción específica o acceder a ciertos datos. Esto se basa en roles y permisos asignados al usuario.

Implementación de Autenticación y Autorización en GraphQL

  1. Configuración del Servidor

Primero, necesitamos configurar nuestro servidor GraphQL para manejar la autenticación. En este ejemplo, usaremos JSON Web Tokens (JWT) para la autenticación.

Instalación de Dependencias

npm install jsonwebtoken express express-jwt

Configuración del Middleware de Autenticación

const express = require('express');
const { ApolloServer, gql } = require('apollo-server-express');
const jwt = require('express-jwt');
const jsonwebtoken = require('jsonwebtoken');

const app = express();

const authMiddleware = jwt({
  secret: 'your_secret_key',
  credentialsRequired: false,
  algorithms: ['HS256'],
});

app.use(authMiddleware);

  1. Definición del Esquema

Definimos nuestro esquema GraphQL con un tipo User y una consulta me que devuelve la información del usuario autenticado.

const typeDefs = gql`
  type User {
    id: ID!
    username: String!
    email: String!
  }

  type Query {
    me: User
  }
`;

  1. Implementación de Resolvers

Implementamos los resolvers para manejar la lógica de negocio. En este caso, el resolver me devolverá la información del usuario autenticado.

const resolvers = {
  Query: {
    me: (parent, args, context) => {
      if (!context.user) {
        throw new Error('Not authenticated');
      }
      return context.user;
    },
  },
};

  1. Configuración del Contexto

Configuramos el contexto de Apollo Server para incluir la información del usuario autenticado.

const server = new ApolloServer({
  typeDefs,
  resolvers,
  context: ({ req }) => {
    const user = req.user || null;
    return { user };
  },
});

server.applyMiddleware({ app });

app.listen({ port: 4000 }, () =>
  console.log(`Server ready at http://localhost:4000${server.graphqlPath}`)
);

  1. Autorización Basada en Roles

Para implementar la autorización, podemos definir roles y permisos y verificar estos roles en nuestros resolvers.

Definición de Roles

const roles = {
  ADMIN: 'ADMIN',
  USER: 'USER',
};

Verificación de Roles en Resolvers

const resolvers = {
  Query: {
    me: (parent, args, context) => {
      if (!context.user) {
        throw new Error('Not authenticated');
      }
      return context.user;
    },
    adminData: (parent, args, context) => {
      if (!context.user || context.user.role !== roles.ADMIN) {
        throw new Error('Not authorized');
      }
      return { secretData: 'This is admin data' };
    },
  },
};

Ejercicio Práctico

Ejercicio 1: Implementar Autenticación

  1. Configura un servidor GraphQL con autenticación usando JWT.
  2. Define un esquema con un tipo User y una consulta me.
  3. Implementa los resolvers para manejar la autenticación y devolver la información del usuario autenticado.

Ejercicio 2: Implementar Autorización

  1. Define roles y permisos en tu aplicación.
  2. Implementa la lógica de autorización en los resolvers para restringir el acceso a ciertas consultas y mutaciones basadas en los roles del usuario.

Solución del Ejercicio 1

// Paso 1: Configuración del servidor
const express = require('express');
const { ApolloServer, gql } = require('apollo-server-express');
const jwt = require('express-jwt');
const jsonwebtoken = require('jsonwebtoken');

const app = express();

const authMiddleware = jwt({
  secret: 'your_secret_key',
  credentialsRequired: false,
  algorithms: ['HS256'],
});

app.use(authMiddleware);

// Paso 2: Definición del esquema
const typeDefs = gql`
  type User {
    id: ID!
    username: String!
    email: String!
  }

  type Query {
    me: User
  }
`;

// Paso 3: Implementación de resolvers
const resolvers = {
  Query: {
    me: (parent, args, context) => {
      if (!context.user) {
        throw new Error('Not authenticated');
      }
      return context.user;
    },
  },
};

// Paso 4: Configuración del contexto
const server = new ApolloServer({
  typeDefs,
  resolvers,
  context: ({ req }) => {
    const user = req.user || null;
    return { user };
  },
});

server.applyMiddleware({ app });

app.listen({ port: 4000 }, () =>
  console.log(`Server ready at http://localhost:4000${server.graphqlPath}`)
);

Solución del Ejercicio 2

// Paso 1: Definición de roles
const roles = {
  ADMIN: 'ADMIN',
  USER: 'USER',
};

// Paso 2: Verificación de roles en resolvers
const resolvers = {
  Query: {
    me: (parent, args, context) => {
      if (!context.user) {
        throw new Error('Not authenticated');
      }
      return context.user;
    },
    adminData: (parent, args, context) => {
      if (!context.user || context.user.role !== roles.ADMIN) {
        throw new Error('Not authorized');
      }
      return { secretData: 'This is admin data' };
    },
  },
};

Conclusión

En esta sección, hemos aprendido cómo implementar autenticación y autorización en un servidor GraphQL. La autenticación nos permite verificar la identidad de los usuarios, mientras que la autorización nos permite controlar el acceso a los recursos y acciones basados en roles y permisos. Estos conceptos son esenciales para construir aplicaciones seguras y robustas.

En el siguiente módulo, exploraremos cómo optimizar las consultas en GraphQL para mejorar el rendimiento de nuestras aplicaciones.

© Copyright 2024. Todos los derechos reservados