jwt

package
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: Oct 1, 2026 License: MIT Imports: 12 Imported by: 0

README

JWT Authentication (platform/jwt)

HMAC-SHA256 (HS256) access token signing, validation, and automatic 3-way context enrichment across context.Context, structured slog logging, and OpenTelemetry distributed tracing.


1. Configuration (conf.toml)

[jwt]
secret = "your-secret-key-min-32-chars" # [REQUIRED] HMAC-SHA256 signing secret
expiration = "24h"                      # Optional, default: 24h
Environment Variables

Config structs declare relative tags (env:"SECRET"). When embedded in a Sling service with the standard env-prefix:"JWT_", they resolve to:

Config Key Relative Tag Standard Service Env (with env-prefix) Default
secret env:"SECRET" JWT_SECRET none (required)
expiration env:"EXPIRATION" JWT_EXPIRATION 24h

2. Usage

A. Initialization & Route Protection (cmd/<service>/main.go)
auth := jwt.NewHS256(cfg.JWT)

r.Route("/v1", func(r chi.Router) {
    // Public routes (no auth required)
    r.Post("/login", h.Login)

    // Protected routes (401 Unauthorized if token is missing or invalid)
    r.Group(func(r chi.Router) {
        r.Use(jwt.RequireAuth(auth))

        r.Get("/profile", h.GetProfile)
        r.Post("/orders", h.CreateOrder)
    })

    // Optional auth routes (proceeds anonymously if token absent; enriches context if present)
    r.Group(func(r chi.Router) {
        r.Use(jwt.OptionalAuth(auth))
        r.Get("/catalog", h.ListCatalog)
    })
})
B. Extracting Identity in Handlers (handler.go)
func (h *Handler) CreateOrder(w http.ResponseWriter, r *http.Request) {
    // Panics if RequireAuth was not used; returns uuid.UUID
    userID := jwt.MustUserID(r.Context())

    // Or safe extraction:
    // userID, ok := jwt.UserID(r.Context())

    // Context logger and OpenTelemetry span are ALREADY enriched
    // Log will automatically include: user_id=<uuid>
    // Jaeger trace span will automatically include attribute: enduser.id = <uuid>
    logger.Info(r.Context(), "creating order", "amount", 100)

    httpx.JSON(w, http.StatusCreated, map[string]any{"user_id": userID})
}
C. Issuing Access Tokens (service.go or handler.go)
userID := uuid.NewV7()
tokenString, err := auth.SignAccess(userID)
if err != nil {
    // handle error
}

3. Features

  • Zero-Touch Context Enrichment: When a valid token is verified, the middleware automatically injects user_id into the logger (slog) and labels the active OpenTelemetry span with semconv.EnduserIDKey.
  • Fail-Fast Error Handling: Rejects invalid, tampered, or expired tokens immediately with standardized 401 Unauthorized responses via httpx.WriteError.

Documentation

Overview

Package jwt provides JWT signing, verification, and HTTP authentication middleware.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrTokenExpired indicates that the provided JWT has expired.
	ErrTokenExpired = errors.New("token is expired")
	// ErrInvalidToken indicates that the provided JWT is malformed or has an invalid signature.
	ErrInvalidToken = errors.New("invalid token")
	// ErrMissingToken indicates that the Authorization header is absent.
	ErrMissingToken = errors.New("missing authorization header")
)

Functions

func MustUserID

func MustUserID(ctx context.Context) uuid.UUID

MustUserID extracts the user ID from the context or panics if not found.

func OptionalAuth

func OptionalAuth(verifier TokenVerifier) func(http.Handler) http.Handler

OptionalAuth inspects the Authorization header if present. Valid tokens enrich the context, missing headers continue unauthenticated, and invalid tokens return 401 Unauthorized.

func RequireAuth

func RequireAuth(verifier TokenVerifier) func(http.Handler) http.Handler

RequireAuth enforces valid JWT authentication. If the token is missing, expired, or invalid, it responds with 401 Unauthorized via httpx.WriteError.

func UserID

func UserID(ctx context.Context) (uuid.UUID, bool)

UserID extracts the user ID from the context if present.

func WithUserID

func WithUserID(ctx context.Context, id uuid.UUID) context.Context

WithUserID stores the user ID in the context.

Types

type Config

type Config struct {
	Secret     string        `toml:"secret" env:"SECRET" env-required:"true" comment:"JWT HMAC-SHA256 secret key"`
	Expiration time.Duration `toml:"expiration" env:"EXPIRATION" env-default:"24h" comment:"Access token expiration duration"`
}

Config defines JWT authentication parameters.

type HS256

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

HS256 implements TokenSigner and TokenVerifier using HMAC-SHA256.

func NewHS256

func NewHS256(cfg Config) *HS256

NewHS256 creates a new HMAC-SHA256 signer and verifier.

func (*HS256) SignAccess

func (s *HS256) SignAccess(userID uuid.UUID) (string, error)

SignAccess generates a signed access token for the given user ID.

func (*HS256) VerifyToken

func (s *HS256) VerifyToken(ctx context.Context, tokenStr string) (uuid.UUID, error)

VerifyToken parses and verifies the token string, returning the associated user ID.

type TokenSigner

type TokenSigner interface {
	SignAccess(userID uuid.UUID) (string, error)
}

TokenSigner generates signed access tokens for users.

type TokenVerifier

type TokenVerifier interface {
	VerifyToken(ctx context.Context, tokenStr string) (uuid.UUID, error)
}

TokenVerifier validates and extracts user identity from access tokens.

type UserClaims

type UserClaims struct {
	jwt.RegisteredClaims
	UserID string `json:"user_id"`
}

UserClaims defines custom JWT claims including user ID.

Jump to

Keyboard shortcuts

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