token

package
v0.3.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 17, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package token provides compact URL-safe signed tokens with truncated HMAC-SHA256.

Tokens encode any JSON-serializable payload into a short, URL-safe string suitable for email verification links, invite tokens, magic links, and password reset URLs. Unlike JWTs, tokens have no header or registered claims — just a signed payload.

Token Format

A token consists of two base64url-encoded segments separated by a dot:

base64url(json(payload)).base64url(hmac-sha256[:8])

The signature is a truncated HMAC-SHA256 (first 8 bytes / 64 bits), providing adequate brute-force resistance for short-lived, single-use tokens. The entire token is URL-safe with no padding characters.

Features

  • Generic functions for any JSON-serializable payload type
  • Truncated HMAC-SHA256 signature (compact, 8 bytes)
  • Constant-time signature verification
  • URL-safe output (no padding, no special characters)
  • Zero external dependencies (stdlib only)

Usage

Generating a token:

type EmailVerification struct {
    UserID string `json:"user_id"`
    Email  string `json:"email"`
    Action string `json:"action"`
}

payload := EmailVerification{
    UserID: "usr_abc123",
    Email:  "user@example.com",
    Action: "verify_email",
}

tok, err := token.GenerateToken(payload, []byte("your-secret-key"))
if err != nil {
    log.Fatal(err)
}

verifyURL := fmt.Sprintf("https://example.com/verify?token=%s", tok)

Parsing and verifying a token:

result, err := token.ParseToken[EmailVerification](tok, []byte("your-secret-key"))
if err != nil {
    switch {
    case errors.Is(err, token.ErrSignatureInvalid):
        log.Println("Token has been tampered with")
    case errors.Is(err, token.ErrInvalidToken):
        log.Println("Token is malformed")
    default:
        log.Printf("Token parsing failed: %v", err)
    }
    return
}

log.Printf("Verified email: %s for user: %s", result.Email, result.UserID)

Use Cases

  • Email verification: encode user ID + email + action, embed in verification link
  • Invite tokens: encode workspace ID + inviter + role, send in invitation email
  • Magic links: encode user ID + timestamp, send passwordless login link
  • Password reset: encode user ID + nonce, embed in reset URL

When to Use Token vs JWT

Use this package for short-lived, single-use tokens embedded in URLs or emails where compact size matters and there are no temporal claims (expiration, not-before). Use the jwt package for API authentication tokens that require standard claims, longer signatures, and header metadata.

Security Considerations

Secret key requirements:

  • Use at least 32 bytes (256 bits) for HMAC-SHA256
  • Generate using a cryptographically secure random source
  • Store securely (environment variables, key management service)

Truncated signature trade-offs:

  • 8-byte (64-bit) signature provides ~2^64 brute-force resistance
  • Adequate for short-lived, single-use tokens with server-side state
  • Not suitable for long-lived bearer tokens — use JWT for those

Token lifecycle:

  • Always pair with server-side state (database flag, one-time nonce)
  • Mark tokens as consumed after use to prevent replay
  • Enforce expiration at the application level if needed

Error Handling

The package provides specific error types for different failure modes:

  • ErrInvalidToken: malformed token structure or invalid base64url encoding
  • ErrSignatureInvalid: HMAC signature does not match (tampered or wrong secret)
  • ErrEmptySecret: nil or empty secret provided

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidToken is returned when the token string is malformed,
	// has an incorrect number of segments, or contains invalid base64url encoding.
	ErrInvalidToken = errors.New("token: invalid token")

	// ErrSignatureInvalid is returned when the token's HMAC signature
	// does not match the expected signature for the given payload and secret.
	ErrSignatureInvalid = errors.New("token: invalid signature")

	// ErrEmptySecret is returned when a nil or empty secret key is provided.
	ErrEmptySecret = errors.New("token: empty secret")
)

Functions

func GenerateToken

func GenerateToken[T any](payload T, secret []byte) (string, error)

GenerateToken encodes payload as JSON, signs it with a truncated HMAC-SHA256, and returns a compact URL-safe token string.

The token format is: base64url(json(payload)).base64url(hmac-sha256[:8])

The payload must be JSON-serializable. The secret must not be empty.

func ParseToken

func ParseToken[T any](tokenStr string, secret []byte) (*T, error)

ParseToken verifies the signature and decodes the payload from a token string.

Returns a pointer to the decoded payload on success, or an error if the token is malformed, the signature is invalid, or the payload cannot be decoded.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL