█
LastWrite
  • > Curriculum
  • > Pricing
  • > For Educators
  • > About
  • > Contact
Log InGet Started

Questions, concerns, bug reports, or suggestions? We read every message, write to us at [email protected].

More ways to reach us →
LastWrite

Structured computer science lessons for aspiring developers and security professionals.

[email protected]

(201) 785-7951

Mon–Fri, 9 AM–5 PM EST

Learn

  • Curriculum
  • Pricing

Company

  • About
  • For Educators & Schools
  • Contact Us

Legal

  • Terms of Service
  • Privacy Policy
© 2026 LastWrite. All rights reserved.
Curriculum/Programming Languages/Node.js/Authentication in Node
55 minIntermediate

Authentication in Node

After this lesson, you will be able to: Implement auth in Node: sessions vs JWT, OAuth flows, modern auth libraries (Lucia / Auth.js).

Auth is the most-screwed-up area of backend dev. Knowing the right defaults saves real users.

Prerequisites:REST API Design

Sessions vs JWT

Session (server-state): server stores session ID → user. Cookie sends ID. Revocable by deleting server-side. Default in most production apps. JWT (stateless): token contains user + signature. Server verifies signature; no lookup. Revocation needs a denylist or short TTL. Default: sessions in a cookie unless you have a specific reason for JWT (microservices, mobile apps).

Session-based auth (Lucia or your own)

Modern lightweight setup.

python
// Lucia (TypeScript-first; works with any DB)
import { Lucia } from "lucia";
import { BetterSqlite3Adapter } from "@lucia-auth/adapter-sqlite";
const lucia = new Lucia(
new BetterSqlite3Adapter(db, { user: "users", session: "sessions" }),
{
sessionCookie: {
attributes: { secure: process.env.NODE_ENV === "production" },
},
}
);
// Login: validate password, then
const session = await lucia.createSession(userId, {});
const cookie = lucia.createSessionCookie(session.id);
res.setHeader("Set-Cookie", cookie.serialize());
// Auth middleware: read cookie, validate, attach user
const cookieHeader = req.headers.cookie;
const sessionId = lucia.readSessionCookie(cookieHeader ?? "");
if (sessionId) {
const { user, session } = await lucia.validateSession(sessionId);
req.user = user;
}

OAuth 2.0 (Sign in with Google etc)

Use a library, never roll your own OAuth.

python
// Auth.js (next-auth)
import NextAuth from "next-auth";
import Google from "next-auth/providers/google";
export const { handlers, auth, signIn, signOut } = NextAuth({
providers: [
Google({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
}),
],
});
// For non-Next: Lucia + arctic (oauth helper library)
// Or Passport.js if you must use Express middleware

What to NEVER do

Store JWT in localStorage. XSS = token theft. Use httpOnly cookies. Use SHA-256 / MD5 for passwords. Use bcrypt / argon2. Roll your own OAuth. Use a library. Skip CSRF protection. SameSite=Lax cookies + Origin check (LastWrite style) are the modern minimum.

Quick Check

Why store auth tokens in httpOnly cookies instead of localStorage?

Pick the security reason.

Sign in and purchase access to unlock this lesson.

Sign in to purchase
←REST API Design with Express / Fastify
Back to Node.js
Working with Databases from Node→