Documentation
¶
Overview ¶
Package approvaltoken signs and verifies the short-lived HMAC tokens embedded in HITL notification-email magic links.
A token authorizes exactly one action (approve or reject) on exactly one message and carries its own expiration. Tokens are URL-safe and contain no session state — verification depends only on the shared HMAC secret and the current time, so magic links work on any device the reviewer happens to be reading email on.
Format:
base64url(payload) + "." + base64url(hmac_sha256(secret, payload))
where payload is "<message_id>|<action>|<exp_unix>".
The same config.Signing.HMACSecret used to sign X-E2A-Auth-* email headers is reused here, so there's no new key to rotate.
Index ¶
Constants ¶
const ( ActionApprove = "approve" ActionReject = "reject" )
Action values mirror the design-doc contract. Any other value in a verified token is treated as tampering.
Variables ¶
var ( // ErrInvalidToken covers malformed, tampered, or unknown-action tokens. // Callers should treat all three the same — do not distinguish for // attackers. ErrInvalidToken = errors.New("invalid approval token") // ErrTokenExpired is returned when the signature is valid but the // embedded exp is in the past. ErrTokenExpired = errors.New("approval token expired") )
Functions ¶
func PeekMessageID ¶ added in v0.3.0
PeekMessageID extracts the message_id from a token *without* verifying the HMAC. Useful when the caller needs to look up the owning user's signing secrets to then call Verify with that secret list.
SECURITY: the returned message_id is attacker-controlled until Verify confirms the signature. Use it only as a lookup hint to find which secrets to verify against — never act on the value before Verify returns claims successfully.
Types ¶
type Claims ¶
Claims is the verified payload of a magic-link token.
func Verify ¶ added in v0.3.0
Verify parses, HMAC-checks (against any of `secrets`), and exp-checks a token. Returns the claims on success; ErrInvalidToken for malformed / tampered / wrong-secret tokens; ErrTokenExpired for valid-but-past-exp tokens.
Verify does not check that the message still exists or is still pending — that is the handler's job. Verify's only job is "was this string issued by us, and is its exp in the future".
Accepting multiple secrets supports per-user multi-secret rotation: after a user creates a new secret, in-flight magic-link tokens issued under the old secret continue to verify until that secret is deleted.