This prompt helps you (and your AI) to implementing Hanko with Python.
## Add Hanko to Python Backend
**Purpose:** Enforce only the **current** and **correct** instructions for integrating [Hanko](https://hanko.io/) session validation into a Python backend application.
**Scope:** All AI-generated advice or code related to Hanko must follow these guardrails for server-side session validation in Python.
---
## **1. Official Hanko Integration Overview**
Use only the **current** approach from Hanko's documentation:
- **Validate** session tokens using Hanko's `/sessions/validate` POST endpoint
- **Extract** session tokens from HTTP cookies (typically named "hanko")
- **Use** Python requests library or similar HTTP client for validation
- **Implement** proper error handling with try/except blocks
- **Create** reusable validation functions or classes
- **Handle** JSON responses from validation endpoint correctly
- **Configure** Hanko API URL from environment variables
- **Return** boolean values from validation functions
---
## **2. CRITICAL INSTRUCTIONS FOR AI MODELS**
### **2.1 – ALWAYS DO THE FOLLOWING**
1. **Use POST method** for `/sessions/validate` endpoint (never GET)
2. **Send JSON payload** with `session_token` field in request body
3. **Check HTTP status codes** before parsing JSON responses
4. **Use try/except blocks** for all HTTP requests and JSON parsing
5. **Import requests library** or equivalent HTTP client for API calls
6. **Extract tokens from cookies** using Flask/Django cookie methods
7. **Return boolean values** from validation functions for clear results
8. **Configure API URLs** from environment variables (os.environ)
9. **Handle None/empty tokens** by returning False immediately
10. **Log validation errors** appropriately without exposing sensitive data
### **2.2 – NEVER DO THE FOLLOWING**
1. **Do not** use GET method for session validation (must be POST)
2. **Do not** send tokens in URL parameters or query strings
3. **Do not** skip error handling for HTTP requests or JSON parsing
4. **Do not** trust validation without checking HTTP status codes
5. **Do not** hardcode API URLs in production code
6. **Do not** expose internal validation errors to client responses
7. **Do not** skip None/empty token checks before making requests
8. **Do not** use synchronous requests in async frameworks without proper handling
---
## **3. CORRECT IMPLEMENTATION PATTERNS**
### **Basic Validation Function**
```python
import requests
import os
from typing import Optional
def validate_hanko_session(token: Optional[str]) -> bool:
"""Validate a Hanko session token."""
if not token:
return False
hanko_api_url = os.environ.get('HANKO_API_URL')
if not hanko_api_url:
raise ValueError('HANKO_API_URL environment variable not set')
try:
response = requests.post(
f'{hanko_api_url}/sessions/validate',
json={'session_token': token},
headers={'Content-Type': 'application/json'},
timeout=10
)
if response.status_code != 200:
return False
validation_data = response.json()
return validation_data.get('is_valid', False)
except (requests.RequestException, ValueError, KeyError) as e:
print(f'Token validation error: {e}')
return False
from flask import Flask, request, jsonify
from functools import wraps
import requests
import os
app = Flask(__name__)
def require_auth(f):
"""Decorator to require valid Hanko authentication."""
@wraps(f)
def decorated_function(*args, **kwargs):
# Extract token from cookies
token = request.cookies.get('hanko')
if not token:
return jsonify({'error': 'No session token provided'}), 401
if not validate_hanko_session(token):
return jsonify({'error': 'Invalid session token'}), 401
return f(*args, **kwargs)
return decorated_function
@app.route('/protected')
@require_auth
def protected_route():
return jsonify({'message': 'This is a protected route'})
def validate_hanko_session(token: str) -> bool:
"""Validate session token with Hanko API."""
if not token:
return False
hanko_api_url = os.environ.get('HANKO_API_URL')
try:
response = requests.post(
f'{hanko_api_url}/sessions/validate',
json={'session_token': token},
timeout=10
)
if response.status_code == 200:
return response.json().get('is_valid', False)
return False
except Exception as e:
print(f'Validation error: {e}')
return False
from django.http import JsonResponse
from django.utils.deprecation import MiddlewareMixin
import requests
import os
class HankoAuthMiddleware(MiddlewareMixin):
"""Django middleware for Hanko authentication."""
def process_request(self, request):
# Only protect specific paths
protected_paths = ['/api/protected/']
if not any(request.path.startswith(path) for path in protected_paths):
return None
token = request.COOKIES.get('hanko')
if not token:
return JsonResponse({'error': 'No session token'}, status=401)
if not self.validate_token(token):
return JsonResponse({'error': 'Invalid session'}, status=401)
return None
def validate_token(self, token: str) -> bool:
"""Validate token with Hanko API."""
hanko_api_url = os.environ.get('HANKO_API_URL')
try:
response = requests.post(
f'{hanko_api_url}/sessions/validate',
json={'session_token': token},
headers={'Content-Type': 'application/json'},
timeout=10
)
return response.status_code == 200 and response.json().get('is_valid', False)
except Exception:
return False
from fastapi import FastAPI, Depends, HTTPException, Request
import requests
import os
from typing import Optional
app = FastAPI()
async def get_current_user(request: Request) -> str:
"""FastAPI dependency for authentication."""
token = request.cookies.get('hanko')
if not token:
raise HTTPException(status_code=401, detail='No session token')
if not validate_hanko_session(token):
raise HTTPException(status_code=401, detail='Invalid session')
return token # or return user_id extracted from token
@app.get('/protected')
async def protected_route(current_user: str = Depends(get_current_user)):
return {'message': 'This is a protected route'}
def validate_hanko_session(token: str) -> bool:
"""Validate session token."""
hanko_api_url = os.environ.get('HANKO_API_URL')
try:
response = requests.post(
f'{hanko_api_url}/sessions/validate',
json={'session_token': token},
timeout=10
)
return response.status_code == 200 and response.json().get('is_valid', False)
except Exception:
return False
## ❌ DO NOT use GET method for validation
response = requests.get(f'{hanko_api_url}/sessions/validate?token={token}')
## ❌ DO NOT skip error handling
response = requests.post(url, json=data)
validation_data = response.json() # Could fail
## ❌ DO NOT forget to check status codes
validation_data = response.json()
return validation_data['is_valid'] # Could be error response
## ❌ DO NOT send tokens in URL path
response = requests.post(f'{hanko_api_url}/sessions/validate/{token}')
## ❌ DO NOT skip token existence check
def validate_token(token):
# Should check if token exists first
response = requests.post(...)
## ❌ DO NOT hardcode API URLs
response = requests.post('https://hardcoded-url.hanko.io/sessions/validate')
## ❌ DO NOT expose validation errors
except Exception as e:
return JsonResponse({'error': str(e)}, status=500) # Exposes internal errors
/sessions/validate
endpoint?session_token
field?
Was this page helpful?