server/src/api/routes_auth.rs — POST /auth/telegram/webapp.
Gotchas
HMAC secret is NOT the bot token. It's HMAC_SHA256(key="WebAppData", message=bot_token). Login Widget uses SHA256(bot_token) — different algorithm. Don't confuse the two.
User ID is i64. Always.
Constant-time compare prevents timing-oracle leaks of the expected hash.
JWT secret ≠ bot token. Bot token rotation must not invalidate active sessions.
Clock skew tolerance. A few seconds is fine; reject only when auth_date > 24h old, per spec.
Never log raw initData above debug level. Carries user.first_name, user.username, possibly user.phone_number in some flows.
Use RedactedToken from src/utils/redact.rs if you must log a token-shaped string for debugging.
Verification
cargo test auth_service — known-good and known-bad fixtures.
/tg-init-debug slash command for ad-hoc validation in dev.