UrbanFlow / backend /auth.py
Subh775's picture
RELEASE: auth; pf section added; bug/crash/ major improvements & fixes; refactoring pending..
5cd1866
Raw
History Blame Contribute Delete
2.41 kB
"""
Google OAuth token verification and lightweight user store.
Uses google-auth to verify JWT credentials issued by Google Identity Services.
User profiles are stored in a JSON file (/tmp) — ephemeral on HF Spaces,
which is acceptable for a demo. Client-side localStorage persists the session.
"""
import json
import os
from pathlib import Path
from datetime import datetime, timezone
from google.oauth2 import id_token
from google.auth.transport import requests as google_requests
GOOGLE_CLIENT_ID = os.getenv("GOOGLE_CLIENT_ID", "")
USER_STORE_PATH = Path(os.getenv("USER_STORE_PATH", "/tmp/urbanflow_users.json"))
def _load_users() -> dict:
if USER_STORE_PATH.exists():
return json.loads(USER_STORE_PATH.read_text())
return {}
def _save_users(users: dict):
USER_STORE_PATH.write_text(json.dumps(users, indent=2))
def verify_google_token(credential: str) -> dict:
"""
Verify a Google ID token (JWT) and return the decoded payload.
Raises ValueError on invalid/expired tokens.
"""
idinfo = id_token.verify_oauth2_token(
credential,
google_requests.Request(),
GOOGLE_CLIENT_ID,
)
return {
"email": idinfo["email"],
"name": idinfo.get("name", ""),
"picture": idinfo.get("picture", ""),
}
def get_or_create_user(email: str, name: str, picture: str) -> dict:
"""
Look up a user by email. If they don't exist, create a stub record.
Returns the user record with a `new_user` flag.
"""
users = _load_users()
is_new = email not in users
if is_new:
users[email] = {
"username": "",
"name": name,
"picture": picture,
"created_at": datetime.now(timezone.utc).isoformat(),
}
_save_users(users)
user = users[email]
return {
"email": email,
"username": user.get("username", ""),
"name": user.get("name", name),
"picture": user.get("picture", picture),
"new_user": is_new or not user.get("username"),
}
def set_username(email: str, username: str) -> bool:
"""
Save a display username for a first-time user.
Returns True on success, False if the user record doesn't exist.
"""
users = _load_users()
if email not in users:
return False
users[email]["username"] = username.strip()
_save_users(users)
return True