auth_decorator.py 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. """Authentication decorator for protecting API endpoints."""
  2. from functools import wraps
  3. from flask import request
  4. import jwt
  5. from app.services.auth_service import AuthService
  6. def require_auth(f):
  7. """Decorator to require JWT authentication for an endpoint.
  8. Validates the Authorization header contains a valid JWT token.
  9. Sets request.current_admin with the decoded token payload if valid.
  10. Returns:
  11. 401 Unauthorized if token is missing, expired, or invalid
  12. """
  13. @wraps(f)
  14. def decorated(*args, **kwargs):
  15. auth_header = request.headers.get('Authorization', '')
  16. # Check for Bearer token
  17. if not auth_header:
  18. return {
  19. 'success': False,
  20. 'error': 'Authentication required',
  21. 'code': 'UNAUTHORIZED'
  22. }, 401
  23. # Extract token from "Bearer <token>" format
  24. parts = auth_header.split()
  25. if len(parts) != 2 or parts[0].lower() != 'bearer':
  26. return {
  27. 'success': False,
  28. 'error': 'Invalid authorization header format',
  29. 'code': 'INVALID_TOKEN'
  30. }, 401
  31. token = parts[1]
  32. try:
  33. payload = AuthService.verify_token(token)
  34. request.current_admin = payload
  35. except jwt.ExpiredSignatureError:
  36. return {
  37. 'success': False,
  38. 'error': 'Token expired',
  39. 'code': 'TOKEN_EXPIRED'
  40. }, 401
  41. except jwt.InvalidTokenError:
  42. return {
  43. 'success': False,
  44. 'error': 'Invalid token',
  45. 'code': 'INVALID_TOKEN'
  46. }, 401
  47. return f(*args, **kwargs)
  48. return decorated