Integrating secrets token generation with hmac.compare_digest for expiring credentials
0 reputation · 19 Mar 2023, 22:53 UTC
0 reputation · 19 Mar 2023, 22:53 UTC
Design an authentication flow that uses secrets.token_urlsafe for issuing short‑lived API tokens and hmac.compare_digest for constant‑time verification, while enforcing automatic expiration without external libraries.
bcrypt or argon2-cffi are excluded.secrets is guaranteed.hmac.compare_digest without storing issuance timestamps?secrets?35775 reputation · 20 Mar 2023, 06:27 UTC
Issue a token that carries its own expiry, authenticate it with an HMAC, and verify the MAC before checking the timestamp. This satisfies all three open questions without a database.
token = base64url(payload) + "." + base64url(hmac_sha256(key, base64url(payload)))
Where payload is a JSON object:
{
"nonce": "",
"exp": 1731456000, // Unix epoch seconds
"kid": "key-2024-11" // Key identifier for rotation
}
The nonce provides entropy; exp embeds expiry; kid enables key rotation.
'.' into payload_b64 and sig_b64.expected_sig = hmac.new(key, payload_b64, 'sha256').digest().hmac.compare_digest(expected_sig, base64url_decode(sig_b64)).exp, reject if time.time() > exp.This order prevents timing oracles on the expiry field.
keys.json mapping kid to base64-encoded secrets (e.g., {"key-2024-11": "...", "key-2024-10": "..."}).kid.kid present in the local keys.json.No shared secret store is needed; each instance holds the same static file.
secrets, hmac, base64, json, time.Verify with:
python -c "
import secrets, hmac, base64, json, time
key = b'shared-secret-32-bytes-long!!'
nonce = secrets.token_urlsafe(16)
exp = int(time.time()) + 300
payload = json.dumps({'nonce': nonce, 'exp': exp, 'kid': 'key-1'}, separators=(',', ':')).encode()
payload_b64 = base64.urlsafe_b64encode(payload).rstrip(b'=')
sig = hmac.new(key, payload_b64, 'sha256').digest()
sig_b64 = base64.urlsafe_b64encode(sig).rstrip(b'=')
token = payload_b64 + b'.' + sig_b64
print(token.decode())
"
Then feed the printed token into the verifier before and after exp to confirm MAC-first rejection.
What is the maximum acceptable clock skew between your service instances? This determines the grace period added to exp during verification and the safe key-retirement delay.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.