-
Release v1.0.0 Stable
released this
2026-05-29 10:13:27 -06:00 | 0 commits to main since this releasev1.0.0
code.nochebuena.dev/einherjar/auth-jwt
Architecture Decisions Resolved
Decision Outcome Root factory Excluded — HMAC vs RSA vs EC is a caller choice; no universal default exists (see ADR-001) Logger in AuthMiddleware Added — 401 responses routed through httputil.Errorfor Warn-level visibility (see ADR-002)web dependency Accepted — auth-jwtdepends on web solely forhttputil.Error(see ADR-003)ErrTokenRevoked type Plain errors.Newsentinel — idiomatic Go, works witherrors.IswithoutIs()method (see ADR-004)EC algorithm selection Auto-detected from key curve — eliminates misconfiguration class (see ADR-005)
API
import authjwt "code.nochebuena.dev/einherjar/auth-jwt" // Package sentinel // Module identifies this package to observability systems. // auth-jwt is a function-only package — not registered with the launcher as a lifecycle component. // Register Module manually with any version registry if needed. var Module observability.Identifiable // Interfaces type Verifier interface { Verify(tokenString string) (*jwt.Token, error) } type Signer interface { Verifier Sign(claims jwt.Claims) (string, error) } type Blacklist interface { IsRevoked(ctx context.Context, jti string) (bool, error) Revoke(ctx context.Context, jti string, ttl time.Duration) error } // Value types type TokenConfig struct { AccessTTL time.Duration RefreshTTL time.Duration Issuer string } type TokenPair struct { AccessToken string RefreshToken string ExpiresIn int64 } // Sentinel var ErrTokenRevoked = errors.New("token revoked") // Constructors — HMAC func NewHMACSigner(secret []byte) Signer // Constructors — RSA func NewRSASigner(privateKey *rsa.PrivateKey) Signer func NewRSASignerFromPEM(pemKey []byte) (Signer, error) func NewRSAPublicKeyVerifier(publicKey *rsa.PublicKey) Verifier func NewRSAPublicKeyVerifierFromPEM(pemKey []byte) (Verifier, error) // Constructors — EC (algorithm auto-detected from curve) func NewECSigner(privateKey *ecdsa.PrivateKey) Signer func NewECSignerFromPEM(pemKey []byte) (Signer, error) func NewECPublicKeyVerifier(publicKey *ecdsa.PublicKey) Verifier func NewECPublicKeyVerifierFromPEM(pemKey []byte) (Verifier, error) // Token lifecycle func IssueTokenPair(signer Signer, uid string, customClaims map[string]any, cfg TokenConfig) (TokenPair, error) func RefreshTokenPair(ctx context.Context, signer Signer, refreshToken string, bl Blacklist, cfg TokenConfig, customClaims map[string]any) (TokenPair, error) // HTTP middleware func AuthMiddleware(logger logging.Logger, verifier Verifier, publicPaths []string) func(http.Handler) http.Handler
Wiring example
signer := authjwt.NewHMACSigner([]byte(os.Getenv("JWT_SECRET"))) cfg := authjwt.TokenConfig{ AccessTTL: 15 * time.Minute, RefreshTTL: 7 * 24 * time.Hour, Issuer: "myapp", } srv.Use(authjwt.AuthMiddleware(logger, signer, []string{"/health", "/auth/*"})) srv.Use(authmw.EnrichmentMiddleware(logger, userEnricher)) pair, err := authjwt.IssueTokenPair(signer, uid, customClaims, cfg) newPair, err := authjwt.RefreshTokenPair(ctx, signer, body.RefreshToken, blacklist, cfg, freshClaims)
Install
go get code.nochebuena.dev/einherjar/auth-jwt@v1.0.0
Dependencies
Module Version Role code.nochebuena.dev/einherjar/authv1.0.0 authmw.SetTokenData/authmw.GetClaimsintegration contractcode.nochebuena.dev/einherjar/contractsv1.0.0 logging.Logger,security.*code.nochebuena.dev/einherjar/corev1.0.0 xerrors.Unauthorizedcode.nochebuena.dev/einherjar/webv1.0.0 httputil.Errorgithub.com/golang-jwt/jwt/v5v5.2.1 JWT signing, verification, claims Downloads