API Key Authentication — Simple Token-Based Access for Public APIs
In this tutorial, you will learn about API Key Authentication. We cover key concepts, practical examples, and best practices to help you master this topic.
API key authentication uses a static token string that clients include in requests to identify themselves, offering a simple balance of security and usability for public APIs.
What You'll Learn
How API keys work, best practices for generation and transmission, security limitations, and when API keys are appropriate for your API.
Why It Matters
API keys are the most widely used authentication method for public APIs. Services like Google Maps, Stripe, and GitHub all use API keys. They provide simple access control without the complexity of OAuth2 or JWT.
Real-World Use
Google Cloud APIs use API keys for project identification, Stripe uses publishable and secret keys for different environments, and weather APIs use keys for usage tracking.
flowchart LR
A["Developer"] -->|"Requests API key"| B["API Portal"]
B -->|"Issues key: sk-abc123"| A
A -->|"Request + X-API-Key: sk-abc123"| C["API Server"]
C -->|"Validate key"| D["Key Database"]
D -->|"Valid"| E["200 OK + Data"]
D -->|"Invalid"| F["401 Unauthorized"]
style A fill:#dbeafe,stroke:#2563eb
style B fill:#fef3c7,stroke:#d97706
style C fill:#fef3c7,stroke:#d97706
style E fill:#dcfce7,stroke:#16a34a
style F fill:#fecaca,stroke:#dc2626
How API Keys Work
- Developer registers and requests an API key
- Server generates a unique key and stores a hash of it
- Developer includes the key in API requests (usually via header)
- Server looks up the key, validates it, and identifies the client
Transmission Methods
| Method | Example | Pros | Cons |
|---|---|---|---|
| Header | X-API-Key: sk-abc123 |
Not in logs or browser history | Requires custom header support |
| Query Param | ?api_key=sk-abc123 |
Simple for GET requests | Exposed in URLs, logs |
| Bearer Token | Authorization: Bearer sk-abc123 |
Standard header | Less semantic than X-API-Key |
Code Example: API Key Generation and Validation
import secrets
import hashlib
from flask import Flask, request, jsonify
app = Flask(__name__)
# In production, use a real database
valid_keys = {}
def generate_api_key():
key = f"sk-{secrets.token_hex(16)}"
key_hash = hashlib.sha256(key.encode()).hexdigest()
return key, key_hash
@app.route("/api/keys", methods=["POST"])
def create_key():
key, key_hash = generate_api_key()
valid_keys[key_hash] = {"owner": "user-123", "active": True}
return jsonify({"api_key": key})
def validate_api_key():
key = request.headers.get("X-API-Key")
if not key:
return None
key_hash = hashlib.sha256(key.encode()).hexdigest()
info = valid_keys.get(key_hash)
if info and info["active"]:
return info
return None
@app.route("/api/data")
def get_data():
client = validate_api_key()
if not client:
return jsonify({"error": "Invalid API key"}), 401
return jsonify({"data": "sensitive data", "client": client["owner"]})
if __name__ == "__main__":
app.run()
Expected output:
$ curl -X POST http://localhost:5000/api/keys
{"api_key":"sk-1a2b3c4d5e6f7g8h9i0j..."}
$ curl -H "X-API-Key: sk-1a2b3c4d5e6f7g8h9i0j..." http://localhost:5000/api/data
{"data":"sensitive data","client":"user-123"}
Code Example: Python Client
import requests
API_KEY = "sk-your-key-here"
headers = {"X-API-Key": API_KEY}
response = requests.get(
"https://api.example.com/v1/users",
headers=headers
)
if response.status_code == 200:
print(response.json())
elif response.status_code == 401:
print("Invalid or missing API key")
Code Example: Server-Side Rate Limiting with API Keys
from collections import defaultdict
import time
rate_limits = defaultdict(list)
MAX_REQUESTS = 100
WINDOW_SECONDS = 60
def check_rate_limit(api_key):
now = time.time()
window_start = now - WINDOW_SECONDS
requests = [t for t in rate_limits[api_key] if t > window_start]
rate_limits[api_key] = requests
if len(requests) >= MAX_REQUESTS:
return False
rate_limits[api_key].append(now)
return True
@app.route("/api/data")
def get_data_with_rate_limit():
key = request.headers.get("X-API-Key")
if not key:
return {"error": "Missing API key"}, 401
if not check_rate_limit(key):
return {"error": "Rate limit exceeded"}, 429
return {"data": "success"}
Common Mistakes
1. Exposing API Keys in Client-Side Code
API keys in mobile apps or JavaScript frontends can be extracted. Use a backend proxy or API key restrictions (HTTP referrers, IP addresses).
2. Storing Keys in Plain Text
Store a hash of the API key, not the key itself. If your database is breached, hashed keys cannot be used to make API calls.
3. Not Allowing Key Rotation
Users should be able to generate new keys and revoke old ones. Without rotation, a compromised key is valid forever.
4. Using API Keys for User Authentication
API keys identify applications, not users. They are not suitable for user-specific access control (e.g., "show my data"). Use JWT or OAuth2 for user auth.
5. Putting Keys in URLs
?api_key=abc123 exposes the key in server logs, browser history, and referrer headers. Always use headers.
Practice Questions
- Why should API keys be hashed before storage?
- What is the difference between a secret key and a publishable key?
- Why should API keys be transmitted via headers rather than query parameters?
- How can you restrict API key usage to specific domains?
- Can API keys identify individual users?
Answers:
- If the database is breached, hashed keys cannot be used directly. The server hashes the incoming key and compares hashes.
- Publishable keys (frontend) have limited permissions; secret keys (backend) have full access. This principle of Least Privilege limits damage if a key is exposed.
- Headers are less likely to appear in server logs, browser history, or referrer headers. URLs are visible in many places.
- During key creation, store allowed referrer domains or IP ranges. The server validates the request's Origin header against these restrictions.
- No — API keys identify applications. For user-specific identity, use JWT or OAuth2 tokens.
Challenge: Build an API key management system with key generation, hashed storage, key rotation, deactivation, and usage tracking. Include rate limits per key.
FAQ
Mini Project
Build a Flask API key management service with endpoints for creating, listing, revoking, and rotating keys. Store hashed keys in a dictionary (simulating a database) with rate limiting per key.
What's Next
Now that you understand API keys, learn about Token-Based Authentication which provides more flexibility with dynamic tokens.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro