Autenticación JWT con tokens de actualización

Al crear una aplicación web, la autenticación es uno de los aspectos importantes y, por lo general, implementamos la autenticación mediante tokens JWT (puede obtener más información sobre JWT aquí ). Creamos un token de acceso y lo almacenamos en el almacenamiento local o sesión o cookie. Pero hay una forma más segura de implementar esto usando Refresh Tokens.

Refresh Tokens: Es un token único que se utiliza para obtener tokens de acceso adicionales. Esto le permite tener tokens de acceso de corta duración sin tener que recopilar credenciales cada vez que uno caduca.

Dado que los tokens de acceso no son válidos durante un período prolongado por motivos de seguridad, un token de actualización ayuda a volver a autenticar a un usuario sin credenciales de inicio de sesión. Este token de actualización nunca se expone al Javascript del lado del cliente, incluso si nuestro token de acceso se ve comprometido, caducará en muy poco tiempo. Entonces, enviaremos dos tokens en lugar de uno, un token de acceso y un token de actualización. El token de acceso contendrá toda la información del usuario y se almacenará en el tiempo de ejecución de Javascript, pero el token de actualización se almacenará de forma segura en una cookie solo de HTTP. 

 

Persistencia de autenticación: podemos persistir fácilmente a los usuarios entre actualizaciones e inicio de sesión sin ninguna credencial. Podemos crear una nueva ruta llamada actualizar, cada vez que un token caduca o un usuario actualiza, podemos obtener un nuevo token de acceso enviando una solicitud a esta ruta

 

Implementación: ahora implementemos la autenticación con tokens JWT y Refresh. Comenzaremos creando una nueva aplicación Express e instalando todas las dependencias requeridas. 

Paso 1: Ejecute los siguientes comandos para inicializar el proyecto y crear un archivo de índice y un archivo env. (Asegúrese de tener node y npm instalados)

npm init -y
touch index.js .env

Paso 2: Instale todas las dependencias requeridas y abra el proyecto en el editor de código.

npm install express cookie-parser dontenv jsonwebtoken 

Estructura del proyecto:

 

Escribiremos nuestra lógica de autenticación en Index.js. Primero crearemos una aplicación rápida y luego implementaremos dos rutas de inicio de sesión y actualización . La ruta de inicio de sesión recibirá una solicitud posterior, luego verificará las credenciales si coinciden, enviará un token de actualización y un token de acceso en respuesta. La ruta de actualización también recibirá una solicitud posterior, verificará el token de actualización, si es correcto, responderá con un nuevo token de acceso; de lo contrario, arrojará un error de autorización.

Ejemplo: ahora implementaremos dos rutas de inicio de sesión y actualización. El siguiente código es para index.js:

índice.js

const dotenv = require('dotenv');
const express = require('express');
const cookieparser = require('cookie-parser');
const jwt = require('jsonwebtoken')
const bodyParser = require('body-parser');

// Configuring dotenv
dotenv.config();

const app = express();

// Setting up middlewares to parse request body and cookies
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieparser());

const userCredentials = {
    username: 'admin',
    password: 'admin123',
    email: 'admin@gmail.com'
}

app.post('/login', (req, res) => {
    // Destructuring username & password from body
    const { username, password } = req.body;

    // Checking if credentials match
    if (username === userCredentials.username && 
        password === userCredentials.password) {
        
        //creating a access token
        const accessToken = jwt.sign({
            username: userCredentials.username,
            email: userCredentials.email
        }, process.env.ACCESS_TOKEN_SECRET, {
            expiresIn: '10m'
        });
        // Creating refresh token not that expiry of refresh 
        //token is greater than the access token
        
        const refreshToken = jwt.sign({
            username: userCredentials.username,
        }, process.env.REFRESH_TOKEN_SECRET, { expiresIn: '1d' });

        // Assigning refresh token in http-only cookie 
        res.cookie('jwt', refreshToken, { httpOnly: true, 
            sameSite: 'None', secure: true, 
            maxAge: 24 * 60 * 60 * 1000 });
        return res.json({ accessToken });
    }
    else {
        // Return unauthorized error if credentials dont match
        return res.status(406).json({ 
            message: 'Invalid credentials' });
    }
})

app.post('/refresh', (req, res) => {
    if (req.cookies?.jwt) {

        // Destructuring refreshToken from cookie
        const refreshToken = req.cookies.jwt;

        // Verifying refresh token
        jwt.verify(refreshToken, process.env.REFRESH_TOKEN_SECRET, 
        (err, decoded) => {
            if (err) {

                // Wrong Refesh Token
                return res.status(406).json({ message: 'Unauthorized' });
            }
            else {
                // Correct token we send a new access token
                const accessToken = jwt.sign({
                    username: userCredentials.username,
                    email: userCredentials.email
                }, process.env.ACCESS_TOKEN_SECRET, {
                    expiresIn: '10m'
                });
                return res.json({ accessToken });
            }
        })
    } else {
        return res.status(406).json({ message: 'Unauthorized' });
    }
})

app.listen(process.env.PORT, () => {
    console.log(`Server active on http://localhost:${process.env.PORT}!`);
})

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *