Skip to content

sun1211/authentication-example

Repository files navigation

Node.js Authentication Methods - Complete Guide

Here's a comprehensive list of common authentication methods used in Node.js backends:

πŸ“‹ Table of Contents

  • Uses server-side sessions (stored in memory, Redis, or a database).
  • Relies on cookies (express-session + cookie-parser).
  • Libraries:
    • express-session βœ…
    • cookie-session
    • connect-redis (for Redis-based sessions)
  • Stateless authentication using digitally signed tokens.
  • Tokens are stored client-side (localStorage, cookies, or mobile storage).
  • Libraries:
    • jsonwebtoken (JWT)
    • passport-jwt (for JWT strategy in Passport.js)

3. OAuth 2.0 / OpenID Connect (OIDC)

  • Delegated authentication (e.g., "Login with Google/GitHub/Facebook").
  • Uses access tokens & refresh tokens.
  • Libraries:
    • passport-oauth2
    • openid-client
    • google-auth-library (for Google OAuth)

4. API Key Authentication

  • Simple authentication using a unique API key (often in headers or query params).
  • Used for server-to-server communication.
  • Libraries: Custom middleware or express-api-key-auth.

5. Basic Authentication

  • Uses username:password encoded in Base64 in the Authorization header.
  • Libraries:
    • express-basic-auth
    • Custom middleware with Buffer.from(req.headers.authorization, 'base64')

6. Passport.js (Middleware for Auth Strategies)

  • Supports multiple auth methods (Local, JWT, OAuth, etc.).
  • Strategies:
    • passport-local (username/password)
    • passport-jwt
    • passport-google-oauth20
    • passport-github

7. Magic Link / Passwordless Authentication

  • Users log in via a link sent to their email.
  • Libraries:
    • magic-link
    • Custom implementation with JWT + email service (Nodemailer).

8. Two-Factor Authentication (2FA) / Multi-Factor (MFA)

  • Uses TOTP (Time-Based OTP) or SMS-based verification.
  • Libraries:
    • speakeasy (TOTP)
    • node-2fa
    • Twilio (for SMS-based 2FA)

9. LDAP / Active Directory Authentication

  • Enterprise authentication (used in corporate environments).
  • Libraries:
    • ldapjs
    • passport-ldapauth

10. Social Logins (OAuth-based)

  • Login via Google, Facebook, GitHub, etc.
  • Libraries:
    • passport-google-oauth20
    • passport-facebook
    • passport-github2

11. Firebase Authentication

  • Managed auth service by Google (supports email, phone, social logins).
  • Library: firebase-admin

12. WebAuthn / FIDO2 (Passwordless & Biometric Auth)

  • Uses hardware security keys or biometrics (fingerprint, FaceID).
  • Libraries:
    • fido2-lib
    • simplewebauthn

Common Security Middleware

  • helmet (Secure HTTP headers)
  • bcrypt / argon2 (Password hashing)
  • rate-limiter-flexible (Prevent brute-force attacks)

1. Session-Based Authentication - Demo Example

A simple yet secure authentication system built with Express.js using session-based authentication, bcrypt password hashing, and TypeScript.

Features

  • βœ… User registration with password hashing
  • βœ… Session-based login/logout
  • βœ… Protected routes with middleware
  • βœ… Secure session configuration
  • βœ… TypeScript support
  • βœ… HTTP-only cookies for security

Running the Application

npm start 

The server will start on http://localhost:3000

Method Endpoint Description Protected
GET / API status and auth info No
POST /register Register new user No
POST /login User login No
POST /logout User logout No
GET /profile Get user profile Yes
GET /dashboard User dashboard Yes
GET /session Check session status No

πŸ” Session Management Deep Dive

1. Session Creation

Sessions are automatically created when users log in successfully:

// Login endpoint creates session app.post('/login', async (req: Request, res: Response) => { // ... password validation ... // 🎯 Session Creation req.session.userId = user.id; // Store user ID req.session.username = user.username; // Store username // Session cookie automatically sent to client });

What happens:

  • Server generates unique session ID
  • Session data stored server-side (memory by default)
  • Secure HTTP-only cookie sent to client with session ID
  • Client automatically sends cookie with future requests

2. Session Configuration & Timeout

app.use(session({ secret: 'your-secret-key-change-in-production', // πŸ”‘ Signs session cookies resave: false, // Don't save unchanged sessions saveUninitialized: false, // Don't save empty sessions cookie: { secure: false, // Set true for HTTPS in production httpOnly: true, // πŸ›‘οΈ Prevents XSS attacks maxAge: 24 * 60 * 60 * 1000 // ⏰ 24 hours timeout } }));

Session Timeout Options:

// Different timeout configurations maxAge: 30 * 60 * 1000, // 30 minutes maxAge: 2 * 60 * 60 * 1000, // 2 hours  maxAge: 24 * 60 * 60 * 1000, // 24 hours maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days

3. Session Verification

Every protected route uses the requireAuth middleware:

const requireAuth = (req: Request, res: Response, next: NextFunction) => { // πŸ” Session Verification if (req.session.userId) { next(); // βœ… Valid session - proceed } else { res.status(401).json({ error: 'Authentication required' }); // ❌ Invalid } }; // Apply to protected routes app.get('/dashboard', requireAuth, (req, res) => { // This only runs if session is valid });

4. Session Renewal

Session Renewal on Every Request

app.use(session({ secret: 'your-secret-key-change-in-production', resave: false, saveUninitialized: false, rolling: true, // Add this line cookie: { secure: false, httpOnly: true, maxAge: 24 * 60 * 60 * 1000 // 24 hours } }) as express.RequestHandler);

Manual Session Renewal:

const requireAuth = (req: Request, res: Response, next: NextFunction): void => { if (req.session.userId) { req.session.touch(); // This will save the session and renew the cookie next(); } else { res.status(401).json({ error: 'Authentication required' }); } };

5. Session Destruction

app.post('/logout', (req, res) => { req.session.destroy((err) => { if (err) { return res.status(500).json({ error: 'Logout failed' }); } // πŸ—‘οΈ Clear cookie from client res.clearCookie('connect.sid'); res.json({ message: 'Logout successful' }); }); });

πŸ”’ Security Features

Password Security

  • bcrypt hashing with salt rounds (10)
  • No plain text passwords stored
  • Secure comparison using bcrypt.compare()

Session Security

  • HTTP-only cookies - Prevents XSS attacks
  • Signed cookies - Prevents tampering
  • Secure flag - HTTPS only in production
  • Session expiration - Automatic timeout

Route Protection

  • Middleware-based authentication
  • Early exit for unauthorized requests
  • Generic error messages - No information leakage

πŸ—οΈ Session Data Storage Options

Memory Store (Default - Development Only)

// Current setup - sessions lost on server restart const users: User[] = []; // In-memory storage

⚠️ Not for production - Sessions lost on restart, won't scale

Redis Store (Recommended): See full implementation β†’

npm install connect-redis redis
import RedisStore from 'connect-redis'; import { createClient } from 'redis'; const redisClient = createClient(); redisClient.connect(); app.use(session({ store: new RedisStore({ client: redisClient }), // ... other options }));
npm install connect-mongo
import MongoStore from 'connect-mongo'; app.use(session({ store: MongoStore.create({ mongoUrl: 'mongodb://localhost:27017/sessions' }), // ... other options }));

PostgreSQL Store

npm install connect-pg-simple pg
import pgSession from 'connect-pg-simple'; const PostgreSQLStore = pgSession(session); app.use(session({ store: new PostgreSQLStore({ /* db config */ }), // ... other options }));

File Store

npm install session-file-store
import FileStore from 'session-file-store'; const FileStoreSession = FileStore(session); app.use(session({ store: new FileStoreSession({ path: './sessions' }), // ... other options }));

Quick Recommendations:

  • Development: Memory Store
  • Small Apps: File Store
  • Production: Redis Store
  • Existing DB: Match your database (MongoDB/PostgreSQL)

πŸ“Š Session Lifecycle

1. User Login β†’ 2. Session Created β†’ 3. Cookie Sent ↓ ↓ ↓ Credentials Server Storage Client Browser Validated userId: "123" connect.sid=abc... username: "john" 4. Future Requests β†’ 5. Session Verified β†’ 6. Access Granted ↓ ↓ ↓ Cookie Sent Check Storage Protected Route connect.sid=abc... Find Session Dashboard/Profile 7. Session Expires β†’ 8. Access Denied β†’ 9. Re-login Required ↓ ↓ ↓ TTL Reached 401 Error New Session Cycle Auto-cleanup Clear Cookie Fresh Start 

JWT Token-Based Authentication Demo

A simple Node.js + TypeScript demonstration of JWT-based authentication with Express.

πŸš€ Quick Start

# Install dependencies npm install express jsonwebtoken bcryptjs npm install -D @types/express @types/jsonwebtoken @types/bcryptjs @types/node typescript ts-node # Start server npx ts-node server.ts

Visit http://localhost:3000/demo for API instructions.

πŸ“‘ API Endpoints

Method Endpoint Description Auth Required
POST /register Register new user ❌
POST /login Login user ❌
GET /profile Get user profile βœ…
GET /demo API documentation ❌

πŸ”‘ JWT Flow

  1. Register/Login β†’ Receive JWT token
  2. Include token in Authorization: Bearer <token> header
  3. Access protected routes with valid token

πŸ“ Usage Examples

Register User

curl -X POST http://localhost:3000/register \ -H "Content-Type: application/json" \ -d '{"email":"demo@example.com","password":"password123"}'

Login User

curl -X POST http://localhost:3000/login \ -H "Content-Type: application/json" \ -d '{"email":"demo@example.com","password":"password123"}'

Access Protected Route

curl -X GET http://localhost:3000/profile \ -H "Authorization: Bearer YOUR_JWT_TOKEN"

πŸ›‘οΈ Security Features

  • Password Hashing: bcrypt with salt rounds
  • JWT Tokens: 1-hour expiration
  • Protected Routes: Middleware validation
  • Error Handling: Proper HTTP status codes

πŸ”§ Comprehensive JWT Guide

πŸ”‘ 1. Token Generation

Basic Syntax:

jwt.sign(payload, secret, options)

From Our Example:

const token = jwt.sign({ userId: user.id }, JWT_SECRET, { expiresIn: '1h' });

Detailed Breakdown:

  • payload: Data stored in token (user ID, role, permissions)
  • secret: Secret key for signing (keep secure!)
  • options: Configuration object for token behavior

⏰ 2. Expiration Configuration

String Format (Recommended):

{ expiresIn: '1h' } // 1 hour { expiresIn: '30m' } // 30 minutes  { expiresIn: '7d' } // 7 days { expiresIn: '2y' } // 2 years

Numeric Format (Seconds):

{ expiresIn: 3600 } // 3600 seconds = 1 hour

Using 'exp' Claim:

{ userId: 123, exp: Math.floor(Date.now() / 1000) + (60 * 60) // 1 hour from now }

βœ… 3. Token Verification

Basic Verification (Our Example):

try { const decoded = jwt.verify(token, JWT_SECRET) as any; req.userId = decoded.userId; } catch (error) { // Handle invalid/expired token }

With Options:

jwt.verify(token, JWT_SECRET, { issuer: 'my-app', // Must match token's issuer audience: 'api-users', // Must match token's audience  algorithms: ['HS256'], // Only allow specific algorithms clockTolerance: 30, // Allow 30 seconds clock skew maxAge: '1h' // Additional age limit });

❌ 4. Error Types

catch (error) { if (error instanceof jwt.TokenExpiredError) { // Token has expired } else if (error instanceof jwt.JsonWebTokenError) { // Invalid token format/signature } else if (error instanceof jwt.NotBeforeError) { // Token not active yet } }

πŸ”„ 5. Common Expiration Patterns

Access Tokens (Short-lived):

  • API Access: 15m - 1h
  • Sensitive Operations: 5m

Refresh Tokens (Long-lived):

  • Mobile Apps: 7d - 30d
  • Web Apps: 24h - 7d

Special Purpose:

  • Password Reset: 2h
  • Email Verification: 24h

πŸ›‘οΈ 6. Security Best Practices

Strong Secrets:

// Use environment variables const JWT_SECRET = process.env.JWT_SECRET; // Generate secure random secret const crypto = require('crypto'); const secret = crypto.randomBytes(64).toString('hex');

Minimal Payload:

// Good - minimal data { userId: 123, role: 'user' } // Bad - sensitive data { userId: 123, password: 'secret', creditCard: '1234' }

Token Pair Strategy:

// Short access token const accessToken = jwt.sign( { userId: 123, type: 'access' }, JWT_SECRET, { expiresIn: '15m' } ); // Long refresh token  const refreshToken = jwt.sign( { userId: 123, type: 'refresh' }, JWT_SECRET, { expiresIn: '7d' } );

πŸ“ 7. Complete Configuration Example

const token = jwt.sign( { userId: 123, email: 'user@example.com', role: 'admin' }, JWT_SECRET, { expiresIn: '1h', // Token expires in 1 hour issuer: 'my-application', // Who created this token audience: 'my-app-users', // Who can use this token subject: 'user-auth', // What this token is for algorithm: 'HS256', // Signing algorithm jwtid: 'unique-id-123' // Unique token identifier } );

🎯 Key Takeaways

  1. Keep secrets secure - use environment variables
  2. Use appropriate expiration times - balance security vs UX
  3. Handle errors properly - different error types need different responses
  4. Minimal payloads - don't store sensitive data
  5. Token refresh strategy - use short access + long refresh tokens
  6. Validate thoroughly - verify issuer, audience, algorithms

Releases

No releases published

Packages

 
 
 

Contributors