jwt

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Jun 14, 2025 License: MIT Imports: 17 Imported by: 0

README ΒΆ

JWT Package - Generic Claims Architecture

A high-performance JWT (JSON Web Token) implementation for Go with support for custom claims types and verification-only mode for microservices architecture.

Go Reference Go Report Card Coverage Go Version Tests

🎯 Architecture Overview

This JWT package is designed for microservices architectures where:

  • Authentication Service generates tokens (has private key)
  • Client Services only verify tokens (have public key or use verification endpoint)
  • Each service can have its own custom claims structure

✨ Key Features

  • πŸ”§ Custom Claims: Type-safe custom claims for each service
  • πŸ” Asymmetric Algorithms: RSA, ECDSA, EdDSA support for distributed systems
  • πŸ”‘ Verification-only Mode: Services can verify without knowing secrets
  • πŸš€ High Performance: Buffer pooling and optimized parsing
  • πŸ›‘οΈ Security First: Built-in validation and expiration checking
  • 🧡 Thread Safe: Concurrent operations supported
  • 🎯 Type Safety: Generics for compile-time claim validation

πŸ“¦ Supported Algorithms

Algorithm Family Algorithms Key Type Best For
HMAC HS256, HS384, HS512 Symmetric (shared secret) Internal microservices
RSA RS256, RS384, RS512 Asymmetric (RSA keys) Public/private separation
ECDSA ES256, ES384, ES512 Asymmetric (ECDSA keys) Efficient asymmetric
EdDSA Ed25519 Asymmetric (Ed25519 keys) Modern, fast asymmetric

πŸš€ Quick Start

1. Authentication Service (Token Generation)
package main

import (
    "crypto/rand"
    "crypto/rsa"
    "fmt"
    "time"
    
    "github.com/krajcik/go-jwt"
)

// Define your custom claims
type AuthClaims struct {
    UserID    string   `json:"user_id"`
    Email     string   `json:"email"`
    Roles     []string `json:"roles"`
    TokenType string   `json:"token_type"`
}

// Implement validation (optional)
func (c AuthClaims) Validate() error {
    if c.UserID == "" {
        return errors.New("user_id is required")
    }
    return nil
}

func main() {
    // Generate RSA key pair for Auth Service
    privateKey, _ := rsa.GenerateKey(rand.Reader, 2048)
    
    // Create token signer
    algorithm := jwt.NewRS256(privateKey)
    signer, _ := jwt.NewTokenSigner[AuthClaims](algorithm, "auth-service")
    
    // Generate token with custom claims
    customClaims := AuthClaims{
        UserID:    "user_12345",
        Email:     "user@example.com",
        Roles:     []string{"user", "admin"},
        TokenType: "access",
    }
    
    token, err := signer.GenerateToken("user_12345", time.Hour, customClaims)
    if err != nil {
        panic(err)
    }
    
    fmt.Println("Generated token:", token)
}
2. Client Service (Token Verification)
package main

import (
    "crypto/rsa"
    "fmt"
    
    "github.com/krajcik/go-jwt"
)

// Client service defines its own claims structure
type ClientClaims struct {
    UserID      string `json:"user_id"`
    Permissions []string `json:"permissions"`
}

func main() {
    // Client service only has public key
    var publicKey *rsa.PublicKey // obtained from Auth Service
    
    // Create token verifier (verification-only)
    algorithm := jwt.NewRS256WithPublicKey(publicKey)
    verifier, _ := jwt.NewTokenVerifier[ClientClaims](algorithm, "auth-service")
    
    // Verify token from request
    token := "eyJ..." // from Authorization header
    
    standardClaims, customClaims, err := verifier.VerifyToken(token)
    if err != nil {
        panic(err)
    }
    
    // Use standard claims
    userID := standardClaims.Subject
    expiry := standardClaims.ExpiresAt
    
    // Use custom claims
    permissions := customClaims.Permissions
    
    fmt.Printf("User: %s, Permissions: %v, Expires: %d\n", 
        userID, permissions, expiry)
}

πŸ—οΈ Service-Specific Examples

E-commerce Service
type EcommerceClaims struct {
    CartID       string `json:"cart_id"`
    CustomerTier string `json:"customer_tier"`
    StoreID      string `json:"store_id"`
}

func (c EcommerceClaims) Validate() error {
    validTiers := map[string]bool{
        "bronze": true, "silver": true, "gold": true, "platinum": true,
    }
    if !validTiers[c.CustomerTier] {
        return errors.New("invalid customer tier")
    }
    return nil
}

// Usage in e-commerce service
algorithm := jwt.NewRS256WithPublicKey(publicKey)
verifier, _ := jwt.NewTokenVerifier[EcommerceClaims](algorithm, "auth-service")

standardClaims, ecommerceClaims, err := verifier.VerifyToken(token)
if err != nil {
    return http.StatusUnauthorized, err
}

// Use e-commerce specific claims
cartID := ecommerceClaims.CartID
customerTier := ecommerceClaims.CustomerTier
Payment Service
type PaymentClaims struct {
    PaymentMethodID string  `json:"payment_method_id"`
    MaxAmount       float64 `json:"max_amount"`
    Currency        string  `json:"currency"`
    MerchantID      string  `json:"merchant_id"`
}

func (c PaymentClaims) Validate() error {
    if c.MaxAmount <= 0 {
        return errors.New("max_amount must be positive")
    }
    return nil
}

// Usage in payment service
algorithm := jwt.NewRS256WithPublicKey(publicKey)
verifier, _ := jwt.NewTokenVerifier[PaymentClaims](algorithm, "auth-service")

_, paymentClaims, err := verifier.VerifyToken(token)
if err != nil {
    return errors.New("invalid payment token")
}

// Validate payment amount against token limits
if requestAmount > paymentClaims.MaxAmount {
    return errors.New("amount exceeds token limit")
}

πŸ” Security Architecture

Asymmetric Key Distribution
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    Private Key    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Auth Service   β”‚ ◄─────────────── β”‚   Key Store     β”‚
β”‚ (Token Signing) β”‚                   β”‚                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                                      β”‚
         β”‚ Tokens                               β”‚ Public Key
         β–Ό                                      β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Client Service  β”‚ ◄─────────────── β”‚ Client Service  β”‚
β”‚   (Verify)      β”‚    Public Key     β”‚   (Verify)      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
HMAC Shared Secret (Internal Services)
// For internal microservices that can share secrets
algorithm := jwt.NewHS256("shared-internal-secret")

// Both services can sign and verify
signer, _ := jwt.NewTokenSigner[InternalClaims](algorithm, "internal")
verifier, _ := jwt.NewTokenVerifier[InternalClaims](algorithm, "internal")

πŸ“‹ Standard Claims

All tokens include standard JWT claims:

type StandardClaims struct {
    Subject   string `json:"sub"`      // User/entity identifier
    IssuedAt  int64  `json:"iat"`      // Issued at timestamp
    ExpiresAt int64  `json:"exp"`      // Expiration timestamp
    NotBefore int64  `json:"nbf"`      // Not valid before (optional)
    Issuer    string `json:"iss"`      // Token issuer
    Audience  string `json:"aud"`      // Token audience (optional)
    JwtID     string `json:"jti"`      // JWT ID (optional)
}

πŸ” Claims Validation

Implement ClaimsValidator interface for automatic validation:

type ClaimsValidator interface {
    Validate() error
}

type UserClaims struct {
    UserID string `json:"user_id"`
    Email  string `json:"email"`
}

func (c UserClaims) Validate() error {
    if c.UserID == "" {
        return errors.New("user_id cannot be empty")
    }
    
    emailRegex := regexp.MustCompile(`^[^\s@]+@[^\s@]+\.[^\s@]+$`)
    if c.Email != "" && !emailRegex.MatchString(c.Email) {
        return errors.New("invalid email format")
    }
    
    return nil
}

❌ Error Handling

standardClaims, customClaims, err := verifier.VerifyToken(token)
if err != nil {
    switch err {
    case jwt.ErrExpiredToken:
        return http.StatusUnauthorized, "Token expired"
    case jwt.ErrInvalidSignature:
        return http.StatusUnauthorized, "Invalid token"
    case jwt.ErrInvalidClaims:
        return http.StatusBadRequest, "Invalid claims"
    default:
        return http.StatusInternalServerError, "Token verification failed"
    }
}

πŸš€ Performance Features

  • Buffer Pooling: Reduces memory allocations
  • Manual Token Parsing: 5.6x faster than strings.Split
  • High-Performance Libraries: goccy/go-json and cloudwego/base64x
  • Zero-Copy Operations: Optimized string handling
  • Concurrent Safe: Thread-safe operations

πŸ§ͺ Testing

# Run all tests
go test ./... -v

# Run tests with coverage
go test ./... -cover

# Run specific test
go test ./... -run TestTokenSigner -v

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

🀝 Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

πŸ™ Acknowledgments

  • Optimized with high-performance libraries: goccy/go-json and cloudwego/base64x
  • Designed for modern microservices architectures
  • Built for production use in distributed systems

Documentation ΒΆ

Index ΒΆ

Constants ΒΆ

This section is empty.

Variables ΒΆ

View Source
var (
	ErrInvalidToken     = errors.New("invalid token")
	ErrExpiredToken     = errors.New("token has expired")
	ErrInvalidSignature = errors.New("invalid token signature")
	ErrInvalidClaims    = errors.New("invalid claims structure")
	ErrEmptySubject     = errors.New("subject cannot be empty")
	ErrInvalidDuration  = errors.New("duration must be positive")
)
View Source
var (
	ErrInvalidKeyType = errors.New("invalid key type for algorithm")
)

Functions ΒΆ

func GenerateEdDSAKey ΒΆ

func GenerateEdDSAKey() (ed25519.PublicKey, ed25519.PrivateKey, error)

GenerateEdDSAKey generates a new Ed25519 key pair

Types ΒΆ

type Algorithm ΒΆ

type Algorithm interface {
	// Name returns the algorithm name for JWT header (e.g., "HS256", "RS256", "ES256")
	Name() string
	// Sign creates a signature for the given payload
	Sign(payload []byte) ([]byte, error)
	// Verify checks if the signature is valid for the given payload
	Verify(payload []byte, signature []byte) error
	// Header returns the JWT header as JSON bytes
	Header() []byte
}

Algorithm defines the interface for JWT signing algorithms

func NewES256 ΒΆ

func NewES256(privateKey *ecdsa.PrivateKey) Algorithm

NewES256 creates a new ECDSA-SHA256 algorithm instance (P-256 curve)

func NewES256WithPublicKey ΒΆ

func NewES256WithPublicKey(publicKey *ecdsa.PublicKey) Algorithm

NewES256WithPublicKey creates a verification-only ES256 instance

func NewES384 ΒΆ

func NewES384(privateKey *ecdsa.PrivateKey) Algorithm

NewES384 creates a new ECDSA-SHA384 algorithm instance (P-384 curve)

func NewES384WithPublicKey ΒΆ

func NewES384WithPublicKey(publicKey *ecdsa.PublicKey) Algorithm

NewES384WithPublicKey creates a verification-only ES384 instance

func NewES512 ΒΆ

func NewES512(privateKey *ecdsa.PrivateKey) Algorithm

NewES512 creates a new ECDSA-SHA512 algorithm instance (P-521 curve)

func NewES512WithPublicKey ΒΆ

func NewES512WithPublicKey(publicKey *ecdsa.PublicKey) Algorithm

NewES512WithPublicKey creates a verification-only ES512 instance

func NewEdDSA ΒΆ

func NewEdDSA(privateKey ed25519.PrivateKey) Algorithm

NewEdDSA creates a new EdDSA algorithm instance

func NewEdDSAWithPublicKey ΒΆ

func NewEdDSAWithPublicKey(publicKey ed25519.PublicKey) Algorithm

NewEdDSAWithPublicKey creates a verification-only EdDSA instance

func NewHS256 ΒΆ

func NewHS256(secret string) Algorithm

NewHS256 creates a new HMAC-SHA256 algorithm instance

func NewHS384 ΒΆ

func NewHS384(secret string) Algorithm

NewHS384 creates a new HMAC-SHA384 algorithm instance

func NewHS512 ΒΆ

func NewHS512(secret string) Algorithm

NewHS512 creates a new HMAC-SHA512 algorithm instance

func NewRS256 ΒΆ

func NewRS256(privateKey *rsa.PrivateKey) Algorithm

NewRS256 creates a new RSA-SHA256 algorithm instance

func NewRS256WithPublicKey ΒΆ

func NewRS256WithPublicKey(publicKey *rsa.PublicKey) Algorithm

NewRS256WithPublicKey creates a verification-only RS256 instance

func NewRS384 ΒΆ

func NewRS384(privateKey *rsa.PrivateKey) Algorithm

NewRS384 creates a new RSA-SHA384 algorithm instance

func NewRS512 ΒΆ

func NewRS512(privateKey *rsa.PrivateKey) Algorithm

NewRS512 creates a new RSA-SHA512 algorithm instance

type ClaimsValidator ΒΆ

type ClaimsValidator interface {
	Validate() error
}

ClaimsValidator interface for custom claims validation

type ECDSAAlgorithm ΒΆ

type ECDSAAlgorithm struct {
	// contains filtered or unexported fields
}

ECDSAAlgorithm implements ECDSA-based JWT signing

func (*ECDSAAlgorithm) Header ΒΆ

func (e *ECDSAAlgorithm) Header() []byte

Header returns the algorithm header

func (*ECDSAAlgorithm) Name ΒΆ

func (e *ECDSAAlgorithm) Name() string

Name returns the algorithm name

func (*ECDSAAlgorithm) Sign ΒΆ

func (e *ECDSAAlgorithm) Sign(payload []byte) ([]byte, error)

Sign signs the payload using ECDSA

func (*ECDSAAlgorithm) Verify ΒΆ

func (e *ECDSAAlgorithm) Verify(payload, signature []byte) error

Verify verifies the signature using ECDSA

type EdDSAAlgorithm ΒΆ

type EdDSAAlgorithm struct {
	// contains filtered or unexported fields
}

EdDSAAlgorithm implements EdDSA-based JWT signing (Ed25519)

func (*EdDSAAlgorithm) Header ΒΆ

func (e *EdDSAAlgorithm) Header() []byte

Header returns the algorithm header

func (*EdDSAAlgorithm) Name ΒΆ

func (e *EdDSAAlgorithm) Name() string

Name returns the algorithm name

func (*EdDSAAlgorithm) Sign ΒΆ

func (e *EdDSAAlgorithm) Sign(payload []byte) ([]byte, error)

Sign signs the payload using EdDSA

func (*EdDSAAlgorithm) Verify ΒΆ

func (e *EdDSAAlgorithm) Verify(payload, signature []byte) error

Verify verifies the signature using EdDSA

type HMACAlgorithm ΒΆ

type HMACAlgorithm struct {
	// contains filtered or unexported fields
}

HMACAlgorithm implements HMAC-based JWT signing

func (*HMACAlgorithm) Header ΒΆ

func (h *HMACAlgorithm) Header() []byte

Header returns the algorithm header

func (*HMACAlgorithm) Name ΒΆ

func (h *HMACAlgorithm) Name() string

Name returns the algorithm name

func (*HMACAlgorithm) Sign ΒΆ

func (h *HMACAlgorithm) Sign(payload []byte) ([]byte, error)

Sign signs the payload using HMAC

func (*HMACAlgorithm) Verify ΒΆ

func (h *HMACAlgorithm) Verify(payload, signature []byte) error

Verify verifies the signature using HMAC

type RSAAlgorithm ΒΆ

type RSAAlgorithm struct {
	// contains filtered or unexported fields
}

RSAAlgorithm implements RSA-based JWT signing

func (*RSAAlgorithm) Header ΒΆ

func (r *RSAAlgorithm) Header() []byte

Header returns the algorithm header

func (*RSAAlgorithm) Name ΒΆ

func (r *RSAAlgorithm) Name() string

Name returns the algorithm name

func (*RSAAlgorithm) Sign ΒΆ

func (r *RSAAlgorithm) Sign(payload []byte) ([]byte, error)

Sign signs the payload using RSA

func (*RSAAlgorithm) Verify ΒΆ

func (r *RSAAlgorithm) Verify(payload, signature []byte) error

Verify verifies the signature using RSA

type Signer ΒΆ

type Signer interface {
	crypto.Signer
}

Signer represents a key that can sign JWT tokens

type StandardClaims ΒΆ

type StandardClaims struct {
	Subject   string `json:"sub,omitempty"`
	IssuedAt  int64  `json:"iat"`
	ExpiresAt int64  `json:"exp"`
	NotBefore int64  `json:"nbf,omitempty"`
	Issuer    string `json:"iss,omitempty"`
	Audience  string `json:"aud,omitempty"`
	JwtID     string `json:"jti,omitempty"`
}

StandardClaims represents standard JWT claims that are always present

type TokenSigner ΒΆ

type TokenSigner[T any] struct {
	// contains filtered or unexported fields
}

TokenSigner represents a JWT token signer (Auth Service)

func NewTokenSigner ΒΆ

func NewTokenSigner[T any](algorithm Algorithm, issuer string) (*TokenSigner[T], error)

NewTokenSigner creates a new token signer for generating JWTs

func (*TokenSigner[T]) GenerateToken ΒΆ

func (s *TokenSigner[T]) GenerateToken(subject string, duration time.Duration, customClaims T) (string, error)

GenerateToken creates a new JWT token with custom claims

type TokenVerifier ΒΆ

type TokenVerifier[T any] struct {
	// contains filtered or unexported fields
}

TokenVerifier represents a JWT token verifier (Client Service)

func NewTokenVerifier ΒΆ

func NewTokenVerifier[T any](algorithm Algorithm, issuer string) (*TokenVerifier[T], error)

NewTokenVerifier creates a new token verifier for validating JWTs

func (*TokenVerifier[T]) VerifyToken ΒΆ

func (v *TokenVerifier[T]) VerifyToken(tokenString string) (*StandardClaims, *T, error)

VerifyToken validates a JWT token and returns the claims

type Verifier ΒΆ

type Verifier interface {
	// For HMAC algorithms, this will be the same as Signer
	// For asymmetric algorithms, this will be the public key
	Verify(payload []byte, signature []byte) error
}

Verifier represents a key that can verify JWT signatures

Jump to

Keyboard shortcuts

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