feat: Implement Supabase-backed authentication and entitlement checks for frontend-to-backend requests.

This commit is contained in:
2569718930@qq.com
2026-03-13 11:01:44 +08:00
parent 534eef4197
commit 5b7a257087
2 changed files with 34 additions and 6 deletions
+14
View File
@@ -3,6 +3,8 @@ import { NextResponse } from "next/server";
import { createSupabaseRouteClient, hasSupabaseServerEnv } from "@/lib/supabase/server";
export const BACKEND_ENTITLEMENT_HEADER = "x-polyweather-entitlement";
export const FORWARDED_SUPABASE_USER_ID_HEADER = "x-polyweather-auth-user-id";
export const FORWARDED_SUPABASE_EMAIL_HEADER = "x-polyweather-auth-email";
type HeaderBuildResult = {
headers: HeadersInit;
@@ -36,6 +38,18 @@ export async function buildBackendRequestHeaders(
const {
data: { session },
} = await supabase.auth.getSession();
const {
data: { user },
} = await supabase.auth.getUser();
const forwardedUserId = String(user?.id || session?.user?.id || "").trim();
const forwardedEmail = String(user?.email || session?.user?.email || "").trim();
if (forwardedUserId) {
headers.set(FORWARDED_SUPABASE_USER_ID_HEADER, forwardedUserId);
}
if (forwardedEmail) {
headers.set(FORWARDED_SUPABASE_EMAIL_HEADER, forwardedEmail);
}
const accessToken = session?.access_token || "";
if (accessToken) {
+20 -6
View File
@@ -95,6 +95,8 @@ def _env_bool(name: str, default: bool = False) -> bool:
_ENTITLEMENT_GUARD_ENABLED = _env_bool("POLYWEATHER_REQUIRE_ENTITLEMENT", False)
_ENTITLEMENT_HEADER = "x-polyweather-entitlement"
_ENTITLEMENT_TOKEN = (os.getenv("POLYWEATHER_BACKEND_ENTITLEMENT_TOKEN") or "").strip()
_FORWARDED_SUPABASE_USER_ID_HEADER = "x-polyweather-auth-user-id"
_FORWARDED_SUPABASE_EMAIL_HEADER = "x-polyweather-auth-email"
_SUPABASE_AUTH_REQUIRED = _env_bool(
"POLYWEATHER_AUTH_REQUIRED",
SUPABASE_ENTITLEMENT.enabled,
@@ -211,12 +213,24 @@ def _require_supabase_identity(request: Request) -> Dict[str, str]:
detail="payment requires SUPABASE_URL and SUPABASE_ANON_KEY",
)
token = extract_bearer_token(request.headers.get("authorization"))
if not token:
raise HTTPException(status_code=401, detail="Unauthorized")
identity = SUPABASE_ENTITLEMENT.get_identity(token)
if not identity:
raise HTTPException(status_code=401, detail="Unauthorized")
return {"user_id": identity.user_id, "email": identity.email}
if token:
identity = SUPABASE_ENTITLEMENT.get_identity(token)
if identity:
return {"user_id": identity.user_id, "email": identity.email}
# Trusted fallback for server-to-server proxy calls:
# only when entitlement token is valid do we accept forwarded identity headers.
if _legacy_service_token_valid(request):
forwarded_user_id = str(
request.headers.get(_FORWARDED_SUPABASE_USER_ID_HEADER) or ""
).strip()
if forwarded_user_id:
forwarded_email = str(
request.headers.get(_FORWARDED_SUPABASE_EMAIL_HEADER) or ""
).strip()
return {"user_id": forwarded_user_id, "email": forwarded_email}
raise HTTPException(status_code=401, detail="Unauthorized")
class WalletChallengeRequest(BaseModel):