Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Autenticazione JWT in un'applicazione Node.js con Express e MongoDB

Costruire un sistema di login sicuro in Node.js usando Express, MongoDB per memorizzare gli utenti e JWT per gestire l'autenticazione.
Costruire un sistema di login sicuro in Node.js usando Express, MongoDB per memorizzare gli utenti e JWT per gestire l'autenticazione.
Link copiato negli appunti

Quando si sviluppano applicazioni web, gestire in modo sicuro l'autenticazione degli utenti è essenziale. In questo contesto, JWT (JSON Web Token) è una delle soluzioni più moderne ed efficaci per l'autenticazione stateless, cioè senza sessioni salvate sul server.

In questa guida vedremo come costruire un sistema di login sicuro in Node.js usando Express, MongoDB per memorizzare gli utenti e JWT per gestire l'autenticazione.

Cosa useremo

  • Node.js e Express per il server.
  • MongoDB e Mongoose per gestire gli utenti.
  • bcrypt per criptare le password.
  • jsonwebtoken per firmare e verificare i token JWT.
  • dotenv per gestire le variabili d’ambiente.

Setup del progetto

Creiamo il progetto e installiamo i pacchetti:

mkdir jwt-auth-app
cd jwt-auth-app
npm init -y
npm install express mongoose bcrypt jsonwebtoken dotenv

Creiamo anche il file .env:

PORT=3000
MONGO_URI=mongodb://localhost:27017/jwt_auth_db
JWT_SECRET=supersegreto123

Struttura del progetto

jwt-auth-app/
├── models/
│ └── User.js
├── routes/
│ └── auth.js
├── middleware/
│ └── auth.js
├── .env
├── server.js
└── package.json

Configuriamo il server su server.js:

const express = require('express');
const mongoose = require('mongoose');
const dotenv = require('dotenv');
dotenv.config();

const authRoutes = require('./routes/auth');
const app = express();
app.use(express.json());

mongoose.connect(process.env.MONGO_URI)
.then(() => console.log("Connesso a MongoDB"))
.catch(err => console.error(err));
app.use('/api/auth', authRoutes);

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

Creiamo poi il modello utente con models/User.js:

const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
 email: { type: String, required: true, unique: true },
 password: { type: String, required: true }
});

module.exports = mongoose.model('User', userSchema);

Rotte di autenticazione con routes/auth.js

const express = require('express');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const User = require('../models/User');
const router = express.Router();

// REGISTRAZIONE
router.post('/register', async (req, res) => {
 const { email, password } = req.body;
 try {
  const userExist = await User.findOne({ email });
  if (userExist) return res.status(400).json({ message: "Utente già esistente" });

  const hashedPassword = await bcrypt.hash(password, 10);
  const newUser = new User({ email, password: hashedPassword });
  await newUser.save();

  res.status(201).json({ message: "Registrazione completata" });
 } catch (err) {
  res.status(500).json({ message: "Errore nel server" });
 }
});
// LOGIN
router.post('/login', async (req, res) => {
 const { email, password } = req.body;

 try {
  const user = await User.findOne({ email });
  if (!user) return res.status(404).json({ message: "Utente non trovato" });
   const match = await bcrypt.compare(password, user.password);
   if (!match) return res.status(401).json({ message: "Password errata" });

   const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET, { expiresIn: '1h' });
   res.json({ token });
  } catch (err) {
  res.status(500).json({ message: "Errore nel server" });
 }
});
module.exports = router;

Middleware di protezione middleware/auth.js

Questo middleware serve per proteggere le rotte private:

const jwt = require('jsonwebtoken');

function authenticateToken(req, res, next) {
 const authHeader = req.headers['authorization'];
 const token = authHeader && authHeader.split(' ')[1]; // Bearer
 if (!token) return res.status(401).json({ message: 'Accesso negato' });

 jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
  if (err) return res.status(403).json({ message: 'Token non valido' });
   req.user = user;
  next();
 });
}
module.exports = authenticateToken;

Rotta protetta (esempio)

Nel tuo routes/auth.js, puoi aggiungere una rotta privata:

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

router.get('/profile', authenticateToken, async (req, res) => {
 const user = await User.findById(req.user.id).select('-password');
  res.json(user);
});

Con questa rotta, solo chi ha un token valido può accedere alle informazioni dell'utente.

Come funziona tutto insieme?

  1. L'utente si registra inviando email e password.
  2. La password viene criptata con bcrypt.
  3. Quando fa il login, la password viene confrontata.
  4. Se tutto è corretto, il server genera un token JWT.
  5. L'utente usa quel token per accedere a rotte protette.
  6. Il token viene verificato ad ogni richiesta per garantire la sicurezza.

Test con Postman o frontend

Puoi testare tutto con Postman:

  • POST /api/auth/register
    Body (JSON): { "email": "test@email.com", "password": "123456" }

  • POST /api/auth/login
  • GET /api/auth/profile
    Headers → Authorization: Bearer

Vantaggi dell’uso di JWT

  • Stateless: nessuna sessione salvata lato server.
  • Scalabile: adatto ad architetture moderne come microservizi.
  • Sicuro: i token sono firmati e, se configurati bene, difficili da falsificare.
  • Versatile: possono contenere payload personalizzati (es. ruolo, ID, email, ecc.).

Estensioni e miglioramenti

Se vuoi espandere questo sistema puoi:

  • Aggiungere il refresh token per una sicurezza maggiore.
  • Impostare ruoli e permessi nel JWT.
  • Utilizzare HTTPS per proteggere i token in transito.
  • Salvare il token in cookie HttpOnly per protezione XSS.
  • Collegare a un frontend (React, Vue, ecc.).

Conclusione

L'autenticazione basata su JWT (JSON Web Token) rappresenta oggi uno degli approcci più adottati nello sviluppo di applicazioni moderne, specialmente in ambito RESTful e SPA (Single Page Application). In questa guida abbiamo visto come implementare passo dopo passo un sistema di login e protezione delle rotte, usando Node.js, Express, MongoDB e una combinazione di strumenti come bcrypt e jsonwebtoken per garantire la sicurezza dei dati e la facilità di utilizzo.

La semplicità con cui i JWT possono essere generati, inviati e verificati li rende estremamente adatti per architetture distribuite e scalabili, dove più servizi o client devono comunicare in modo sicuro senza dover fare affidamento su sessioni lato server. L'approccio stateless favorisce anche la scalabilità verticale e orizzontale dell'applicazione, rendendola perfetta per ambienti in cloud o microservizi.

Con la protezione delle rotte tramite middleware, hai anche imparato come creare zone sicure all'interno dell'applicazione, accessibili solo da utenti autenticati. E grazie all'uso di Mongoose e MongoDB, hai visto come creare e gestire un modello utente semplice ma efficace.

Ovviamente, quanto mostrato in questa guida rappresenta una base solida, ma è solo l'inizio. In progetti reali è importante considerare ulteriori accorgimenti per rafforzare la sicurezza, come ad esempio:

  • Gestione dei refresh token per sessioni più durature e sicure.
  • Controllo degli accessi basato su ruoli (RBAC).
  • Rate limiting e protezione da brute force durante il login.
  • Salvataggio dei token in cookie HttpOnly per evitare attacchi XSS.
  • Logging e tracciamento delle attività dell’utente per motivi di auditing.
  • Implementazione di sistemi di reset password e verifica email.

Integrare JWT con frontend moderni come React, Vue o Angular è molto semplice, e ti permetterà di costruire esperienze utente fluide, reattive e sicure.

In definitiva, padroneggiare l'autenticazione con JWT in un ambiente Node.js è una competenza fondamentale per qualsiasi sviluppatore backend. Ti apre le porte a moltissimi progetti reali, professionali e commerciali. Con le conoscenze di oggi sei in grado di costruire un sistema di autenticazione robusto, personalizzabile e in linea con le best practices del web moderno.

Ti consigliamo anche