Spaces:
Sleeping
Sleeping
Download backend/auth.py from Success-dev/receipter-pro: direct link, hf CLI and curl.
- Browser
- Download file 3.12 kB
-
https://huggingface.co/spaces/Success-dev/receipter-pro/resolve/main/backend/auth.py
- Command line
-
hf download hf://spaces/Success-dev/receipter-pro/backend/auth.py
-
curl -L -o auth.py https://huggingface.co/spaces/Success-dev/receipter-pro/resolve/main/backend/auth.py
3.12 kB
| """ | |
| Real Firebase ID token verification — decoupled from LOCAL_MODE (which only governs | |
| storage) and from REAL_SEND_ENABLED (mail transport), same independent-flag pattern as | |
| backend/mailer_client.py. A request either carries a real Firebase ID token | |
| (REAL_AUTH_ENABLED=true) or, for local/dev/test convenience, an X-Dev-Uid header | |
| (REAL_AUTH_ENABLED=false — the default in tests, see tests/conftest.py). | |
| """ | |
| from __future__ import annotations | |
| import os | |
| import firebase_admin | |
| from fastapi import Header, HTTPException | |
| from firebase_admin import auth as firebase_auth | |
| from backend.firebase_app import get_app | |
| def real_auth_enabled() -> bool: | |
| return os.getenv("REAL_AUTH_ENABLED", "false").lower() == "true" | |
| class AuthError(Exception): | |
| pass | |
| def verify_id_token(token: str) -> dict: | |
| get_app() | |
| try: | |
| return firebase_auth.verify_id_token(token) | |
| except firebase_admin.exceptions.FirebaseError as exc: | |
| raise AuthError(str(exc)) from exc | |
| def current_uid( | |
| authorization: str | None = Header(default=None), | |
| x_dev_uid: str = Header(default="dev-user-1", alias="X-Dev-Uid"), | |
| ) -> str: | |
| """FastAPI dependency — every route that needs "who is calling" uses this instead of | |
| reading X-Dev-Uid directly, so the real/local branch lives in exactly one place.""" | |
| if not real_auth_enabled(): | |
| return x_dev_uid | |
| if not authorization or not authorization.startswith("Bearer "): | |
| raise HTTPException(status_code=401, detail="Missing bearer token") | |
| token = authorization[len("Bearer "):] | |
| try: | |
| claims = verify_id_token(token) | |
| except AuthError as exc: | |
| raise HTTPException(status_code=401, detail=f"Invalid token: {exc}") from exc | |
| # Password sign-ups must prove they own the address before touching anything real. | |
| if not claims.get("email_verified", False): | |
| raise HTTPException(status_code=403, detail="Email not verified") | |
| return claims["uid"] | |
| def current_email( | |
| authorization: str | None = Header(default=None), | |
| x_dev_email: str = Header(default="", alias="X-Dev-Email"), | |
| ) -> str: | |
| """The signed-in address (checked to be verified by current_uid). Used where an | |
| action depends on who the person is, such as accepting an invite.""" | |
| if not real_auth_enabled(): | |
| return x_dev_email | |
| if not authorization or not authorization.startswith("Bearer "): | |
| raise HTTPException(status_code=401, detail="Missing bearer token") | |
| try: | |
| claims = verify_id_token(authorization[len("Bearer "):]) | |
| except AuthError as exc: | |
| raise HTTPException(status_code=401, detail=f"Invalid token: {exc}") from exc | |
| return claims.get("email", "") | |
| def lookup_user(uid: str) -> dict: | |
| """{email, name} for a uid, best effort; empty when unknown or running locally.""" | |
| if not real_auth_enabled(): | |
| return {} | |
| try: | |
| get_app() | |
| record = firebase_auth.get_user(uid) | |
| except Exception: # noqa: BLE001 — a missing name must not break the team list | |
| return {} | |
| return {"email": record.email or "", "name": record.display_name or ""} | |