File size: 2,735 Bytes
f171e60
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
from fastapi import Security, HTTPException, status, Depends
from fastapi.security import APIKeyHeader, HTTPBearer, HTTPAuthorizationCredentials
from typing import Optional
from app.config import settings
from app.utils.logger import logger

# API Key Authentication
api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False)

async def verify_api_key(api_key: str = Security(api_key_header)) -> str:
    """
    Verify API key từ header
    
    Args:
        api_key: API key từ X-API-Key header
        
    Returns:
        API key nếu valid
        
    Raises:
        HTTPException: Nếu API key invalid
    """
    if not settings.AUTH_ENABLED:
        return "auth-disabled"
    
    if not api_key:
        logger.warning("API request without API key")
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="API key is required",
            headers={"WWW-Authenticate": "ApiKey"},
        )
    
    if api_key not in settings.API_KEYS:
        logger.warning(
            f"Invalid API key attempted",
            extra={"api_key_prefix": api_key[:8] + "..."}
        )
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid API key",
            headers={"WWW-Authenticate": "ApiKey"},
        )
    
    logger.info(
        f"API key verified",
        extra={"api_key_prefix": api_key[:8] + "..."}
    )
    
    return api_key

# Bearer Token Authentication (for future JWT support)
bearer_scheme = HTTPBearer(auto_error=False)

async def verify_token(
    credentials: Optional[HTTPAuthorizationCredentials] = Depends(bearer_scheme)
) -> Optional[str]:
    """
    Verify bearer token (JWT)
    
    Args:
        credentials: Bearer token credentials
        
    Returns:
        Token payload nếu valid
        
    Raises:
        HTTPException: Nếu token invalid
    """
    if not settings.AUTH_ENABLED:
        return None
    
    if not credentials:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Authentication required",
            headers={"WWW-Authenticate": "Bearer"},
        )
    
    # TODO: Implement JWT token verification
    # For now, just return the token
    return credentials.credentials

# Optional authentication (không bắt buộc)
async def optional_api_key(api_key: Optional[str] = Security(api_key_header)) -> Optional[str]:
    """
    Optional API key verification
    Không raise error nếu không có key
    """
    if not settings.AUTH_ENABLED:
        return None
    
    if not api_key:
        return None
    
    if api_key in settings.API_KEYS:
        return api_key
    
    return None