Authentifizierung ist einer der kritischsten, aber oft missverstandenen Aspekte der Backend-Entwicklung. Aufgrund seiner Komplexität greifen Entwickler häufig auf Lösungen von Drittanbietern wie Auth0 oder Supabase zurück. Obwohl dies hervorragende Tools sind, kann der Aufbau eines eigenen Authentifizierungssystems für mehr Flexibilität und Kontrolle sorgen.
In diesem Leitfaden erfahren Sie, wie Sie eine einfache Authentifizierungs-Middleware für Ihren Express.js-API-Dienst mit minimalen Abhängigkeiten implementieren. Am Ende haben Sie:
Dieser Leitfaden konzentriert sich auf Einfachheit und vermeidet die Verwendung von Paketen wie „passport.js“, um die Komplexität zu reduzieren.
Erstellen Sie zunächst eine PostgreSQL-Tabelle zum Speichern von Benutzerkonten:
CREATE TABLE users ( "id" SERIAL PRIMARY KEY, "username" VARCHAR(255) UNIQUE NOT NULL, "password" VARCHAR(255) NOT NULL, "email" VARCHAR(255) UNIQUE, "created_at" TIMESTAMP NOT NULL DEFAULT NOW() );
Als nächstes erstellen Sie eine JWT-Authentifizierungs-Middleware, um API-Endpunkte zu schützen. In diesem Beispiel wird die symmetrische Verschlüsselung verwendet. Erwägen Sie für Microservices-Architekturen die Verwendung einer asymmetrischen Verschlüsselung mit einem öffentlichen/privaten Schlüsselpaar.
import jwt from "jsonwebtoken"; const JWT_SECRET_KEY = process.env.JWT_SECRET_KEY as string; // Randomly generated. Min length: 64 characters export const protectedRoute: RequestHandler = async (req, _, next) => { const authHeader = req.header("authorization"); if (!authHeader) { return next(notAuthenticated()); } const accessToken = authHeader.replace(new RegExp("\b[Bb]earer\s"), ""); try { const { userId } = validateJWT(accessToken); const user = await userRepository.getUserById(parseInt(userId)); if (user) { req.user = user; next(); } else { next(invalidAccessToken()); } } catch (err) { next(invalidAccessToken()); } }; const validateJWT = (token: string, verifyOptions?: jwt.VerifyOptions) => { const jwtVerifyOptions = Object.assign( { algorithms: "HS256" }, verifyOptions, { issuer: "yourAPI.com", audience: "yourAPI.com:client", } ); return jwt.verify(token, JWT_SECRET_KEY, jwtVerifyOptions) as T; };
Verwenden Sie die Middleware, um Routen zu sichern:
import { protectedRoute } from "@/middleware/jwt"; router.get("/user", protectedRoute, async (req, res, next) => { const user = req.user!; res.json({ user }); });
Jetzt implementieren Sie Controller für die Anmeldung und Anmeldung:
import argon from "argon2"; const signup = async (props) => { const { username, password, email } = props; await userRepo.getUser(username).then((res) => { if (res !== null) throw usernameNotAvailable(); }); const hashedPass = await argon.hash(password, { timeCost: 2, parallelism: 1, memoryCost: 19456, }); const newUser = await createUser({ username, hashedPass, email, }); const refreshToken = await generateRefreshToken(newUser.userId); const accessToken = generateAccessToken(newUser.userId); const { password: _, ...userRes } = newUser; return { user: userRes, accessToken, refreshToken }; };
const login = async (props) => { const { username, password } = props; const user = await getUser(username).then((res) => { if (res === null) throw invalidLoginCredentials(); return res; }); const isOk = await argon.verify(user.password, password); if (isOk) { const refreshToken = await generateRefreshToken(user.userId); const accessToken = generateAccessToken(user.userId); const { password: _, ...userRes } = user; return { user: userRes, accessToken, refreshToken }; } throw invalidLoginCredentials(); };
Aktualisierungstoken bieten eine langfristige Authentifizierung. Erstellen wir eine Datenbanktabelle, um sie zu speichern:
CREATE TABLE refresh_tokens ( "id" SERIAL PRIMARY KEY, "token" UUID NOT NULL DEFAULT gen_random_uuid(), "token_family" UUID NOT NULL DEFAULT gen_random_uuid(), "user_id" INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, "active" BOOLEAN DEFAULT true, "expires_at" TIMESTAMP NOT NULL, "created_at" TIMESTAMP NOT NULL DEFAULT NOW() );
import jwt from "jsonwebtoken"; const JWT_SECRET_KEY = process.env.JWT_SECRET_KEY as string; // Randomly generated. Min length: 64 characters const generateAccessToken = (userId: number) => { const jwtSignOptions = Object.assign( { algorithm: "HS256" }, {}, { issuer: "yourAPI.com", audience: "yourAPI.com:client", } ); return jwt.sign({ userId: userId.toString() }, JWT_SECRET_KEY, jwtSignOptions); }; const generateRefreshToken = async (userId: number, tokenFamily?: string) => { const expAt = new Date(new Date().getTime() + 31 * 24 * 60 * 60 * 1000); // Expire in 31 days const refreshTokenExp = expAt.toISOString(); const token = await createTokenQuery({ userId, tokenFamily, expiresAt: refreshTokenExp, }); return token; };
Logik implementieren, um Aktualisierungstokens sicher zu verarbeiten:
const refreshToken = async ({ token }: RefreshTokenSchema) => { const tokenData = await getRefreshToken(token); if (!tokenData) throw forbiddenError(); const { userId, tokenFamily, active } = tokenData; if (active) { // Token is valid and hasn't been used yet const newRefreshToken = await generateRefreshToken(userId, tokenFamily); const accessToken = generateAccessToken(userId); return { accessToken, refreshToken: newRefreshToken }; } else { // Previously refreshed token used, invalidate all tokens in family await invalidateRefreshTokenFamily(tokenFamily); throw forbiddenError(); } };
Erfahren Sie mehr über Aktualisierungstokens und die automatische Wiederverwendungserkennung in diesem Auth0-Artikel.
Indem Sie dieser Anleitung folgen, haben Sie ein einfaches, sicheres Authentifizierungssystem für Ihre Node.js-API mit minimalen Abhängigkeiten erstellt. Dieser Ansatz stellt sicher, dass Sie die volle Kontrolle haben und moderne Best Practices für die Sicherheit einhalten.
Wenn Sie Zeit und Mühe sparen möchten, schauen Sie sich Vratix an. Unsere Open-Source-CLI kann in Sekundenschnelle ein voll funktionsfähiges Node.js-Projekt mit Authentifizierung einrichten. Entdecken Sie unser vollständig implementiertes Authentifizierungsmodul auf GitHub.
Hat Ihnen dieser Leitfaden geholfen? Lass es uns in den Kommentaren wissen oder vernetze dich mit uns auf X!
Das obige ist der detaillierte Inhalt vonDer richtige Weg zur Authentifizierung in Node.js [uide]. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!