← Volver

Login y registro en Node.js

Publicado el 10 de agosto de 2025

Para crear el backend de login y registro en Node.js vamos a crear la siguiente estructura de ficheros:

Instalamos los paquetes necesarios:

sudo npm install nodemon bcrypt jsonwebtoken cors mysql2 express

El archivo index.js

const express = require("express");
const cors = require("cors");

const app = express();
const PORT = 3000;

const loginRoute = require("./routes/login.js");
const registerRoute = require("./routes/register.js");
const protectedRoutes = require('./routes/protected.js');

app.use(cors());
app.use(express.json());

app.use("/login", loginRoute);
app.use("/register", registerRoute);
app.use('/protected', protectedRoutes);

app.listen(PORT, () => {
    console.log(`Servidor escuchando en http://localhost:${PORT}`);
})

El archivo login.js

const express = require("express");
const jwt = require("jsonwebtoken");
const bcrypt = require('bcrypt');
const pool = require("../config/db.js");

const router = express.Router();
const JWT_SECRET = "12345";

router.post("/", async (req, res) => {

    const { user, password } = req.body;

    if (!user || !password) {
        return res.status(400).json({
            message: "Faltan datos"
        });
    }

    try {
        const [rows] = await pool.execute("SELECT * FROM users WHERE user = ?", [user]);
        if (rows.length === 0) {
            return res.status(401).json({
                message: "Usuario o contraseña incorrectos"
            })
        }

        const userDB = rows[0];
        const validPassword = await bcrypt.compare(password, userDB.password);

        if (!validPassword) {
            return res.status(401).json({ message: "Usuario o contraseña incorrectos" });
        }

        const token = jwt.sign({
            id: userDB.id,
            user: userDB.user
        }, JWT_SECRET, { expiresIn: "1h" });

        res.json({ token: token });

    } catch (error) {
        console.log(error);
        res.status(500).json({
            message: "Error interno del servidor"
        })
    }



})

module.exports = router;

El archivo register.js

const express = require('express');
const bcrypt = require('bcrypt');
const pool = require('../config/db.js'); // importa el pool de conexiones MySQL

const router = express.Router();

const saltRounds = 10;

router.post("/", async (req, res) => {
    const { user, password } = req.body;

    if (!user || !password) {
        return res.status(400).json({
            message: "Faltan datos"
        });
    }

    try {

        const [existingUsers] = await pool.execute("SELECT * FROM users WHERE user = ?", [user]);

        if (existingUsers.length > 0) {
            return res.status(409).json({
                message: "El usuario ya existe"
            });
        }

        const hashedPassword = await bcrypt.hash(password, saltRounds);

        await pool.execute("INSERT INTO users (user, password) VALUES (?, ?)", [user, hashedPassword]);

        res.status(201).json({
            message: "Usuario registrado correctamente"
        });

    } catch (error) {
        res.status(500).json({
            message: "Error interno del servidor"
        });
    }



});


module.exports = router;

El archivo protected.js

const express = require('express');
const authenticateToken = require('../middleware/auth');

const router = express.Router();

router.get('/profile', authenticateToken, (req, res) => {
    res.json({ message: 'Acceso permitido', user: req.user });
});

module.exports = router;

El archivo db.js

const mysql = require("mysql2/promise");

const pool = mysql.createPool({
    host: "localhost",
    user: "root",
    password: "tuPassword",
    database: "login_register",
    waitForConnections: true,
    connectionLimit: 10,
    queueLimit: 0
});

module.exports = pool;

El archivo auth.js

const jwt = require("jsonwebtoken");

const JWT_SECRET = "12345";

function authenticateToken(req, res, next) {
    const authHeader = req.headers["authorization"];

    const token = authHeader && authHeader.split(" ")[1];

    if (!token) {
        return res.status(401).json({
            message: "Token no proporcionado"
        });
    }

    jwt.verify(token, JWT_SECRET, (err, user) => {
        if (err) {
            return res.status(403).json({
                message: "Token invalido"
            });
        }

        req.user = user;

        next();
    })

}

module.exports = authenticateToken;

En el frontend tendremos 3 ficheros de javascript:

El archivo login.js

const loginUser = document.querySelector("#login-user");
const loginPassword = document.querySelector("#login-password");
const loginButton = document.querySelector("#login-button");

loginButton.addEventListener("click", async (e) => {
    const userInfo = {
        user: loginUser.value,
        password: loginPassword.value,
    }

    try {
        const response = await fetch("http://localhost:3000/login", {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
            },
            body: JSON.stringify(userInfo),
        });

        const data = await response.json();

        if (response.ok) {
            // Aquí recibes el token JWT
            const token = data.token;
            alert("Login exitoso");

            // Guardar token en localStorage (o cookie, según prefieras)
            localStorage.setItem("jwtToken", token);

            // Redirigir o mostrar contenido protegido
            // window.location.href = "/dashboard.html"; // ejemplo

        } else {
            alert(data.message || "Error en el login");
        }
    } catch (error) {
        console.error("Error en login:", error);
        alert("Error en la conexión con el servidor");
    }

});

El archivo register.js

const registerUser = document.querySelector("#register-user");
const registerPassword = document.querySelector("#register-password");
const registerButton = document.querySelector("#register-button");

registerButton.addEventListener("click", async (e) => {
    const userInfo = {
        user: registerUser.value,
        password: registerPassword.value,
    }

    try {
        const response = await fetch("http://localhost:3000/register", {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
            },
            body: JSON.stringify(userInfo),
        });

        const data = await response.json();

        if (response.ok) {
            alert(data.message); // Usuario registrado correctamente
            registerUser.value = "";
            registerPassword.value = "";
        } else {
            alert(data.message || "Error al registrar");
        }
    } catch (error) {
        console.error("Error en registro:", error);
        alert("Error en la conexión con el servidor");
    }
});

El archivo protected.js

async function checkAuth() {
    const token = localStorage.getItem("jwtToken");

    if (!token) {
        window.location.href = "index.html"; // No hay token, redirigir
        return;
    }

    try {
        const response = await fetch("http://localhost:3000/protected/profile", {
            method: "GET",
            headers: {
                "Authorization": "Bearer " + token
            }
        });

        if (!response.ok) {
            // Token inválido o expirado
            localStorage.removeItem("jwtToken");
            window.location.href = "index.html";
            return;
        }

        // Token válido, puedes obtener data si quieres
        const data = await response.json();
        console.log("Usuario autenticado:", data.user);
        // Aquí sigues en la página

    } catch (error) {
        console.error("Error validando token:", error);
        localStorage.removeItem("jwtToken");
        window.location.href = "index.html";
    }
}

// Ejecutar al cargar la página
checkAuth();