Heim > Web-Frontend > js-Tutorial > Der richtige Weg zur Authentifizierung in Node.js [uide]

Der richtige Weg zur Authentifizierung in Node.js [uide]

Barbara Streisand
Freigeben: 2024-12-12 20:08:17
Original
639 Leute haben es durchsucht

The Right Way to do Authentication in Node.js [uide]

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:

  • Voll funktionsfähige Authentifizierung mit Benutzername und Passwort.
  • Integration mit PostgreSQL zum Speichern von Benutzerkonten.
  • Eine JWT-basierte Authentifizierungs-Middleware.
  • Aktualisieren Sie Token mit automatischer Wiederverwendungserkennung für mehr Sicherheit.

Dieser Leitfaden konzentriert sich auf Einfachheit und vermeidet die Verwendung von Paketen wie „passport.js“, um die Komplexität zu reduzieren.


Einrichten der Benutzerkontentabelle

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()
);
Nach dem Login kopieren

JWT-Authentifizierungs-Middleware

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.

Middleware-Code (/src/middleware/jwt.ts):

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;
};
Nach dem Login kopieren

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 });
});
Nach dem Login kopieren

Authentifizierungscontroller erstellen

Jetzt implementieren Sie Controller für die Anmeldung und Anmeldung:

Anmeldecontroller:

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 };
};
Nach dem Login kopieren

Login-Controller:

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();
};
Nach dem Login kopieren

Speichern von Aktualisierungstoken

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()
);
Nach dem Login kopieren

Token-Generatoren:

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;
};
Nach dem Login kopieren

Token-Logik aktualisieren:

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();
  }
};
Nach dem Login kopieren

Erfahren Sie mehr über Aktualisierungstokens und die automatische Wiederverwendungserkennung in diesem Auth0-Artikel.


Abschluss

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!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage