How to Build an OAuth Client Credentials Mock Server in Python
A minimal HTTP mock server implementing the OAuth 2.0 client credentials grant for local testing and microservice development.
Python code
37 linesfrom http.server import HTTPServer, BaseHTTPRequestHandler
import json
TOKENS = {"valid_token": "demo_access_token", "client_id": "my_service"}
class OAuthHandler(BaseHTTPRequestHandler):
def do_POST(self):
if self.path == "/oauth/token":
length = int(self.headers.get("Content-Length", 0))
body = json.loads(self.rfile.read(length)) if length else {}
if body.get("grant_type") == "client_credentials" and body.get("client_id") == "my_service":
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.end_headers()
self.wfile.write(json.dumps({
"access_token": TOKENS["valid_token"],
"token_type": "Bearer",
"expires_in": 3600
}).encode())
else:
self.send_response(401)
self.end_headers()
self.wfile.write(json.dumps({"error": "invalid_client"}).encode())
else:
self.send_response(404)
self.end_headers()
def log_message(self, format, *args):
pass # suppress default logging for cleaner output
def run_server(port=8000):
server = HTTPServer(("localhost", port), OAuthHandler)
print(f"Mock OAuth server running on http://localhost:{port}")
server.serve_forever()
if __name__ == "__main__":
run_server()
Output
Mock OAuth server running on http://localhost:8000
When a POST request is sent to /oauth/token with:
{"grant_type": "client_credentials", "client_id": "my_service"}
The server responds with:
{"access_token": "demo_access_token", "token_type": "Bearer", "expires_in": 3600}
How it works
This mock server uses Python's built-in http.server module to create a lightweight HTTP endpoint that simulates an OAuth token service. The HTTPServer class handles the networking layer, while BaseHTTPRequestHandler provides the request/response lifecycle. Client credentials flow is implemented by checking the grant_type and client_id fields in the POST body — if they match, a token payload is returned with a 200 status; otherwise, a 401 is sent. Hardcoded token data keeps the mock deterministic and fast, making it ideal for integration tests where you don't want to hit a real OAuth provider.
Common mistakes
- Forgetting to set Content-Type header to application/json for API responses
- Not reading the request body fully before responding, causing connection issues on keep-alive
- Hardcoding port 8000 without making it configurable can cause port conflicts
- Returning 200 with a token even for invalid credentials instead of 401
Variations
- Use `flask` with `@app.route('/oauth/token', methods=['POST'])` for a more feature-rich framework
- Use `FastAPI` with Pydantic models to validate request bodies automatically
Real-world use cases
- Simulating an OAuth provider in integration tests to verify microservice auth flows without network calls.
- Providing a local stub token endpoint for contract testing service-to-service authentication.
- Speeding up development by giving front-end teams a mock identity server for API mocking.
Sponsored
More from Microservices patterns
- BFF aggregation pattern: combine multiple service responses in Python easy
- Backward Compatible Schema Evolution in Python medium
- Bulkhead Thread Pool per Service Mock in Python medium
- CQRS with Separate Read and Write Repositories in Python medium
- Cache-Aside Pattern in Python: Per-Service Mock easy
- Consumer Driven Contract Pact Mock in Python medium
Keep learning
Related tutorials and quizzes for this topic.