En aquest tema, explorarem com implementar l'autenticació i l'autorització en un servidor GraphQL. Aquests dos conceptes són fonamentals per assegurar que només els usuaris autoritzats puguin accedir a les dades i funcionalitats de la teva aplicació.
Continguts
- Introducció a l'autenticació i autorització
- Implementació de l'autenticació
- Implementació de l'autorització
- Exemples pràctics
- Exercicis pràctics
- Introducció a l'autenticació i autorització
Autenticació
L'autenticació és el procés de verificar la identitat d'un usuari. Això es fa normalment mitjançant credencials com ara noms d'usuari i contrasenyes, tokens JWT (JSON Web Tokens), o OAuth.
Autorització
L'autorització és el procés de determinar si un usuari autenticat té permís per accedir a un recurs o realitzar una acció específica. Això es fa normalment mitjançant rols i permisos.
- Implementació de l'autenticació
Utilitzant JWT per a l'autenticació
-
Instal·lació de dependències
npm install jsonwebtoken bcryptjs
-
Creació de tokens JWT
const jwt = require('jsonwebtoken'); const bcrypt = require('bcryptjs'); const SECRET_KEY = 'your_secret_key'; // Funció per generar un token JWT function generateToken(user) { return jwt.sign({ id: user.id, email: user.email }, SECRET_KEY, { expiresIn: '1h' }); } // Funció per verificar un token JWT function verifyToken(token) { try { return jwt.verify(token, SECRET_KEY); } catch (error) { throw new Error('Invalid token'); } }
-
Autenticació d'usuaris
const users = []; // Simulació d'una base de dades d'usuaris async function login(email, password) { const user = users.find(user => user.email === email); if (!user) { throw new Error('User not found'); } const isPasswordValid = await bcrypt.compare(password, user.password); if (!isPasswordValid) { throw new Error('Invalid password'); } return generateToken(user); } async function register(email, password) { const hashedPassword = await bcrypt.hash(password, 10); const newUser = { id: users.length + 1, email, password: hashedPassword }; users.push(newUser); return generateToken(newUser); }
- Implementació de l'autorització
Utilitzant rols i permisos
-
Definició de rols i permisos
const roles = { ADMIN: 'ADMIN', USER: 'USER' }; const permissions = { READ: 'READ', WRITE: 'WRITE' }; const rolePermissions = { [roles.ADMIN]: [permissions.READ, permissions.WRITE], [roles.USER]: [permissions.READ] };
-
Verificació de permisos
function checkPermission(user, permission) { const userPermissions = rolePermissions[user.role]; if (!userPermissions.includes(permission)) { throw new Error('Permission denied'); } }
-
Integració amb resolvers de GraphQL
const resolvers = { Query: { getUser: (parent, args, context) => { const user = verifyToken(context.token); checkPermission(user, permissions.READ); return users.find(u => u.id === args.id); } }, Mutation: { createUser: (parent, args, context) => { const user = verifyToken(context.token); checkPermission(user, permissions.WRITE); return register(args.email, args.password); } } };
- Exemples pràctics
Exemple de resolució d'una consulta amb autenticació i autorització
const { ApolloServer, gql } = require('apollo-server'); const typeDefs = gql` type User { id: ID! email: String! } type Query { getUser(id: ID!): User } type Mutation { login(email: String!, password: String!): String register(email: String!, password: String!): String } `; const resolvers = { Query: { getUser: (parent, args, context) => { const user = verifyToken(context.token); checkPermission(user, permissions.READ); return users.find(u => u.id === args.id); } }, Mutation: { login: async (parent, args) => { return await login(args.email, args.password); }, register: async (parent, args) => { return await register(args.email, args.password); } } }; const server = new ApolloServer({ typeDefs, resolvers, context: ({ req }) => { const token = req.headers.authorization || ''; return { token }; } }); server.listen().then(({ url }) => { console.log(`Server ready at ${url}`); });
- Exercicis pràctics
Exercici 1: Implementar autenticació amb JWT
- Crea una funció per generar tokens JWT.
- Crea una funció per verificar tokens JWT.
- Implementa la funció de registre d'usuaris amb hash de contrasenya.
Exercici 2: Implementar autorització basada en rols
- Defineix rols i permisos.
- Crea una funció per verificar permisos.
- Integra la verificació de permisos en els resolvers de GraphQL.
Solucions
Solució Exercici 1
// Funció per generar un token JWT function generateToken(user) { return jwt.sign({ id: user.id, email: user.email }, SECRET_KEY, { expiresIn: '1h' }); } // Funció per verificar un token JWT function verifyToken(token) { try { return jwt.verify(token, SECRET_KEY); } catch (error) { throw new Error('Invalid token'); } } // Funció de registre d'usuaris async function register(email, password) { const hashedPassword = await bcrypt.hash(password, 10); const newUser = { id: users.length + 1, email, password: hashedPassword }; users.push(newUser); return generateToken(newUser); }
Solució Exercici 2
// Definició de rols i permisos const roles = { ADMIN: 'ADMIN', USER: 'USER' }; const permissions = { READ: 'READ', WRITE: 'WRITE' }; const rolePermissions = { [roles.ADMIN]: [permissions.READ, permissions.WRITE], [roles.USER]: [permissions.READ] }; // Funció per verificar permisos function checkPermission(user, permission) { const userPermissions = rolePermissions[user.role]; if (!userPermissions.includes(permission)) { throw new Error('Permission denied'); } } // Integració amb resolvers de GraphQL const resolvers = { Query: { getUser: (parent, args, context) => { const user = verifyToken(context.token); checkPermission(user, permissions.READ); return users.find(u => u.id === args.id); } }, Mutation: { createUser: (parent, args, context) => { const user = verifyToken(context.token); checkPermission(user, permissions.WRITE); return register(args.email, args.password); } } };
Conclusió
En aquesta secció, hem après com implementar l'autenticació i l'autorització en un servidor GraphQL utilitzant JWT per a l'autenticació i rols i permisos per a l'autorització. Hem vist exemples pràctics i hem realitzat exercicis per reforçar els conceptes apresos. Amb aquests coneixements, estàs preparat per assegurar la teva aplicació GraphQL i protegir les teves dades de manera efectiva.
Curs de GraphQL
Mòdul 1: Introducció a GraphQL
- Què és GraphQL?
- GraphQL vs REST
- Configuració d'un servidor GraphQL
- Conceptes bàsics de l'esquema de GraphQL
Mòdul 2: Conceptes bàsics
Mòdul 3: Disseny avançat d'esquemes
Mòdul 4: Treballant amb dades
- Connexió a una base de dades
- Estratègies de recuperació de dades
- Agrupació i emmagatzematge en memòria cau
- Gestió d'errors
Mòdul 5: Rendiment i seguretat
Mòdul 6: Eines i ecosistema
Mòdul 7: Proves i desplegament
- Proves unitàries de resolvers
- Proves d'integració
- Integració contínua
- Desplegament de servidors GraphQL