Documentation
¶
Overview ¶
Package botstoken implements a compact, URL-safe token codec for (verb string, subject string, args map[string]string) triples.
Two token variants are provided:
Plain tokens — encode verb/subject/args into a short string, optionally base64url-encoded. Suitable for in-platform use (Telegram callback_data, WhatsApp interactive reply id) where the platform protects integrity. Guaranteed ≤ 64 bytes for typical inputs; Encode returns an error if the result would exceed 64 bytes.
Signed tokens — HMAC-SHA256 signed with an issued-at timestamp. Suitable for tokens that leave the platform (wa.me URLs, web deep links). Expiry is checked on Decode. The key is provided via a pluggable KeyProvider.
Token wire format (plain, before base64url):
<verb>\t<subject>[\t<k1>=<v1>\t<k2>=<v2>...]
Signed token wire format (base64url, no padding):
b64url(<verb>\t<subject>\t<k>=<v>...\tat=<unix-seconds>\tsig=<hex-hmac-sha256>)
Args are sorted by key for deterministic encoding.
Index ¶
Constants ¶
const (
// MaxTokenBytes is the maximum allowed byte length of the encoded token.
MaxTokenBytes = 64
)
Variables ¶
var ErrInvalidSignature = errors.New("botstoken: invalid signature")
ErrInvalidSignature is returned when the HMAC signature does not match.
var ErrInvalidToken = errors.New("botstoken: invalid token format")
ErrInvalidToken is returned when a token cannot be parsed.
var ErrTokenExpired = errors.New("botstoken: token has expired")
ErrTokenExpired is returned when the issued-at timestamp is too old.
var ErrTokenTooLong = errors.New("botstoken: encoded token exceeds 64 bytes")
ErrTokenTooLong is returned when an encoded token would exceed MaxTokenBytes.
Functions ¶
func Encode ¶
Encode encodes (verb, subject, args) into a compact string token. Args are sorted by key for deterministic output. Returns ErrTokenTooLong if the result would exceed 64 bytes.
func EncodeSignedToken ¶
func EncodeSignedToken(verb, subject string, args map[string]string, now time.Time, kp KeyProvider) (string, error)
EncodeSignedToken encodes and HMAC-signs a token with an issued-at timestamp. The result is base64url-encoded (no padding). Signed tokens carry authentication overhead (HMAC-SHA256 signature + issued-at timestamp) that makes them inherently larger than plain tokens; they are intended for off-platform use (web, wa.me deep links) where URL length is not as constrained as in-platform callback fields. There is no explicit length limit on signed tokens — the caller is responsible for keeping verb, subject and args short enough for the target channel.
Types ¶
type KeyProvider ¶
type KeyProvider interface {
// SigningKey returns the current signing key and its ID.
SigningKey() (key []byte, keyID string)
// VerifyingKey returns the key for the given key ID.
// Return nil to indicate that the key ID is unknown.
VerifyingKey(keyID string) []byte
}
KeyProvider returns the HMAC signing key. Implementations may rotate keys; they receive the key ID stored in the token. For the current (signing) call, keyID is empty.
type Token ¶
Token holds the decoded fields of a token.
func DecodeSignedToken ¶
DecodeSignedToken decodes and verifies a signed token produced by EncodeSignedToken. Returns ErrTokenExpired if the token is older than maxAge. Returns ErrInvalidSignature if the HMAC is wrong. Returns ErrInvalidToken if the format is unrecognised.