File size: 2,401 Bytes
3064989
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import os
from typing import Optional
from fastapi import Header, HTTPException, Security, status
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer


security_bearer = HTTPBearer(auto_error=False)


def verify_api_key(api_key: Optional[str]) -> bool:
    """Verifies X-API-Key header against API_KEY environment variable."""
    expected_key = os.environ.get("API_KEY")
    if not expected_key:
        return False
    return api_key == expected_key


def verify_jwt(token: str) -> Optional[dict]:
    """Verifies Supabase JWT token using SUPABASE_JWT_SECRET environment variable."""
    jwt_secret = os.environ.get("SUPABASE_JWT_SECRET")
    if not jwt_secret:
        return None
    try:
        from jose import jwt
        payload = jwt.decode(token, jwt_secret, algorithms=["HS256"])
        return payload
    except Exception:
        # Fallback to PyJWT if jose is not present
        try:
            import jwt as pyjwt
            payload = pyjwt.decode(token, jwt_secret, algorithms=["HS256"])
            return payload
        except Exception:
            return None


async def get_current_user(
    auth_credentials: Optional[HTTPAuthorizationCredentials] = Security(security_bearer),
    x_api_key: Optional[str] = Header(default=None, alias="X-API-Key"),
):
    """
    FastAPI dependency enforcing authentication on protected routes.
    Checks:
    1. If neither API_KEY nor SUPABASE_JWT_SECRET is set, bypass (development mode).
    2. Validates X-API-Key header.
    3. Validates Authorization: Bearer <JWT> header.
    """
    api_key_env = os.environ.get("API_KEY")
    jwt_secret_env = os.environ.get("SUPABASE_JWT_SECRET")

    # Bypass authentication if no secret or API key is set in environment (Dev Mode)
    if not api_key_env and not jwt_secret_env:
        return {"user": "anonymous_dev"}

    # 1. Check API Key
    if x_api_key and verify_api_key(x_api_key):
        return {"user": "api_key_client"}

    # 2. Check Supabase JWT
    if auth_credentials and auth_credentials.credentials:
        payload = verify_jwt(auth_credentials.credentials)
        if payload:
            return payload

    raise HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Credenciais de autenticação inválidas ou ausentes. Forneça um JWT Token (Bearer) ou X-API-Key.",
        headers={"WWW-Authenticate": "Bearer"},
    )