Skip to content

Authentication vs Authorization

“Auth” is often used loosely to mean both authentication and authorization. Understanding the difference between them is essential for building a secure API.

Authentication verifies identity. When a user logs in with a username and password, the server checks the credentials and confirms: “Yes, this is Alice.”

Authentication answers: Who is making this request?

Authorization controls access. Once the server knows who you are, it decides what you’re allowed to do: “Alice can edit her own posts but not Bob’s.”

Authorization answers: Is this person allowed to do this specific thing?

In Bulletin:

  • Authentication: verify username + password, issue a token
  • Authorization: only the post’s author can delete it, only authenticated users can post

A request without a token is unauthenticated — we don’t know who it is (401 Unauthorized). A request with a valid token from a user who doesn’t own the post is authenticated but unauthorized (403 Forbidden).

The traditional approach:

  1. User logs in — server creates a session record in a database
  2. Server sends the session ID in a cookie
  3. Browser sends the cookie with every subsequent request
  4. Server looks up the session ID in the database on each request

Pros: Easy to invalidate sessions (delete the record), works well for same-domain web apps.

Cons: Requires server-side session storage, harder to scale across multiple servers, cookie-based which adds CSRF complexity.

The stateless approach used by the Bulletin API:

  1. User logs in — server creates a signed token (JWT) containing the user’s ID
  2. Server sends the token to the client
  3. Client stores the token (localStorage or memory)
  4. Client sends the token in the Authorization: Bearer <token> header
  5. Server verifies the token’s signature — no database lookup needed

Pros: Stateless (no session storage), works across multiple servers and domains, natural for API + SPA architecture.

Cons: Tokens can’t be invalidated until they expire (without additional infrastructure), tokens live in JavaScript memory/storage (XSS risk).

For an API serving a React SPA (like Bulletin), JWT tokens are the standard choice:

  • The API and frontend can be on different domains
  • No shared session storage needed between API servers
  • React handles the token in state/localStorage

For traditional server-rendered web apps where the server and frontend are on the same domain, sessions are often simpler and safer.

POST /auth/register
Body: { username, password }
→ Hash password with bcrypt
→ Insert user into database
→ Sign and return JWT
POST /auth/login
Body: { username, password }
→ Find user by username
→ Compare password with bcrypt
→ Sign and return JWT
GET /posts (protected)
Header: Authorization: Bearer <token>
→ Verify JWT signature
→ Extract user ID from payload
→ User is authenticated — proceed

No code yet. Think through the Bulletin auth flow:

  1. What data should the JWT payload contain? (What does the API need to know about the current user?)
  2. What HTTP status code should a request with no token get? What about a request with a valid token but trying to delete someone else’s post?
  3. What happens if a token is stolen? How long should tokens be valid?
  • Authentication verifies identity (who are you?); authorization controls access (what can you do?).
  • 401 Unauthorized = not authenticated; 403 Forbidden = authenticated but not allowed.
  • Session-based auth stores state on the server; token-based auth (JWT) is stateless.
  • JWTs are ideal for APIs + SPAs: different domains, no shared session storage needed.