Token-Based Authentication — Complete Stateless Auth Guide
In this tutorial, you will learn about Token. We cover key concepts, practical examples, and best practices to help you master this topic.
Token-based authentication issues a signed token upon login, which the client includes in subsequent requests. The server validates the token's signature without storing session state.
What You'll Learn
You'll learn how token-based auth works, its advantages over sessions, and how to implement it securely.
Why It Matters
Token auth scales horizontally without shared session storage, works natively with mobile apps, and integrates seamlessly with third-party services.
Real-World Use
A Microservices deployment with 20 services uses JWT tokens. Each service validates tokens independently using a shared public key. No centralized session store is needed.
sequenceDiagram
participant Client
participant Auth as Auth Service
participant API as API Service
Client->>Auth: POST /login
Auth->>Client: Signed Token
Client->>API: GET /resource (Bearer token)
API->>API: Verify signature
API->>Client: Resource data
Teacher's Mindset
Token-based auth is like a stamped concert wristband. The server stamps it (signs it) once, and any staff member can verify the stamp without calling the box office.
Implementation
import jwt
from datetime import datetime, timedelta
from flask import Flask, request, jsonify
from functools import wraps
app = Flask(__name__)
SECRET = "your-256-bit-secret"
def create_token(user_id, role):
payload = {
"sub": user_id,
"role": role,
"iat": datetime.utcnow(),
"exp": datetime.utcnow() + timedelta(hours=1)
}
return jwt.encode(payload, SECRET, algorithm="HS256")
def require_token(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = request.headers.get("Authorization", "")
if not auth.startswith("Bearer "):
return jsonify({"error": "Missing token"}), 401
try:
token = auth.split(" ")[1]
payload = jwt.decode(token, SECRET, algorithms=["HS256"])
request.user = payload
except jwt.ExpiredSignatureError:
return jsonify({"error": "Token expired"}), 401
except jwt.InvalidTokenError:
return jsonify({"error": "Invalid token"}), 401
return f(*args, **kwargs)
return decorated
@app.route("/api/login", methods=["POST"])
def login():
token = create_token("user123", "admin")
return jsonify({"access_token": token, "token_type": "Bearer"})
@app.route("/api/protected")
@require_token
def protected():
return jsonify({"user": request.user})
Common Mistakes
| Mistake | Fix |
|---|---|
| No token expiration | Set exp claim to 15-60 minutes |
| Storing tokens in localStorage (XSS vulnerable) | Use HttpOnly cookies for web apps |
| No token revocation mechanism | Implement blocklist or short expiry |
| Including sensitive data in token | Never put passwords or PII in payload |
| Not validating signature | Always verify signature with correct secret |
Practice Questions
- Why is token auth considered stateless?
- How do you revoke a token before expiration?
- What information should a token contain?
- How do you handle token refresh?
- What is the difference between opaque and self-contained tokens?
Challenge
Implement token-based auth with RS256 (asymmetric signing). Generate an RSA key pair. Sign tokens with the private key and verify with the public key on a separate service.
What's Next
Deep-dive into JWT authentication with best practices.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro