Bearer-token authentication and state
Fast recall
Quick revision
Core answer
Whether the learner understands bearer semantics, opaque versus self-contained tokens, and revocation trade-offs.
Calling all token authentication stateless or treating a signed JWT as encrypted.
Cover transport, storage, expiry, scope, rotation, revocation, and the 401/403 boundary.
Interview-ready guide
Interview answer
A bearer token is a credential whose holder may present it to a protected API. The client normally sends Authorization: Bearer over HTTPS, and possession is enough to use it. The raw value must stay out of URLs, logs, analytics, and browser history, and client storage must match the platform threat model because a leaked token can be replayed until it expires or is revoked.
An opaque token is a random secret with no client-readable meaning. Store only its cryptographic hash and look it up on each request; that server state adds a lookup but makes individual revocation direct. A signed JWT carries readable claims and can be verified locally. Its signature protects integrity, not confidentiality, so private data does not belong in ordinary signed claims.
The API validates the token before using its identity and scope, then performs a separate authorization check for the requested action. An opaque-token store hashes the presented secret, finds an active record, checks expiry and scope, and loads current user or tenant state. The runnable example never stores or prints the usable token; deleting its hash revokes that credential immediately.
Local JWT verification can avoid an access-token row lookup, but the wider design is not automatically stateless. Refresh-token rotation, stolen-token revocation, disabled users, changed roles, and signing-key rotation often use current server data or accept access until a short token expires. Return 401 for an absent or invalid credential and 403 when a known identity lacks permission; authentication and authorization remain separate.
Bearer-token authentication and state
Direct Answer
In bearer-token authentication, a client presents a secret token—normally in the Authorization header—and possession is enough to use it, so TLS and leak prevention are essential. The design is not inherently stateless: opaque tokens require server-side lookup, and JWT systems often keep refresh, revocation, or account state even when access-token signatures are verified locally.
Deep Dive & Architecture
An opaque access token should be generated with enough randomness that guessing is infeasible. Store only a cryptographic hash, just as a password-reset system avoids storing the usable secret. On every request, hash the presented token and find an active record. The record can hold expiry, scopes, user, client, and revocation time. This adds a lookup but gives the server immediate control over one credential.
A signed JWT contains claims such as issuer, audience, subject, and expiration. A resource server validates the allowed algorithm, signature, issuer, audience, time claims, and any required scope before trusting it. Base64url-encoded claims are readable; signing prevents undetected modification but does not encrypt them. Sensitive private data does not belong in ordinary signed claims.
Local JWT validation can remove a central access-token lookup, yet the broader system often remains partly stateful. A user may be suspended after the token was issued, roles may change, refresh tokens need rotation and reuse detection, and emergency logout may require a deny list or token-version check. If the API skips all current checks, it consciously accepts access until the short-lived token expires.
The client also changes the threat model. Page URLs are a poor token transport because URLs commonly enter history and logs. Browser local storage is readable by injected script; an HttpOnly cookie prevents normal JavaScript reads but is sent automatically and therefore needs CSRF-aware design. Native applications should use platform-protected credential storage. Every bearer flow requires HTTPS.
On failure, an absent, expired, malformed, or unverifiable credential normally produces 401 with an appropriate authentication challenge. A valid identity that lacks permission produces 403. Logs may record a token identifier or request correlation value, never the bearer secret itself. Good token design combines short lifetime, narrow audience and scope, safe storage, rotation, revocation policy, and explicit authorization.
A threat model should name who issues the token, which service accepts it, how clock skew is handled, and what happens after theft. Those answers determine lifetime, audience, storage, and revocation; choosing JWT first and discovering these requirements later reverses the design process.
Code Example
require "digest"
class ApiController < ActionController::API
before_action :authenticate_token!
private
def authenticate_token!
scheme, secret = request.authorization.to_s.split(" ", 2)
return head :unauthorized unless scheme&.casecmp?("Bearer") && secret
digest = Digest::SHA256.hexdigest(secret)
token = AccessToken.active.find_by(token_digest: digest)
return head :unauthorized unless token
@current_user = token.user
end
end
This opaque-token design deliberately performs a database lookup, so it is revocable and stateful rather than inherently stateless.
Common Mistakes & Pitfalls
Calling all token authentication stateless or treating a signed JWT as encrypted.
Check your understanding
Answer these without looking back at the article.
- What is the difference between an opaque token and a JWT?
- Why should bearer tokens not appear in query strings?
- How would you revoke a short-lived JWT before it expires?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.