TL;DR
Secure communication between web services within your project using API keys and a shared secret. This guide shows you how to generate, store, and verify these keys for robust authentication.
Generating API Keys
- Choose a Key Generation Method: Use a cryptographically secure random string generator. Avoid simple sequential IDs.
python import secrets import string def generate_api_key(length=32): alphabet = string.ascii_letters + string.digits return ''.join(secrets.choice(alphabet) for i in range(length)) api_key = generate_api_key() print(api_key) - Store the Shared Secret: Keep a strong, randomly generated secret key securely on your server. This is used to sign and verify API requests. Do not hardcode it into your application! Environment variables or a dedicated secrets management system are best.
# Example using environment variable SHARED_SECRET = os.environ.get('API_SHARED_SECRET') - Associate Keys with Services: Link each generated API key to the specific web service that owns it. Store this mapping in your database.
Example Database Table:
api_key (VARCHAR) - Primary Keyservice_name (VARCHAR)created_at (TIMESTAMP)
Authentication Process
- Request Signing: When a web service makes a request to another, it includes the API key and a signature. The signature is created using the shared secret and the request data.
import hmac import hashlib import time def create_signature(api_key, shared_secret, timestamp): message = f'{api_key}{timestamp}'.encode('utf-8') signature = hmac.new(shared_secret.encode('utf-8'), message, hashlib.sha256).hexdigest() return signature # Example usage: timestamp = str(int(time.time())) signature = create_signature("your_api_key", "your_shared_secret", timestamp) print(f"Signature: {signature}") - Include Signature in Request: Add the API key and signature as headers to your HTTP request.
Example Headers:
X-API-Key: your_api_keyX-API-Timestamp: timestampX-API-Signature: signature
- Verification on Receiving Service: The receiving web service verifies the signature using its copy of the shared secret.
def verify_signature(api_key, shared_secret, timestamp, signature): expected_signature = create_signature(api_key, shared_secret, timestamp) return hmac.compare_digest(signature, expected_signature) # Use compare_digest for security - Check Key Existence: Before verifying the signature, confirm that the API key exists in your database and is associated with the calling service.
This prevents unauthorized access even if a valid signature is provided.
Security Considerations
- HTTPS: Always use HTTPS to encrypt communication between services.
- Timestamp Expiration: Limit the validity of timestamps (e.g., requests older than 5 minutes are rejected) to prevent replay attacks.
- Rate Limiting: Implement rate limiting to protect against abuse.
- Shared Secret Rotation: Regularly rotate your shared secret to minimize the impact of a potential compromise.
- Compare Digests: Use
hmac.compare_digest()instead of direct string comparison for signature verification to prevent timing attacks.

