File size: 4,629 Bytes
8b7b267 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
"""
HuggingFace Space Authentication
Authentication middleware for HuggingFace Space API endpoints
CRITICAL RULES:
- Verify HF_TOKEN from environment
- Return error if token missing or invalid
- NO bypass - authentication is REQUIRED
"""
import os
import logging
from fastapi import Security, HTTPException, status, Header
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from typing import Optional
logger = logging.getLogger(__name__)
# Get HF_TOKEN from environment - REQUIRED for authentication
HF_TOKEN_ENV = os.getenv("HF_TOKEN") or os.getenv("HUGGINGFACE_TOKEN")
# CRITICAL: TEST MODE for development/testing
TEST_MODE = os.getenv("TEST_MODE", "false").lower() == "true"
if TEST_MODE:
logger.warning("=" * 80)
logger.warning("🧪 TEST MODE ACTIVE - Authentication bypass enabled!")
logger.warning(" Set TEST_MODE=false in production")
logger.warning("=" * 80)
# Security scheme
security = HTTPBearer(auto_error=False)
async def verify_hf_token(
credentials: Optional[HTTPAuthorizationCredentials] = Security(security),
authorization: Optional[str] = Header(None)
) -> bool:
"""
Verify HuggingFace API token
CRITICAL RULES:
1. MUST check credentials from Bearer token OR Authorization header
2. MUST compare with HF_TOKEN from environment
3. MUST return 401 if token missing or invalid
4. NO fake authentication - REAL token verification ONLY
Args:
credentials: HTTP Bearer token credentials
authorization: Authorization header (fallback)
Returns:
bool: True if authenticated
Raises:
HTTPException: 401 if authentication fails
"""
# Get token from credentials or header
provided_token = None
if credentials:
provided_token = credentials.credentials
elif authorization:
# Handle "Bearer TOKEN" format
if authorization.startswith("Bearer "):
provided_token = authorization[7:]
else:
provided_token = authorization
# CRITICAL: Allow bypass in TEST_MODE for development
if TEST_MODE:
logger.info("✅ TEST MODE: Authentication bypassed")
return {
"user_id": "test_user",
"username": "test_user",
"test_mode": True,
"access_level": "full",
"note": "TEST_MODE active - no real authentication"
}
# If no token provided, return 401
if not provided_token:
logger.warning("Authentication failed: No token provided")
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail={
"success": False,
"error": "Authentication required. Please provide HF_TOKEN in Authorization header.",
"source": "hf_engine",
"hint": "For development: Set TEST_MODE=true in .env"
},
headers={"WWW-Authenticate": "Bearer"}
)
# If HF_TOKEN not configured in environment, return 401
if not HF_TOKEN_ENV:
logger.error("HF_TOKEN not configured in environment")
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail={
"success": False,
"error": "HF_TOKEN not configured on server. Please set HF_TOKEN environment variable.",
"source": "hf_engine"
}
)
# Verify token matches
# CRITICAL: This is REAL token verification - NO bypass
if provided_token != HF_TOKEN_ENV:
logger.warning(f"Authentication failed: Invalid token provided (length: {len(provided_token)})")
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail={
"success": False,
"error": "Invalid authentication token",
"source": "hf_engine"
},
headers={"WWW-Authenticate": "Bearer"}
)
# Token is valid
logger.info("Authentication successful")
return True
async def optional_hf_token(
credentials: Optional[HTTPAuthorizationCredentials] = Security(security),
authorization: Optional[str] = Header(None)
) -> Optional[bool]:
"""
Optional HF token verification (for endpoints that can work without auth)
Returns:
Optional[bool]: True if authenticated, None if no token provided
"""
try:
return await verify_hf_token(credentials, authorization)
except HTTPException:
# Return None if authentication fails (optional mode)
return None
|