Fix 500 on legacy signed URLs
A TimestampSigner value is an HMAC over 'payload:timestamp', so a plain Signer's HMAC check accepts it and the embedded timestamp then reached the JSON decoder, raising JSONDecodeError (not BadSignature) and surfacing as a 500. That broke every stored visual-match thumbnail URL minted before the stable scheme, so the J-ID match tiles never loaded on prod. Detect the legacy shape by its extra separator and verify it with TimestampSigner; malformed input returns None instead of raising.
This commit is contained in:
@@ -36,18 +36,25 @@ def sign_payload(payload, salt, now=None):
|
||||
def load_payload(signature, salt, legacy_max_age=86400):
|
||||
"""Verify a signed payload; ``None`` when missing, tampered with or expired.
|
||||
|
||||
Signatures minted before the stable scheme (``TimestampSigner``) are still
|
||||
accepted for one release so pages open across the deploy keep working.
|
||||
Legacy ``TimestampSigner`` values are still accepted for one release.
|
||||
Detect them by their extra separator (``payload:timestamp:signature``):
|
||||
a plain ``Signer`` accepts the HMAC a ``TimestampSigner`` computed over
|
||||
``payload:timestamp`` and then chokes on the embedded timestamp while
|
||||
decoding the JSON payload, which used to surface as a 500.
|
||||
"""
|
||||
try:
|
||||
data = signing.Signer(salt=salt).unsign_object(signature)
|
||||
except signing.BadSignature:
|
||||
if not signature:
|
||||
return None
|
||||
if signature.count(":") >= 2:
|
||||
try:
|
||||
return signing.TimestampSigner(salt=salt).unsign_object(
|
||||
signature, max_age=legacy_max_age
|
||||
)
|
||||
except signing.BadSignature:
|
||||
except (signing.BadSignature, ValueError):
|
||||
return None
|
||||
try:
|
||||
data = signing.Signer(salt=salt).unsign_object(signature)
|
||||
except (signing.BadSignature, ValueError):
|
||||
return None
|
||||
if not isinstance(data, dict):
|
||||
return None
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user