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