Get a Pentest and security assessment of your IT network.

Cyber Security

Secure User Login: Cookies & JWT

TL;DR

Use HTTP-only cookies to store a refresh token and JWTs for authentication. Refresh tokens extend session life without repeatedly asking for passwords, while JWTs handle most requests. Prioritise security by rotating tokens and implementing proper expiry times.

1. Understanding the Problem

Keeping users logged in securely is tricky. Storing passwords directly is a huge no-no. Session IDs can be vulnerable to hijacking. Cookies are convenient but need careful handling. JWTs (JSON Web Tokens) offer a good solution, but they aren’t perfect on their own.

2. The Cookie & JWT Approach

This method combines the strengths of both cookies and JWTs:

  • JWT (Access Token): A short-lived token used for authenticating API requests.
  • Refresh Token: A longer-lived token stored in an HTTP-only cookie. Used to get new access tokens without re-entering credentials.

3. Step-by-Step Implementation

  1. User Login: When a user logs in successfully:
    • Generate both an Access Token (JWT) and a Refresh Token.
    • Set the Access Token in local storage or session storage on the client side.
    • Set the Refresh Token as an HTTP-only cookie with appropriate security flags (Secure, SameSite). This is crucial!
  2. Subsequent Requests: For each API request:
    • Include the Access Token in the Authorization header (e.g., Bearer <access_token>).
    • If the server detects an invalid or expired Access Token, return a 401 Unauthorized error.
  3. Token Refresh: When the Access Token expires:
    • The client sends a request to a dedicated token refresh endpoint with the Refresh Token (from the cookie).
    • The server validates the Refresh Token.
      • If valid, generate a new Access Token and a new Refresh Token.
      • Return the new Access Token to the client.
      • Set the new Refresh Token as an HTTP-only cookie (overwriting the old one).
  4. Logout: When a user logs out:
    • Delete both the Access Token from client storage.
    • Delete the Refresh Token by setting its expiry date in the past on the server side (or overwrite it with an invalid token).

4. Code Examples

These are simplified examples; adapt them to your specific framework and libraries.

Generating JWTs (Node.js with jsonwebtoken)

const jwt = require('jsonwebtoken');

function generateAccessToken(user) {
  return jwt.sign({ userId: user.id }, 'your_secret_key', { expiresIn: '15m' }); // Short expiry
}

function generateRefreshToken(user) {
  return jwt.sign({ userId: user.id }, 'your_refresh_secret_key', { expiresIn: '7d' }); // Longer expiry
}

Setting Cookies (Node.js with express)

const express = require('express');
const app = express();

app.post('/login', (req, res) => {
  // ... authentication logic...
  const accessToken = generateAccessToken(user);
  const refreshToken = generateRefreshToken(user);

  res.cookie('refreshToken', refreshToken, { httpOnly: true, secure: true, sameSite: 'strict' });
  res.json({ accessToken });
});

Validating Refresh Token (Node.js)

const jwt = require('jsonwebtoken');

function validateRefreshToken(refreshToken) {
  try {
    const decoded = jwt.verify(refreshToken, 'your_refresh_secret_key');
    return decoded;
  } catch (error) {
    return null; // Invalid token
  }
}

5. Security Considerations

  • HTTP-Only Cookies: Essential to prevent XSS attacks from accessing the Refresh Token.
  • Secure Flag: Ensure cookies are only sent over HTTPS.
  • SameSite Attribute: Protect against CSRF attacks (Strict is recommended).
  • Token Expiry Times: Keep Access Tokens short-lived and Refresh Tokens reasonably long, but not indefinite.
  • Refresh Token Rotation: Generate a new Refresh Token with each refresh request to limit the impact of compromised tokens.
  • Database Storage: Consider storing Refresh Tokens in a database (e.g., revoked tokens).
Related posts
Cyber Security

Zip Codes & PII: Are They Personal Data?

Cyber Security

Zero-Day Vulnerabilities: User Defence Guide

Cyber Security

Zero Knowledge Voting with Trusted Server

Cyber Security

ZeroNet: 51% Attack Risks & Mitigation