Aprende a autenticar usuarios y utilizar sesiones, cookies y JWT en Node.js

Posted by

En este tutorial, aprenderás a implementar la autenticación de usuario, sesiones, cookies y JWT (JSON Web Tokens) en una aplicación Node.js. La autenticación es un paso crucial en cualquier aplicación web para garantizar la seguridad de los usuarios y proteger los datos sensibles.

Paso 1: Configuración del proyecto
Primero, crea un nuevo proyecto Node.js e instala las dependencias necesarias. Puedes hacerlo ejecutando el siguiente comando en tu terminal:

npm init -y
npm install express body-parser express-session cookie-parser jsonwebtoken bcrypt

Paso 2: Creación del servidor
Crea un archivo app.js donde configuraremos nuestro servidor Express. Aquí es donde definiremos las rutas y las configuraciones necesarias para la autenticación.

<!DOCTYPE html>
<html>
  <head>
    <title>Autenticación de Usuario con Node.js</title>
  </head>
  <body>
    <h1> Aprende Autenticación de Usuario, Sesión, Cookies y JWT con Node.js</h1>
    <p> Este tutorial te guiará a través de los pasos para implementar autenticación de usuario en una aplicación Node.js.</p>

    <h2> Paso 1: Configuración del proyecto </h2>
    <p> Primero, crea un nuevo proyecto Node.js e instala las dependencias necesarias:</p>

    <pre>
      <code>
        npm init -y
        npm install express body-parser express-session cookie-parser jsonwebtoken bcrypt
      </code>
    </pre>

    <h2> Paso 2: Creación del servidor </h2>
    <p> Crea un archivo `app.js` donde configuraremos nuestro servidor Express:</p>

    <pre>
      <code>
        const express = require('express');
        const bodyParser = require('body-parser');

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

        app.use(bodyParser.json());

        app.listen(port, () => {
          console.log(`Servidor iniciado en el puerto ${port}`);
        });
      </code>
    </pre>

</body>
</html>

En el código anterior, estamos importando las dependencias necesarias, configurando nuestro servidor Express para escuchar en el puerto 3000 y utilizando el middleware body-parser para analizar los cuerpos de las solicitudes entrantes.

Paso 3: Implementación de la autenticación de usuario
Ahora, vamos a crear las rutas y lógica necesarias para la autenticación de usuario en nuestra aplicación. Añade las siguientes rutas a tu archivo app.js:

<h2> Paso 3: Implementación de la autenticación de usuario </h2>
<p> Ahora, vamos a crear las rutas y lógica necesarias para la autenticación de usuario en nuestra aplicación:</p>

<pre>
  <code>
    // Ruta de registro de usuario
    app.post('/register', (req, res) => {
      const { username, password } = req.body;

      // Lógica para registrar al usuario en la base de datos
    });

    // Ruta de inicio de sesión
    app.post('/login', (req, res) => {
      const { username, password } = req.body;

      // Lógica para verificar las credenciales del usuario y generar un JWT
    });
  </code>
</pre>

En las rutas anteriores, estamos creando una ruta de registro de usuario donde el usuario puede enviar sus credenciales para registrarse en la aplicación, y una ruta de inicio de sesión donde el usuario puede enviar sus credenciales para autenticarse y recibir un JWT válido.

Paso 4: Implementación de sesiones y cookies
Para gestionar las sesiones de usuario y utilizar cookies para almacenar información de sesión, podemos utilizar el middleware express-session y cookie-parser. Añade el siguiente código a tu archivo app.js:

<h2> Paso 4: Implementación de sesiones y cookies </h2>
<p> Para gestionar las sesiones de usuario y utilizar cookies para almacenar información de sesión, podemos utilizar el middleware `express-session` y `cookie-parser`:</p>

<pre>
  <code>
    const session = require('express-session');
    const cookieParser = require('cookie-parser');

    app.use(cookieParser());
    app.use(session({
      secret: 'secreto',
      resave: false,
      saveUninitialized: true
    }));
  </code>
</pre>

En el código anterior, estamos configurando nuestras sesiones de usuario y cookies con una clave secreta y las opciones predeterminadas para resave y saveUninitialized.

Paso 5: Implementación de JWT
Finalmente, para autenticar a los usuarios utilizando tokens JWT, podemos añadir la lógica necesaria en nuestra ruta de inicio de sesión. Añade el siguiente código a tu archivo app.js:

<h2> Paso 5: Implementación de JWT </h2>
<p> Finalmente, para autenticar a los usuarios utilizando tokens JWT, podemos añadir la lógica necesaria en nuestra ruta de inicio de sesión:</p>

<pre>
  <code>
    const jwt = require('jsonwebtoken');
    const bcrypt = require('bcrypt');

    const SECRET_KEY = 'secretojwt';

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

      // Lógica para verificar las credenciales del usuario y generar un JWT
      if (/* credenciales válidas */) {
        const token = jwt.sign({ username }, SECRET_KEY);
        res.cookie('token', token, { httpOnly: true });
        res.json({ token });
      } else {
        res.status(401).json({ message: 'Credenciales incorrectas' });
      }
    });
  </code>
</pre>

En el código anterior, estamos generando un token JWT utilizando la librería jsonwebtoken y enviándolo al cliente en forma de cookie para futuras solicitudes.

¡Y eso es todo! Con estos pasos, has aprendido a implementar la autenticación de usuario, sesiones, cookies y JWT en una aplicación Node.js. Ahora puedes aplicar estos conceptos en tu propia aplicación y garantizar la seguridad de tus usuarios. ¡Buena suerte!

0 0 votes
Article Rating
41 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
@juanmaldonado8197
1 month ago

bajé yaak y el avira me lo puso en cuarentena xd

@user-ei8su7hx9r
1 month ago

<!– Index que midu se le olvido subir –>
<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<link rel="shortcut icon" href="#">

<title>Login & Registration Forms</title>

<style>

*,

*::before,

*::after {

box-sizing: border-box;

}

body {

font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;

background-color: #f5f5f5;

display: flex;

justify-content: center;

align-items: center;

height: 100vh;

margin: 0;

}

.container {

display: flex;

flex-direction: column;

align-items: center;

}

.form-container {

background-color: #fff;

padding: 20px;

margin: 10px;

border-radius: 8px;

box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);

width: 300px;

}

form h2 {

margin-bottom: 20px;

font-size: 24px;

text-align: center;

}

label {

display: block;

margin-bottom: 5px;

font-weight: bold;

}

input {

width: 100%;

padding: 10px;

margin-bottom: 20px;

border: 1px solid #ccc;

border-radius: 4px;

}

button {

width: 100%;

padding: 10px;

background-color: #28a745;

color: #fff;

border: none;

border-radius: 4px;

cursor: pointer;

font-size: 16px;

}

button:hover {

background-color: #218838;

}

</style>

</head>

<body>

<div class="container">

<% if (typeof username !=='undefined' ) { %>

<div class="form-container">

<h2>Hola <%= username %>!</h2>

<p>Estas en el panel administracion</p>

<button id="close-session" class="close-session">Cerrar sesión</button>

</div>

<% } else { %>

<div class="form-container">

<form id="login-form">

<h2>Login</h2>

<label for="login-username">Username</label>

<input type="text" id="login-username" name="username" required>

<label for="login-password">Password</label>

<input type="password" id="login-password" name="password" required>

<button type="submit">Login</button>

<span>&nbsp;</span>

</form>

</div>

<div class="form-container">

<form id="register-form">

<h2>Register</h2>

<label for="register-username">Username</label>

<input type="text" id="register-username" name="username" required>

<label for="register-password">Password</label>

<input type="password" id="register-password" name="password" required>

<label for="register-confirm-password">Confirm password</label>

<input type="password" id="register-confirm-password" name="confirm-password" required>

<button type="submit">Register</button>

<span>&nbsp;</span>

</form>

</div>

<% } %>

</div>

<script>

const $ = el => document.querySelector(el);

const loginForm = $('#login-form');

const loginSpan = $('#login-form span');

const registerForm = $('#register-form');

const registerSpan = $('#register-form span');

const logoutButton = $('#close-session');

loginForm?.addEventListener('submit', e => {

e.preventDefault();

const username = $('#login-username').value;

const password = $('#login-password').value;

fetch('/login', {

method: 'POST',

headers: {

'Content-Type': 'application/json'

},

body: JSON.stringify({ username, password })

})

.then(res => {

if (res.ok) {

loginSpan.innerText = 'Sesion iniciada… Entrando…';

loginSpan.style.color = 'green';

setTimeout(() => {

window.location.href = '/protected';

}, 2000);

} else {

loginSpan.innerText = 'Error al iniciar sesion';

loginSpan.style.color = 'red';

}

});

});

registerForm?.addEventListener('submit', e => {

e.preventDefault();

const username = $('#register-username').value;

const password = $('#register-password').value;

const confirmPassword = $('#register-confirm-password').value;

if (password !== confirmPassword) {

alert('Passwords do not match');

return;

}

fetch('/register', {

method: 'POST',

headers: {

'Content-Type': 'application/json'

},

body: JSON.stringify({ username, password })

})

.then(res => {

if (res.ok) {

registerSpan.innerText = 'Registro exitoso! Iniciando sesion…';

registerSpan.style.color = 'green';

setTimeout(() => {

window.location.href = '/login';

}, 2000);

} else {

registerSpan.innerText = 'Error al registrarse';

registerSpan.style.color = 'red';

}

});

});

logoutButton?.addEventListener('click', e => {

e.preventDefault();

fetch('/logout', {

method: 'POST',

headers: {

'Content-Type': 'application/json'

}

})

.then(res => {

console.log(res);

window.location.href = '/';

});

});

</script>

</body>

</html>

@franciscosantander6689
1 month ago

Buenas Midu se agradece el contenido, fui al repo GIT y creo que no esta el código de la clase 7, será posible si la puedes subir? 😁

@codesthenos
1 month ago

que pasada deseando que llegue la siguiente parte, gracias por tanto midu, eres genial, increible la cantidad de contenido de calidad que generas

@danielspinella2177
1 month ago

Hola midu, cuando pasas el template de los forms por github? Me esta gustando mucho el curso, pero me he quedado a mitad por eso.

@codesthenos
1 month ago

Mil gracias por todo, esta siendo una aventura genial, no es como que lo necesite mucho pero se me hace raro que al terminar este video no lo hayas subido al repo junto con el resto

@felipe4181
1 month ago

"index.ejs" Code HERE

Hola @midulive,

apenas me desatraso y déjame decirte que da gusto ver lo bien que explicas, he visto mucho contenido en inglés y ninguno como tú para dar videos magistrales.

Mil gracias por toda esta colaboración , un fuerte abrazo.

Veo que mucha gente esta preguntando por el código del archivo "index.ejs", por acá lo dejo, solo con el animo de ayudarle a la gente que se puede encontrar atascada, pero si no te gusta puedes eliminar este comentario ya que veo que esta clase va a ser complementada con el tema de pasaporte, auth2.0 etc

`<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Login & Registration Forms</title>
<style>
*,
*::before,
*::after {
box-sizing: border-box;
}

body {
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
background-color: ■#f5f5f5;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}

.container {
display: flex;
flex-direction: column;
align-items: center;
}

.form-container {
background-color: #fff;
padding: 20px;
margin: 10px;
border-radius: 8px;
box-shadow: 0 2px 10px;
width: 300px;
}

form h2 {
margin-bottom: 20px;
font-size: 24px;
text-align: center;
}

label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}

input {
width: 100%;
padding: 10px;
margin-bottom: 20px;
border: 1px solid #ccc;
border-radius: 4px;
}

button {
width: 100%;
padding: 10px;
background-color: #28a745;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}

button:hover {
background-color: #218838;
}
</style>
</head>
<body>
<div class="container">
<% if (typeof username !== 'undefined') { %>
<div class="form-container">
<h2>Hola <%= username %>!</h2>
<p>Estas en el panel de administración</p>
<button id="close-session">Cerrar sesión</button>
</div>
<% } %> <% if (typeof username === 'undefined' ) { %>
<div class="form-container">
<form id="login-form">
<h2>Login</h2>
<label for="login-username">Username</label>
<input type="text" id="login-username" name="username" required />

<labe for="login-password">Password</labe>
<input type="password" id="login-password" name="password" required />

<button type="submit">Login</button>
<span>&nbsp;</span>
</form>
</div>
<div class="form-container">
<form id="register-form">
<h2>Register</h2>

<label for="register-username">Username </label>
<input type="text" id="register-username" name="username" required />

<label for="register-password">Password</label>
<input type="password" id="register-password" name="password" required />

<label for="register-confirm-password">Confirm Password</label>
<input type="password" id="register-confirm-password" name="confirm-password" required />

<button type="submit">Register</button>
<span>&nbsp;</span>
</form>
</div>
<% } %>
</div>
<script>
const $ = (el) => document.querySelector(el)

const loginForm = $('#login-form')
const loginSpan = $('#login-form span')

const registerForm = $(' #register-form')
const registerSpan = $('#register-form span')

const logoutButton = $('#close-session')

loginForm?.addEventListener('submit', (e) => {
e.preventDefault()
const username = $('#login-username').value
const password = $('#login-password').value

fetch('/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ username, password }),
}).then((res) => {
if (res.ok) {
loginSpan.innerText = 'Sesión iniciada… Entering…'
loginForm.style.color = 'green'
setTimeout(() => {
window.location.href = '/protected'
}, 2000)
} else {
loginSpan.innerText = 'Error al iniciar sesión'
loginSpan.style.color = 'red'
}
})
})

registerForm?.addEventListener('submit', (e) => {
e.preventDefault()

const username = $('#register-username').value
const password = $('#register-password').value
const confirmPassword = $('#register-confirm-password').value

if (password !== confirmPassword) {
alert('Passwords do not match')
return
}

fetch('/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},

body: JSON.stringify({ username, password }),
}).then((res) => {
console.log(res)
if (res.ok) {
registerSpan.innerText = 'Usuario registrado. Entrando … '
registerSpan.style.color = 'green'
setTimeout(() => {
window.location.href = '/protected'
}, 2000)
} else {
registerSpan.innerText = 'Error al registrar usuario'
registerSpan.style.color = 'red'
}
})
})

logoutButton?.addEventListener('click', (e) => {
e.preventDefault()
fetch('/logout', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
}).then((res) => {
console.log(res)
window.location.href = '/'
})
})
</script>
</body>
</html>
`

@TheFernilo
1 month ago

En el repo no esta esta clase , alguien la tiene para compartir?

@eribertmarquez452
1 month ago

¿Cuando es la proxima clase?

@ismontech
1 month ago

Cool

@JacinMontava
1 month ago

Esta parte esta subida al repo? No lo encuentro, alguien tiene la URL?

@joseangel3915
1 month ago

Hola, alguien sabe donde puedo encontrar el codigo de de esta clase? Estuve viendo el portafolio y ahi no esta

@nauzet.dev_
1 month ago

Aufenfiticacisión

@joaquinsotelo1285
1 month ago

Me acabo de dar cuenta que no le di like a este videaso, 👍👍 ahi va mi rey,

@moralebianco
1 month ago

Por favor el siguiente vídeo del curso!

@sergiostebanpgx
1 month ago

Midu!, gracias por este gran contenido, ¿Qué fuentes utilizas en el VSC?

@CarlosCG_4U
1 month ago

¿Podrias compartir el 'index.ejs'?

@mclovin_2475
1 month ago

estas toro midu

@FrancoRiwi
1 month ago

Grande Midu! Tienes mi gratitud! Saludos desde Colombia!

@TMaxPowerT
1 month ago

Midu ayuda, se borran mi token cada vez que refresco la pagina, alguien aqui auxilio