fix: 增强云端 Supabase 认证可靠性,修复验证码失败可观测性

- JWT 验证器新增 apikey 参数,支持云端 JWKS 认证头
- Auth 网关新增上游超时/错误映射为 503 状态码
- Auth 网关新增重定向 URL 校验,阻断开放重定向风险
- 用户依赖传递 anon_key 给 JWT 验证器
- 新增相关单元测试覆盖 JWKS 头、503 映射、重定向校验
- 新增实现计划文档
This commit is contained in:
zl-q
2026-03-10 09:11:27 +08:00
parent 6fe2e7b6c3
commit c9a2c75c35
10 changed files with 384 additions and 75 deletions
+14 -2
View File
@@ -14,10 +14,22 @@ class TokenVerifierUnavailableError(Exception):
class JwtVerifier:
def __init__(self, jwks_url: str, issuer: str, audience: str) -> None:
def __init__(
self,
jwks_url: str,
issuer: str,
audience: str,
apikey: str,
) -> None:
self._issuer: str = issuer
self._audience: str = audience
self._jwks_client: jwt.PyJWKClient = jwt.PyJWKClient(jwks_url)
self._jwks_client: jwt.PyJWKClient = jwt.PyJWKClient(
jwks_url,
headers={
"apikey": apikey,
"Authorization": f"Bearer {apikey}",
},
)
def verify(self, token: str) -> dict[str, Any]:
try:
-16
View File
@@ -129,19 +129,6 @@ class SupabaseSettings(BaseModel):
jwt_audience: str = "authenticated"
jwt_issuer: str | None = None
jwks_url: str | None = None
site_url: str | None = None
additional_redirect_urls: list[str] = Field(default_factory=list)
@field_validator("additional_redirect_urls", mode="before")
@classmethod
def normalize_redirect_urls(cls, value: object) -> list[str]:
if value is None:
return []
if isinstance(value, str):
return [item.strip() for item in value.split(",") if item.strip()]
if isinstance(value, list):
return [str(item).strip() for item in value if str(item).strip()]
return []
@model_validator(mode="after")
def compute_defaults(self) -> "SupabaseSettings":
@@ -152,9 +139,6 @@ class SupabaseSettings(BaseModel):
if self.jwks_url is None:
self.jwks_url = f"{self.jwt_issuer}/.well-known/jwks.json"
if self.site_url is None:
self.site_url = "http://localhost:3000"
return self
@computed_field