¿Enviar datos de un lugar a otro? Para su propia tranquilidad y la protección de sus usuarios, debe asegurarlo con JWT.
Cuando está creando una aplicación, es vital que proteja los datos confidenciales del acceso no autorizado. Muchas aplicaciones web, móviles y en la nube modernas utilizan API REST como medio principal de comunicación. Como resultado, es crucial diseñar y desarrollar API de back-end con la seguridad en primer plano.
Un enfoque efectivo para asegurar una API REST involucra JSON Web Tokens (JWT). Estos tokens ofrecen un mecanismo sólido para la autenticación y autorización de usuarios, lo que ayuda a salvaguardar los recursos protegidos contra el acceso de actores malintencionados.
¿Qué son los tokens web JSON?
Token web JSON (JWT) es un estándar de seguridad ampliamente utilizado. Proporciona un método conciso e independiente para transmitir datos de forma segura entre una aplicación de cliente y un sistema de back-end.
Una API REST puede usar JWT para identificar y autenticar de forma segura a los usuarios cuando realizan solicitudes HTTP para acceder a recursos protegidos.
Un token web JSON consta de tres partes distintas: el encabezado, la carga útil y la firma. Codifica cada parte y las concatena usando un punto (".").
El encabezado describe el algoritmo criptográfico utilizado para firmar el token, mientras que la carga útil contiene datos sobre el usuario y cualquier metadato adicional.
Por último, la firma, calculada mediante el encabezado, la carga útil y la clave secreta, garantiza la integridad y autenticidad del token.
Con los conceptos básicos de JWT fuera del camino, construyamos una API REST de Node.js e implementemos JWT.
Configurar una aplicación Express.js y una base de datos MongoDB
Aquí encontrará cómo crear una autenticación simple API REST que maneja tanto el registro como la funcionalidad de inicio de sesión. Una vez que el proceso de inicio de sesión autentica a un usuario, debería poder realizar solicitudes HTTP a una ruta API protegida.
Puedes encontrar el código del proyecto en este repositorio GitHub.
Para empezar, crear un servidor web Expresse instale estos paquetes:
npm instalar cors dotenv bycrpt mongoose cookie-parser crypto jsonwebtoken mongodb
Próximo, crear una base de datos MongoDB o configurar un clúster MongoDB en la nube. Luego copie la cadena de conexión de la base de datos, cree una .env archivo en el directorio raíz y pegue la cadena de conexión:
CONNECTION_STRING="cadena de conexión"
Configurar la conexión de la base de datos
Crear un nuevo utils/db.js archivo en el directorio raíz de la carpeta de su proyecto. En este archivo, agregue el siguiente código para establecer la conexión a la base de datos usando Mongoose.
constante mangosta = requerir('mangosta');
constante conectarDB = asíncrono () => {
intentar {
esperar mangosta.conectar (proceso.env. CADENA DE CONEXIÓN);
consola.registro("¡Conectado a MongoDB!");
} atrapar (error) {
consola.error("Error al conectarse a MongoDB:", error);
}
};
módulo.exportaciones = connectDB;
Definir el modelo de datos
Defina un esquema de datos de usuario simple usando Mongoose. En el directorio raíz, cree un nuevo modelo/usuario.modelo.js archivo y agregue el siguiente código.
constante mangosta = requerir('mangosta');
constante esquema de usuario = nuevo mangosta. Esquema({
nombre de usuario: Cadena,
contraseña: {
tipo: Cadena,
requerido: verdadero,
único: verdadero,
},
});
constante Usuario = mangosta.modelo("Usuario", esquema de usuario);
módulo.exportaciones = Usuario;
Definir los controladores para las rutas API
Las funciones del controlador gestionarán el registro y el inicio de sesión; son una parte sustancial de este programa de muestra. En el directorio raíz, cree un controladores/controladores de usuario.js archivo y agregue el siguiente código:
- Defina el controlador de registro de usuario.
Este fragmento de código codifica la contraseña proporcionada mediante bcrypt y luego crea un nuevo registro de usuario en la base de datos, almacenando el nombre de usuario y la contraseña cifrada. Si el registro es exitoso, envía una respuesta con un mensaje de éxito.constante Usuario = requerir('../modelos/usuario.modelo');
constante bcripta = requerir('bcrypt');
constante { generar token } = requerir('../middleware/autorización');exportaciones.registerUser = asíncrono (requerido, res) => {
constante { nombre de usuario, contraseña } = req.body;intentar {
constante hash = esperar bcrypt.hash (contraseña, 10);
esperar Usuario.create({ nombre de usuario, contraseña: hash});
res.status(201).enviar({ mensaje: 'Usuario registrado con éxito' });
} atrapar (error) {
consola.log (error);
res.status(500).enviar({ mensaje: '¡¡Ocurrió un error!! ' });
}
}; - Defina un controlador de inicio de sesión para administrar el proceso de inicio de sesión del usuario:
Cuando un usuario envía una solicitud a la /login ruta, deben pasar sus credenciales de autenticación en el cuerpo de la solicitud. Luego, el código verifica esas credenciales y genera un token web JSON. El token se almacena de forma segura en una cookie con la solo http indicador establecido en verdadero. Esto evita que JavaScript del lado del cliente acceda al token, lo que protege contra posibles ataques de secuencias de comandos entre sitios (XSS).exportaciones.loginUser = asíncrono (requerido, res) => {
constante { nombre de usuario, contraseña } = req.body;intentar {
constante usuario = esperar Usuario.findOne({nombre de usuario});
si (!usuario) {
devolver res.status(404).enviar({ mensaje: 'Usuario no encontrado' });
}constante coincidencia de contraseña = esperar bcrypt.compare (contraseña, usuario.contraseña);
si (!coincidencia de contraseña) {
devolver res.status(401).enviar({ mensaje: 'Credenciales de acceso invalidos' });
}constante carga útil = { ID de usuario: usuario._id };
constante token = generar token (carga útil);
res.cookie('simbólico', token, { solo http: verdadero });
res.status(200).json({ mensaje: 'Inicio de sesión correcto'});
} atrapar (error) {
consola.log (error);
res.status(500).enviar({ mensaje: 'Ocurrió un error al iniciar sesión' });
}
}; - Finalmente, defina una ruta protegida:
Al almacenar el JWT en una cookie, las solicitudes de API posteriores del usuario autenticado incluirán automáticamente el token, lo que permitirá que el servidor valide y autorice las solicitudes.exportaciones.getUsers = asíncrono (requerido, res) => {
intentar {
constante usuarios = esperar Usuario.find({});
res.json (usuarios);
} atrapar (error) {
consola.log (error);
res.status(500).enviar({ mensaje: '¡¡Ocurrió un error!!' });
}
};
Crear un middleware de autenticación
Ahora que ha definido un controlador de inicio de sesión que genera un token JWT tras una autenticación exitosa, defina las funciones de autenticación de middleware que generarán y verificarán el token JWT.
En el directorio raíz, cree una nueva carpeta, software intermedio. Dentro de esta carpeta, agregue dos archivos: autenticación.js y config.js.
Agrega este código a config.js:
constante cripto = requerir('cripto');
módulo.exportaciones = {
clave secreta: crypto.randomBytes(32).Encadenar('maleficio')
};
Este código genera una nueva clave secreta aleatoria cada vez que se ejecuta. Luego puede usar esta clave secreta para firmar y verificar la autenticidad de los JWT. Una vez que un usuario se haya autenticado con éxito, genere y firme un JWT con la clave secreta. Luego, el servidor usará la clave para verificar que el JWT sea válido.
Agregue el siguiente código en autenticación.js que define funciones de middleware que generan y verifican los JWT.
constante jwt = requerir('jsonwebtoken');
constante {clave secreta} = requerir('./config');constante generar token = (carga útil) => {
constante token = jwt.sign (carga útil, clave secreta, { expira en: '1h' });
devolver ficha;
};constante verificarToken = (req, res, siguiente) => {
constante token = req.cookies.token;si (!token) {
devolver res.status(401).json({ mensaje: 'No se proporcionó token' });
}jwt.verify (token, secretKey, (err, decodificado) => {
si (Error) {
devolver res.status(401).json({ mensaje: 'Simbolo no valido' });
}req.userId = decodificado.userId;
próximo();
});
};
módulo.exportaciones = {generarToken, verificarToken};
El generar token La función genera un JWT firmando una carga útil con una clave secreta y estableciendo un tiempo de caducidad mientras el verificarToken La función sirve como middleware para verificar la autenticidad y validez de un token proporcionado.
Definir las rutas API
Crear un nuevo rutas/rutas de usuario.js archivo en el directorio raíz y agregue el siguiente código.
constante expresar = requerir('expresar');
constante enrutador = expreso. enrutador();
constante controladores de usuario = requerir('../controladores/usuarioControladores');
constante { verificarToken } = requerir('../middleware/autorización');
enrutador.post('/api/registrar', controladores de usuario.registerUser);
enrutador.post('/api/iniciar sesión', UserControllers.loginUser);
enrutador.get('/api/usuarios', verificarToken, UserControllers.getUsers);
módulo.exportaciones = enrutador;
Actualice el punto de entrada de su servidor
Actualiza tu servidor.js archivo con el siguiente código.
constante expresar = requerir('expresar');
constante corazones = requerir('corazón');
constante aplicación = expreso();
constante puerto = 5000;
requerir('dotenv').config();
constante conectarDB = requerir('./utils/db');
constante analizador de cookies = requerir('analizador de cookies');conectarDB();
aplicación.uso (express.json());
app.use (express.urlencoded({ extendido: verdadero }));
app.use (cors());
aplicación.uso (cookieParser());
constante rutas de usuario = requerir('./rutas/rutasusuario');
aplicación.uso('/', rutas de usuario);
app.listen (puerto, () => {
consola.registro(`El servidor está escuchando en http://localhost:${puerto}`);
});
Para probar la API REST, active el servidor de desarrollo y realice solicitudes de API a los puntos finales definidos:
nodo servidor.js
Protección de las API REST de Node.js
Proteger las API REST de Node.js va más allá del simple uso de JWT, aunque juegan un papel crucial en la autenticación y autorización, es esencial adoptar un enfoque de seguridad holístico para proteger su backend sistemas Junto con los JWT, también debe considerar implementar HTTPS para cifrar la comunicación, la validación y desinfección de entradas, y muchos otros.
Al combinar múltiples medidas de seguridad, puede establecer un marco de seguridad sólido para su API REST de Node.js y minimice el riesgo de acceso no autorizado, violaciones de datos y otras medidas de seguridad amenazas