improve signed reads, crypto hardening, and scraper transport
This commit is contained in:
@@ -144,3 +144,58 @@ def verify_signed_request_any(
|
||||
last_exc = exc
|
||||
if last_exc is not None:
|
||||
raise last_exc
|
||||
|
||||
|
||||
# ── Signed-read credential extraction (C3) ────────────────────────────────
|
||||
# Read endpoints historically took the signature as `?ts=&sig=` query params,
|
||||
# which leaks signatures into access logs / proxies / browser history. The
|
||||
# canonical transport is now the X-Sig-Ts / X-Sig-Sig HEADERS; the query
|
||||
# params are kept as a deprecated fallback so older clients keep working.
|
||||
from dataclasses import dataclass
|
||||
|
||||
from fastapi import Header, Query
|
||||
|
||||
|
||||
@dataclass
|
||||
class SignedReadCreds:
|
||||
ts: int
|
||||
sig: str
|
||||
|
||||
|
||||
def signed_read_creds(
|
||||
ts: Optional[int] = Query(default=None, deprecated=True,
|
||||
description="DEPRECATED — use X-Sig-Ts header"),
|
||||
sig: Optional[str] = Query(default=None, deprecated=True,
|
||||
description="DEPRECATED — use X-Sig-Sig header"),
|
||||
x_sig_ts: Optional[int] = Header(default=None, alias="X-Sig-Ts",
|
||||
description="Signed timestamp (ms)"),
|
||||
x_sig_sig: Optional[str] = Header(default=None, alias="X-Sig-Sig",
|
||||
description="EIP-191 signature"),
|
||||
) -> SignedReadCreds:
|
||||
"""FastAPI dependency: required signed-read credentials.
|
||||
|
||||
Headers win over query params when both are present."""
|
||||
t = x_sig_ts if x_sig_ts is not None else ts
|
||||
s = x_sig_sig if x_sig_sig else sig
|
||||
if t is None or not s:
|
||||
raise HTTPException(
|
||||
422, "Missing signed-read credentials (X-Sig-Ts / X-Sig-Sig headers)")
|
||||
return SignedReadCreds(ts=t, sig=s)
|
||||
|
||||
|
||||
def optional_signed_read_creds(
|
||||
# Legacy query names used by /telegram/{wallet}/status.
|
||||
timestamp: Optional[int] = Query(default=None, deprecated=True,
|
||||
description="DEPRECATED — use X-Sig-Ts header"),
|
||||
signature: Optional[str] = Query(default=None, deprecated=True,
|
||||
description="DEPRECATED — use X-Sig-Sig header"),
|
||||
x_sig_ts: Optional[int] = Header(default=None, alias="X-Sig-Ts"),
|
||||
x_sig_sig: Optional[str] = Header(default=None, alias="X-Sig-Sig"),
|
||||
) -> Optional[SignedReadCreds]:
|
||||
"""Like signed_read_creds but returns None when absent — for endpoints
|
||||
that serve a redacted response to unauthenticated callers."""
|
||||
t = x_sig_ts if x_sig_ts is not None else timestamp
|
||||
s = x_sig_sig if x_sig_sig else signature
|
||||
if t is None or not s:
|
||||
return None
|
||||
return SignedReadCreds(ts=t, sig=s)
|
||||
|
||||
Reference in New Issue
Block a user