Sub / app /utils /supabase_auth.py
Himankpro's picture
Upload 93 files
3a6c182 verified
Raw History Blame Contribute Delete
2.76 kB
"""Verify caller identity for /api/pipeline/* — Bearer JWTs and/or pipeline client headers."""
from __future__ import annotations
from typing import Optional, Tuple
import jwt
from flask import request
from ..config import Config
from .mirofish_jwt import verify_mirofish_session_jwt
def verify_supabase_user_jwt(token: str) -> Tuple[Optional[str], Optional[str]]:
"""
Returns (user_id, error_message). user_id is None on failure.
"""
if not token or not Config.SUPABASE_JWT_SECRET:
return None, "JWT verification not configured"
try:
payload = jwt.decode(
token,
Config.SUPABASE_JWT_SECRET,
algorithms=["HS256"],
audience="authenticated",
options={"verify_exp": True},
)
sub = payload.get("sub")
if not sub:
return None, "Invalid token: missing sub"
return str(sub), None
except jwt.ExpiredSignatureError:
return None, "Token expired"
except jwt.InvalidTokenError as e:
return None, f"Invalid token: {e}"
def extract_bearer_token() -> Optional[str]:
h = request.headers.get("Authorization", "")
if h.lower().startswith("bearer "):
return h[7:].strip()
return None
def resolve_pipeline_user_id() -> Tuple[Optional[str], Optional[str]]:
"""
When Supabase sync is on:
1) Authorization: Bearer <MiroFish session JWT> (optional / legacy).
2) Authorization: Bearer <Supabase Auth JWT> if SUPABASE_JWT_SECRET is set.
3) X-Mirofish-User-Id + X-Pipeline-Client-Secret matching PIPELINE_CLIENT_SECRET
(Supabase public.User in browser + VITE_PIPELINE_CLIENT_SECRET).
Returns (user_id_str, error_message).
"""
token = extract_bearer_token()
if token:
m_uid, m_hint = verify_mirofish_session_jwt(token)
if m_uid:
return m_uid, None
if m_hint == "expired":
return None, "Token expired"
if Config.SUPABASE_JWT_SECRET:
s_uid, s_err = verify_supabase_user_jwt(token)
if s_uid:
return s_uid, None
return None, s_err or "Invalid token"
return None, "Invalid token"
uid = (request.headers.get("X-Mirofish-User-Id") or "").strip()
key = (request.headers.get("X-Pipeline-Client-Secret") or "").strip()
secret = (Config.PIPELINE_CLIENT_SECRET or "").strip()
if uid and secret and key == secret:
return uid, None
if uid or key:
return None, "Invalid pipeline client credentials"
if not secret:
return None, "Server PIPELINE_CLIENT_SECRET is not configured"
return None, "Missing credentials"