How to Mock OAuth 2.0 Device Code Flow in Python
A mock implementation of the OAuth 2.0 device authorization grant for testing authentication flows without a real provider.
Python code
61 linesimport hashlib
import time
import uuid
class DeviceCodeFlowMock:
def __init__(self):
self.device_codes = {}
def request_device_code(self, client_id, scope="read write"):
device_code = uuid.uuid4().hex
user_code = str(uuid.uuid4().int)[:8].upper()
expires_in = 300
interval = 5
self.device_codes[device_code] = {
"status": "pending",
"created_at": time.time(),
"expires_in": expires_in,
"user_code": user_code,
"client_id": client_id,
"scope": scope,
}
return {
"device_code": device_code,
"user_code": user_code,
"verification_uri": "https://example.com/device",
"expires_in": expires_in,
"interval": interval,
}
def verify_user_code(self, user_code):
for device_code, details in self.device_codes.items():
if details["user_code"] == user_code and details["status"] == "pending":
if time.time() - details["created_at"] > details["expires_in"]:
details["status"] = "expired"
return False
details["status"] = "approved"
return True
return False
def poll_for_token(self, device_code):
details = self.device_codes.get(device_code)
if not details:
return {"error": "invalid_device_code"}
if time.time() - details["created_at"] > details["expires_in"]:
details["status"] = "expired"
return {"error": "expired_token"}
if details["status"] == "approved":
token = hashlib.sha256(device_code.encode()).hexdigest()
return {"access_token": token, "token_type": "Bearer", "expires_in": 3600}
if details["status"] == "pending":
return {"error": "authorization_pending"}
return {"error": "access_denied"}
if __name__ == "__main__":
flow = DeviceCodeFlowMock()
request = flow.request_device_code("client-123")
print("Device code request:", request)
print("User approval:", flow.verify_user_code(request["user_code"]))
print("Token response:", flow.poll_for_token(request["device_code"]))
Output
Device code request: {'device_code': 'f3a7c9e1b2d840a5b6c7d8e9f0a1b2c3', 'user_code': 'A1B2C3D4', 'verification_uri': 'https://example.com/device', 'expires_in': 300, 'interval': 5}
User approval: True
Token response: {'access_token': 'a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f2a1b0c9d8e7f6a5b4c3d2e1f0', 'token_type': 'Bearer', 'expires_in': 3600}
How it works
This mock class simulates the OAuth 2.0 device authorization grant, which lets users sign in on secondary devices like TVs or CLI tools. request_device_code creates a pending record and returns a user code plus verification URI. verify_user_code approves pending requests while enforcing expiry based on creation time. poll_for_token returns an approved token or appropriate error responses for pending, expired, or invalid states. Using a sha256 hash of the device code simulates a deterministic access token without a real authorization server.
Common mistakes
- Forgetting to handle expired tokens in both verification and polling methods
- Storing device codes in memory instead of a persistent store for multi-process production use
- Returning a real token instead of a mock one for testing purposes
Variations
- Use a database or Redis to persist device code states across multiple service instances
- Add JWT-based access tokens instead of simple hash digests for realistic token generation
Real-world use cases
- Testing CLI applications that require user browser-based authorization without a live OAuth provider
- Simulating device login flows for smart TVs or IoT devices during integration testing
- Creating a mock authentication service for local development and CI pipelines
Sponsored
More from Auth & security at scale
- ACME LetsEncrypt Mock Challenge Server in Python medium
- AES GCM encryption and decryption in Python medium
- Build a Mock OIDC Userinfo Endpoint in Python with Flask easy
- ChaCha20-Poly1305 mock in Python medium
- ECDH key agreement in Python with cryptography medium
- Enforce TLS 1.2 Minimum in Python easy
Keep learning
Related tutorials and quizzes for this topic.