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
