Come impostare l'autenticazione Passport in un'applicazione Node e Postgres
Inizia a utilizzare Passport.js per autenticare la tua webapp del nodo con il minimo sforzo.
In qualità di sviluppatore, è tua responsabilità salvaguardare i dati dei tuoi utenti tramite l'autenticazione. Puoi utilizzare Passport.js per autenticare gli utenti in un'applicazione Node e Postgres.
Inizia creando un server Node con endpoint per registrare, accedere e disconnettere gli utenti. Puoi consentire a Passport di gestire l'autenticazione per limitare l'accesso non autorizzato alla tua applicazione.
Creazione di una tabella utenti
Per l'autenticazione dell'utente, utilizzerai un'e-mail e una password. Ciò significa che la tabella utenti deve contenere un campo email e un campo password. Nel prompt dei comandi psql, crea un nuovo database chiamato nodeapp:
CREATE DATABASE nodeapp;
Successivamente, crea una tabella per archiviare gli utenti:
CREATE TABLE users (
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
email CHAR(128),
password CHAR(60)
);
Questo codice creerà una nuova tabella contenente e-mail, password e un campo ID generato automaticamente.
Creazione di un server nodo
Node.js è un ambiente runtime JavaScript lato server che ci consente di creare rapidamente server HTTP. Per semplificare il processo di creazione del server e dei diversi percorsi HTTP, è possibile utilizzare Express, un framework web Node.js.
Esegui questo comando per creare una nuova cartella chiamata postgres-auth:
mkdir postgres-auth
Successivamente, inizializza npm:
npm init -y
Infine, installa Express:
npm install express
Ora puoi creare il server web Node.
In un nuovo file chiamato index.js, aggiungi quanto segue:
const express = require("express");
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.listen(3000, () => console.log("Listening on port 3000"));
L'esecuzione di questo codice avvierà il server e registrerà quanto segue nella console:
Listening on port 3000
Connessione a PostgreSQL
Per connetterti a PostgreSQL usa node-postgres. node-postgres è un driver di connessione che fornisce un'interfaccia tra Node e Postgres.
Eseguire quanto segue per installare node-postrges tramite npm:
npm install pg
Una volta installata la libreria, crea un nuovo file chiamato db.js e collegalo al database:
const { Client } = require("pg");
const { user, host, database, password, port } = require("./dbConfig");
const client = new Client({
user,
host,
database,
password,
port,
});
client.connect();
module.exports = client;
Il metodo client di node-postgres prende i dettagli del database a cui ti stai connettendo. Questo programma importa i dettagli della connessione da un file chiamato dbConfig. Pertanto, crea quel file e aggiungivi il seguente codice:
module.exports = {
user: "postgres",
host: "localhost",
database: "nodeapp",
password: "yourPassword",
port: 5432,
};
Creare funzioni di supporto del database
È sempre buona norma utilizzare singole funzioni per interagire con il database. Semplificano la scrittura di unit test e migliorano la riusabilità. Per l'endpoint di registrazione, devi creare due funzioni:
- Per verificare se l'email è già registrata.
- Per creare l'utente.
L'obiettivo è registrare un utente solo se non esiste nel database.
Crea un nuovo file chiamato helper.js e importa il client del database da db.js:
const client = require("./db.js")
Successivamente, aggiungi una nuova funzione chiamata emailExists():
const emailExists = async (email) => {
const data = await client.query("SELECT * FROM users WHERE email=$1", [
email,
]);
if (data.rowCount == 0) return false;
return data.rows[0];
};
Questa funzione prende un'e-mail e controlla se è già in uso. Lo fa utilizzando la clausola SELECT che restituisce una riga che ha un campo email che corrisponde al valore fornito dall'utente registrato. Se l'e-mail non esiste, restituisce false.
Per creare una funzione che crea l'utente, aggiungi una funzione chiamata createUser() a helper.js:
const createUser = async (email, password) => {
const salt = await bcrypt.genSalt(10);
const hash = await bcrypt.hash(password, salt);
const data = await client.query(
"INSERT INTO users(email, password) VALUES ($1, $2) RETURNING id, email, password",
[email, hash]
);
if (data.rowCount == 0) return false;
return data.rows[0];
};
Questa funzione accetta i valori di email e password. Utilizza la clausola INSERT per creare una nuova riga con questi dettagli e, in caso di successo, restituisce l'utente appena creato. Tieni presente che prima di archiviare la password, dovresti eseguirne l'hashing utilizzando bcrypt. Non è mai una buona idea archiviare le password come testo semplice. Se gli hacker riuscissero ad accedere al tuo database utenti, potrebbero facilmente accedere a informazioni sensibili.
Installa bcryptjs per iniziare a usarlo:
npm install bcryptjs
In helper.js, importa bcryptjs:
const bcrypt = require("bcryptjs")
Utilizzando Bcryptjs, il database memorizza solo la password crittografata. Pertanto, durante l'accesso, sarà necessario confrontare la password in testo semplice fornita dall'utente e la password con hash nel database. Per questo, puoi utilizzare il metodo di confronto fornito da Bcryptjs.
Crea una funzione chiamata matchPassword():
const matchPassword = async (password, hashPassword) => {
const match = await bcrypt.compare(password, hashPassword);
return match
};
Riceve la password semplice e l'hash, quindi utilizza Bcrypt.compare() per determinare se la password fornita è corretta. Se lo è, restituisce vero, altrimenti restituisce falso.
Queste sono tutte le funzioni che utilizzeremo per interagire con il database. Assicurati di esportarli tutti alla fine:
module.exports = { emailExists, createUser, matchPassword };
Configura Passaporto
Passport è un middleware di autenticazione Node che fornisce oltre 500 strategie di autenticazione come accesso social, token Web JSON (JWT) e autenticazione e-mail. Utilizzeremo quest'ultima opzione fornita dalla strategia passaporto-locale.
Utilizza il comando seguente per installare Passport e Passport-local:
npm install passport
npm install passport-local
Successivamente, configura Passport per accedere agli utenti esistenti e registrare nuovi utenti.
Inizia creando un nuovo file passportConfig.js. Quindi, importa la strategia locale di Passport e le funzioni di supporto del database che hai appena creato:
const LocalStrategy = require("passport-local");
const { emailExists, createUser, matchPassword } = require("./helper");
Nello stesso file aggiungi quanto segue per impostare l'iscrizione dell'utente:
module.exports = (passport) => {
passport.use(
"local-signup",
new LocalStrategy(
{
usernameField: "email",
passwordField: "password",
},
async (email, password, done) => {
try {
const userExists = await emailExists(email)
if (userExists) {
return done(null, false);
}
const user = await createUser(email, password);
return done(null, user);
} catch (error) {
done(error);
}
}
)
);
}
Poiché Passport-Local richiede un nome utente e una password e stai utilizzando un'e-mail, imposta il campo del nome utente su un'e-mail. L'utente o meglio la parte frontend di questa applicazione invierà l'e-mail e la password nel corpo della richiesta. Tuttavia, non è necessario estrarre personalmente i valori poiché Passport lo gestirà in background.
Questo programma controlla innanzitutto se l'e-mail è già stata ricevuta utilizzando la funzione emailExists() di helper.js. Se l'e-mail non esiste nel database, crea un nuovo utente con la funzione createUser(). Infine, restituisce l'oggetto utente.
Per accedere agli utenti, aggiungi quanto segue a PassportConfig.js:
module.exports = (passport) => {
passport.use(
"local-signup",
new LocalStrategy(
// sign up
)
);
passport.use(
"local-login",
new LocalStrategy(
{
usernameField: "email",
passwordField: "password",
},
async (email, password, done) => {
try {
const user = await emailExists(email);
if (!user) return done(null, false);
const isMatch = await matchPassword(password, user.password);
if (!isMatch) return done(null, false);
return done(null, {id: user.id, email: user.email});
} catch (error) {
return done(error, false);
}
}
)
);
};
Qui il programma controlla innanzitutto se l'e-mail è registrata. In caso contrario, restituisce false. Se trova l'e-mail, confronta la sua password con quella della richiesta. Se le password corrispondono, accede all'utente e restituisce l'oggetto utente.
Il passaggio finale consiste nel creare gli endpoint API:
- POST /autenticazione/iscrizione
- POST /auth/login
Entrambi questi endpoint riceveranno un'e-mail e una password nel corpo della richiesta. Includeranno anche le funzioni middleware di autenticazione del passaporto che abbiamo appena configurato.
Importa e configura Passport in un nuovo file denominato server.js:
const passport = require("passport");
require("./passportConfig")(passport);
Quindi, aggiungi i seguenti percorsi:
app.post(
"/auth/signup",
passport.authenticate("local-signup", { session: false }),
(req, res, next) => {
res.json({
user: req.user,
});
}
);
app.post(
"/auth/login",
passport.authenticate("local-login", { session: false }),
(req, res, next) => {
res.json({ user: req.user });
}
);
Entrambi questi percorsi restituiscono un oggetto JSON contenente l'utente in caso di esito positivo.
Controlla la tua API utilizzando i test unitari
Puoi utilizzare Passport per autenticare un'applicazione Node utilizzando un'applicazione PostgreSQL. Hai creato endpoint API per registrare e accedere agli utenti.
Sebbene sia possibile utilizzare client REST come Postman per testare il funzionamento di un'API, scrivere test unitari è molto più semplice. I test unitari ti consentono di testare le singole parti della tua applicazione. In questo modo, anche se un endpoint fallisce, puoi individuare il punto esatto del guasto. Uno degli strumenti che puoi utilizzare per testare le applicazioni Node è Jest.