60 lines
1.7 KiB
Python
60 lines
1.7 KiB
Python
"""
|
|
Custom authentication classes for API key authentication.
|
|
"""
|
|
from rest_framework.authentication import BaseAuthentication
|
|
from rest_framework.exceptions import AuthenticationFailed
|
|
from django.contrib.auth import get_user_model
|
|
from django.core.cache import cache
|
|
import hashlib
|
|
|
|
User = get_user_model()
|
|
|
|
|
|
class APIKeyAuthentication(BaseAuthentication):
|
|
"""
|
|
Custom API key authentication for the platform.
|
|
"""
|
|
|
|
def authenticate(self, request):
|
|
api_key = self.get_api_key(request)
|
|
if not api_key:
|
|
return None
|
|
|
|
# Check cache first
|
|
user_id = cache.get(f'api_key_{api_key}')
|
|
if user_id:
|
|
try:
|
|
user = User.objects.get(id=user_id, is_api_enabled=True)
|
|
return (user, None)
|
|
except User.DoesNotExist:
|
|
pass
|
|
|
|
# Check database
|
|
try:
|
|
user = User.objects.get(api_key=api_key, is_api_enabled=True)
|
|
# Cache the result for 1 hour
|
|
cache.set(f'api_key_{api_key}', str(user.id), 3600)
|
|
return (user, None)
|
|
except User.DoesNotExist:
|
|
raise AuthenticationFailed('Invalid API key')
|
|
|
|
def get_api_key(self, request):
|
|
"""
|
|
Get API key from request headers.
|
|
"""
|
|
# Check X-API-Key header first
|
|
api_key = request.META.get('HTTP_X_API_KEY')
|
|
if api_key:
|
|
return api_key
|
|
|
|
# Check Authorization header as fallback
|
|
auth_header = request.META.get('HTTP_AUTHORIZATION', '')
|
|
if auth_header.startswith('ApiKey '):
|
|
return auth_header.split(' ')[1]
|
|
|
|
return None
|
|
|
|
def authenticate_header(self, request):
|
|
return 'ApiKey realm="api"'
|
|
|