API Authentication Capstone Project — Full Auth System Implementation
In this tutorial, you will learn about API Authentication Capstone Project. We cover key concepts, practical examples, and best practices to help you master this topic.
Build a complete API authentication system that supports multiple authentication methods including API keys, JWT bearer tokens, OAuth2 integration, and multi-factor authentication.
Project Overview
You will build a Flask-based authentication service that powers a simulated threat intelligence API for Durga Antivirus Pro. The service must support internal service accounts (API keys), user sessions (JWT), third-party integrations (OAuth2), and sensitive operations (MFA step-up).
flowchart TD
A["API Auth System"] --> B["Service Accounts\nAPI Keys"]
A --> C["User Sessions\nJWT Tokens"]
A --> D["Third-Party\nOAuth2"]
A --> E["Sensitive Ops\nMFA Step-Up"]
B --> F["Threat Intelligence API"]
C --> F
D --> F
E --> F
style A fill:#dbeafe,stroke:#2563eb
style F fill:#dcfce7,stroke:#16a34a
Requirements
1. API Key Authentication
Create a key management system:
POST /api/v1/keys— Generate a new API key with scopesGET /api/v1/keys— List active keys (hash only)DELETE /api/v1/keys/<id>— Revoke a keyPOST /api/v1/keys/<id>/rotate— Rotate a key (new key, old one invalidated)
Store hashed keys with associated scopes and metadata.
2. JWT Authentication
Implement login and token management:
POST /api/v1/auth/login— Username/password returns access + refresh tokensPOST /api/v1/auth/refresh— Refresh token returns new access + refresh tokensPOST /api/v1/auth/logout— Invalidate refresh tokenGET /api/v1/auth/me— Return current user from JWT claims
Use 15-minute access tokens and 7-day refresh tokens with rotation.
3. OAuth2 Client Credentials
Support machine-to-machine auth:
POST /api/v1/oauth/token— Client credentials grant- Validate
client_idandclient_secret - Return scoped access tokens
4. MFA Step-Up
Protect sensitive operations:
POST /api/v1/mfa/setup— Generate TOTP secretPOST /api/v1/mfa/verify— Verify TOTP code- Sensitive endpoints require tokens with
mfa_verified: trueclaim
Starter Code
from flask import Flask, request, jsonify, g
from functools import wraps
import jwt, hashlib, secrets, datetime, pyotp
app = Flask(__name__)
SECRET = secrets.token_hex(32)
# In-memory stores (use Redis/DB in production)
api_keys = {}
refresh_tokens = {}
mfa_secrets = {}
# === MIDDLEWARE ===
def require_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
# Check API Key (X-API-Key header)
api_key = request.headers.get("X-API-Key")
if api_key:
key_hash = hashlib.sha256(api_key.encode()).hexdigest()
key_data = api_keys.get(key_hash)
if key_data and key_data.get("active"):
g.auth_type = "api_key"
g.scopes = key_data["scopes"]
return f(*args, **kwargs)
# Check Bearer JWT
auth = request.headers.get("Authorization", "")
if auth.startswith("Bearer "):
try:
payload = jwt.decode(
auth[7:], SECRET, algorithms=["HS256"]
)
g.auth_type = "jwt"
g.current_user = payload
g.scopes = payload.get("scope", "").split()
return f(*args, **kwargs)
except jwt.InvalidTokenError:
pass
return jsonify({"error": "Authentication required"}), 401
return decorated
# === API KEY ENDPOINTS ===
@app.route("/api/v1/keys", methods=["POST"])
def create_api_key():
data = request.get_json()
raw_key = f"sk-{secrets.token_hex(24)}"
key_hash = hashlib.sha256(raw_key.encode()).hexdigest()
api_keys[key_hash] = {
"name": data.get("name", "default"),
"scopes": data.get("scopes", ["threat:read"]),
"active": True,
"created": datetime.datetime.utcnow().isoformat()
}
return jsonify({"api_key": raw_key, "id": key_hash[:8]})
# === JWT ENDPOINTS ===
@app.route("/api/v1/auth/login", methods=["POST"])
def login():
data = request.get_json()
# Validate credentials (simplified)
if data.get("password") != "correct":
return jsonify({"error": "Invalid credentials"}), 401
access_token = jwt.encode({
"sub": data.get("username"),
"scope": "threat:read threat:write",
"exp": datetime.datetime.utcnow() + datetime.timedelta(minutes=15)
}, SECRET, algorithm="HS256")
refresh = secrets.token_urlsafe(32)
refresh_tokens[refresh] = {"user": data.get("username")}
return jsonify({
"access_token": access_token,
"refresh_token": refresh,
"expires_in": 900
})
# === YOUR TURN: Implement remaining endpoints ===
# 1. POST /api/v1/auth/refresh
# 2. POST /api/v1/auth/logout
# 3. POST /api/v1/oauth/token
# 4. POST /api/v1/mfa/setup
# 5. POST /api/v1/mfa/verify
# 6. Protected threat intelligence endpoints
if __name__ == "__main__":
app.run(debug=True)
What to Implement
Build these additional features:
- Refresh token rotation — issue new refresh token on each use, invalidate old one
- Scope enforcement — resource endpoints check
g.scopesagainst required scopes - MFA step-up — certain endpoints require
mfa_verifiedclaim in JWT - Rate Limiting — 5 attempts per minute on login, 100 requests per minute on API keys
- Audit logging — log all authentication attempts (success and failure) with timestamp, IP, method
Testing Your Project
# Test API Key auth
KEY=$(curl -s -X POST -H "Content-Type: application/json" \
-d '{"name":"test-key","scopes":["threat:read"]}' \
http://localhost:5000/api/v1/keys | python3 -c "import sys,json;print(json.load(sys.stdin)['api_key'])")
curl -H "X-API-Key: $KEY" http://localhost:5000/api/v1/threats
# Test JWT auth
TOKEN=$(curl -s -X POST -H "Content-Type: application/json" \
-d '{"username":"admin","password":"correct"}' \
http://localhost:5000/api/v1/auth/login | python3 -c "import sys,json;print(json.load(sys.stdin)['access_token'])")
curl -H "Authorization: Bearer $TOKEN" http://localhost:5000/api/v1/threats
Common Mistakes
1. Not Validating Scopes
API keys and JWT tokens have associated scopes. Every protected endpoint must check that the scope includes the required permission.
2. Missing Input Validation
Validate all input — email format, password strength, scope names, key names. Invalid input can cause security issues.
3. Not Handling Concurrent Token Refresh
If two requests refresh simultaneously, both may get new tokens. Use token families or detect race conditions.
4. Exposing Internal Error Details
Return generic error messages to clients. Log detailed errors server-side for debugging.
5. Forgetting HTTPS
Deploy behind HTTPS. Authentication without HTTPS is not authentication — it is theater.
Evaluation Criteria
| Requirement | Points |
|---|---|
| API key CRUD with hashed storage | 15 |
| JWT login with access + refresh tokens | 15 |
| Refresh token rotation | 15 |
| OAuth2 Client Credentials | 10 |
| MFA setup and step-up verification | 15 |
| Scope enforcement on all endpoints | 10 |
| Proper HTTP status codes | 5 |
| Error handling and validation | 5 |
| Audit logging | 5 |
| Code quality and documentation | 5 |
FAQ
What's Next
Congratulations on completing the API Authentication learning path! Continue to the JWT Complete Guide for an in-depth exploration of JSON Web Tokens.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro