DEV Community

Tanmay Gupta
Tanmay Gupta

Posted on

Cookie Auth vs Bearer Token in Express – What's the Difference and When to Use Each?

When building secure Express.js applications, you’ll likely face a key architectural choice:
Should you use cookie-based authentication or bearer tokens like JWTs?

Each method has unique advantages depending on your frontend, deployment, and security requirements. In this post, we’ll break it down clearly and practically.


Why It Matters

  • Defines how your app handles sessions and security
  • Impacts frontend integration, especially for SPAs
  • Affects protection against attacks like CSRF and XSS
  • Determines whether tokens are sent automatically or manually

Option 1: Cookie-Based Authentication

How It Works

  • Server sets a cookie containing a session ID or JWT
  • Browser stores it and automatically sends it with every request — if configured correctly
res.cookie('token', jwtToken, {
  httpOnly: true,
  secure: true,
  sameSite: 'Strict'
});
Enter fullscreen mode Exit fullscreen mode

To access it:

import cookieParser from 'cookie-parser';
app.use(cookieParser());

app.get('/dashboard', (req, res) => {
  const token = req.cookies.token;
});
Enter fullscreen mode Exit fullscreen mode

When Are Cookies Sent Automatically?

Cookies are included in requests when:

  • The origin matches the cookie's domain
  • sameSite allows the request (Lax, Strict, or None)
  • credentials: 'include' is used in fetch/axios for cross-origin requests
  • Connection is over HTTPS if secure: true
fetch('http://api.example.com/user', {
  credentials: 'include'
});
Enter fullscreen mode Exit fullscreen mode

Option 2: Bearer Token Authentication (JWT)

How It Works

  • Client stores token manually (e.g., in localStorage)
  • Token is explicitly added to the Authorization header
fetch('/api/protected', {
  headers: {
    Authorization: `Bearer ${token}`
  }
});
Enter fullscreen mode Exit fullscreen mode

On the backend:

const authHeader = req.headers.authorization;
const token = authHeader?.split(' ')[1];
Enter fullscreen mode Exit fullscreen mode

Cookie vs Bearer Token: Quick Comparison

Feature Cookie Auth Bearer Token (JWT)
Auto-sent by browser Yes No
Ideal for Web apps / SSR / same-origin APIs / mobile / cross-origin
Requires CSRF tokens Yes (if not using SameSite) No
Vulnerable to XSS No (if HttpOnly) Yes (if stored in JS)
Cross-origin support Needs config Easier

When to Use Which

Use Cookie Auth if:

  • You’re building a browser-first app (SSR or same-origin SPA)
  • You want session management without manually handling tokens in JS
  • You plan to use HttpOnly cookies for security

Use Bearer Token if:

  • You need to support mobile apps, external clients, or third-party integrations
  • You're building a fully decoupled frontend/backend
  • You prefer handling tokens explicitly in headers

Real-World Example: Cross-Origin Cookie Setup

Backend:

res.cookie('token', jwtToken, {
  httpOnly: true,
  secure: true,
  sameSite: 'None'
});
Enter fullscreen mode Exit fullscreen mode

Frontend:

fetch('http://api.example.com/data', {
  credentials: 'include'
});
Enter fullscreen mode Exit fullscreen mode

Final Thoughts

There’s no one-size-fits-all.
Cookies excel at browser-based workflows, especially when using HttpOnly and SameSite.
Bearer tokens give you flexibility, especially across different platforms or APIs.

Both are secure when implemented correctly — just make sure you understand the browser behavior, attack vectors, and configuration nuances.

Top comments (0)