API Keys — Complete Implementation Security Guide
In this tutorial, you will learn about API Keys. We cover key concepts, practical examples, and best practices to help you master this topic.
API keys are unique identifiers issued to clients for authenticating API requests. They are simpler than OAuth 2.0 but require careful management to prevent abuse.
What You'll Learn
You'll learn how to generate, validate, and rotate API keys securely, and how to prevent common API key vulnerabilities.
Why It Matters
API keys are everywhere -- from Stripe to OpenAI to Google Maps. A leaked API key can cost thousands of dollars in unauthorized usage or expose sensitive data.
Real-World Use
A weather data service issues API keys to developers. Each key tracks usage, enforces rate limits, and can be revoked if the developer violates terms. Keys are passed in HTTP headers, not URLs.
flowchart LR
A[Developer] --> B[Register Account]
B --> C[Generate API Key]
C --> D[Store Key Securely]
D --> E[Client Makes Request]
E --> F{API Key in Header?}
F -->|Yes| G{Key Valid?}
F -->|No| H[401 Unauthorized]
G -->|Yes| I{Within Rate Limit?}
G -->|No| J[403 Invalid Key]
I -->|Yes| K[Process Request]
I -->|No| L[429 Too Many Requests]
Teacher's Mindset
An API key is like a library card. It identifies who you are, tracks what you borrow (API calls), and can be revoked if you damage books. Never share your library card with strangers.
Implementing Secure API Keys
import hashlib
import secrets
from datetime import datetime
def generate_api_key():
raw_key = f"doda_{secrets.token_urlsafe(32)}"
hashed_key = hashlib.sha256(raw_key.encode()).hexdigest()
return raw_key, hashed_key
def validate_api_key(api_key, stored_hashes):
hashed = hashlib.sha256(api_key.encode()).hexdigest()
return hashed in stored_hashes
raw_key, hashed_key = generate_api_key()
print(f"Show once: {raw_key}")
print(f"Store hash: {hashed_key}")
from flask import Flask, request, jsonify
from functools import wraps
app = Flask(__name__)
API_KEYS = {
"abc123hash": {"client": "Acme Corp", "rate_limit": 1000}
}
def require_api_key(f):
@wraps(f)
def decorated(*args, **kwargs):
api_key = request.headers.get("X-API-Key")
if not api_key:
return jsonify({"error": "Missing API key"}), 401
hashed = hashlib.sha256(api_key.encode()).hexdigest()
if hashed not in API_KEYS:
return jsonify({"error": "Invalid API key"}), 403
return f(*args, **kwargs)
return decorated
@app.route("/api/data")
@require_api_key
def get_data():
return jsonify({"data": "sensitive"})
# Key rotation
def rotate_api_key(client_id, old_key_hash):
new_raw, new_hash = generate_api_key()
API_KEYS[new_hash] = API_KEYS.pop(old_key_hash)
return new_raw
def revoke_api_key(key_hash):
if key_hash in API_KEYS:
del API_KEYS[key_hash]
return True
return False
Common Mistakes
| Mistake | Why It's Wrong | Fix |
|---|---|---|
| Including API key in URL | Logged in server logs, exposed in referrer headers | Always pass API key in HTTP header |
| Storing keys in plain text | Data breach exposes all keys | Hash keys with SHA-256 before storing |
| Never rotating keys | Compromised keys remain valid forever | Implement key rotation every 90 days |
| No granular permissions | One key has full access to everything | Support scoped keys with limited permissions |
| Sending keys in client-side code | Keys visible in browser dev tools | Use backend proxy for third-party API calls |
Practice Questions
- Why should API keys be hashed before storage?
- What is the safest way to pass an API key in an HTTP request?
- How does key rotation improve security?
- What are scoped API keys?
- How do you detect a leaked API key?
Challenge
Build an API key management system with key generation, hashing, validation, scoping (read/write/admin), revocation, and usage tracking.
FAQ
Mini Project
Create an API key dashboard: generate scoped keys, hash them for storage, validate on every request, track usage, and provide key rotation. Include an audit log.
What's Next
Learn about Rate Limiting from a security perspective to prevent API abuse.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro