Documentation
¶
Overview ¶
Package authjwt provides JWT authentication middleware and token lifecycle management for the Einherjar framework. It supports HMAC-SHA256 (HS256), RSA-SHA256 (RS256), and ECDSA (ES256/ES384/ES512).
Typical wiring ¶
signer := authjwt.NewHMACSigner([]byte(os.Getenv("JWT_SECRET")))
cfg := authjwt.TokenConfig{
AccessTTL: 15 * time.Minute,
RefreshTTL: 7 * 24 * time.Hour,
Issuer: "myapp",
}
// Verify Bearer tokens and inject uid+claims into context.
srv.Use(authjwt.AuthMiddleware(logger, signer, []string{"/health", "/auth/*"}))
// Enrichment and authz from auth/authmw follow downstream.
srv.Use(authmw.EnrichmentMiddleware(logger, userEnricher))
// Issue tokens on login:
pair, err := authjwt.IssueTokenPair(signer, uid, customClaims, cfg)
// Rotate tokens on refresh:
newPair, err := authjwt.RefreshTokenPair(ctx, signer, body.RefreshToken, blacklist, cfg, freshClaims)
if errors.Is(err, authjwt.ErrTokenRevoked) {
// replay attack — force re-login
}
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrTokenRevoked = errors.New("token revoked")
ErrTokenRevoked is returned by RefreshTokenPair when the JTI is on the blacklist. Use errors.Is(err, authjwt.ErrTokenRevoked) to distinguish replay attacks from infrastructure errors.
var Module observability.Identifiable = &moduleID{}
Module identifies this package to observability systems. auth-jwt is a function library — it is not registered with the launcher as a lifecycle component. Register Module manually with any version registry if needed.
Functions ¶
func AuthMiddleware ¶
func AuthMiddleware(logger logging.Logger, verifier Verifier, publicPaths []string) func(http.Handler) http.Handler
AuthMiddleware verifies the Bearer access token and injects uid + claims into context via authmw.SetTokenData. Downstream authmw.EnrichmentMiddleware reads them transparently.
Accepts a Verifier — pass a Signer when the service issues tokens, or a NewRSAPublicKeyVerifier/NewECPublicKeyVerifier when it only verifies.
Requests to publicPaths are skipped without verification (path.Match wildcards supported). Returns 401 on missing, invalid, or expired tokens.
Types ¶
type Blacklist ¶
type Blacklist interface {
IsRevoked(ctx context.Context, jti string) (bool, error)
Revoke(ctx context.Context, jti string, ttl time.Duration) error
}
Blacklist records and checks revoked refresh token JTIs. Satisfied by einherjar/cache-valkey via duck typing. TTL on Revoke should match the token's remaining lifetime so entries expire naturally.
type Signer ¶
Signer signs and verifies JWTs. NewHMACSigner, NewRSASigner, and NewECSigner return implementations backed by HS256, RS256, and ES256/ES384/ES512 respectively.
func NewECSigner ¶
func NewECSigner(privateKey *ecdsa.PrivateKey) Signer
NewECSigner returns a Signer backed by ECDSA. The signing algorithm is auto-detected from the key's curve: P-256→ES256, P-384→ES384, P-521→ES512.
func NewECSignerFromPEM ¶
NewECSignerFromPEM parses a PKCS#8 PEM-encoded ECDSA private key.
func NewHMACSigner ¶
NewHMACSigner returns a Signer backed by HMAC-SHA256 (HS256). secret should be at least 32 bytes; shorter values are accepted but weakened.
func NewRSASigner ¶
func NewRSASigner(privateKey *rsa.PrivateKey) Signer
NewRSASigner returns a Signer backed by RSA-SHA256 (RS256). The public key is derived from the private key — no separate argument needed.
func NewRSASignerFromPEM ¶
NewRSASignerFromPEM parses a PKCS#8 or PKCS#1 PEM-encoded RSA private key.
type TokenConfig ¶
TokenConfig configures token lifetimes and the issuer claim.
type TokenPair ¶
type TokenPair struct {
AccessToken string
RefreshToken string
ExpiresIn int64 // seconds until the access token expires
}
TokenPair holds an access token and a refresh token.
func IssueTokenPair ¶
func IssueTokenPair(signer Signer, uid string, customClaims map[string]any, cfg TokenConfig) (TokenPair, error)
IssueTokenPair signs a new access + refresh token pair for uid. customClaims are merged into the access token at the top level. Use this to embed per-resource permission masks so ClaimsPermissionProvider can read them without a DB call. The refresh token carries only sub, iss, iat, exp, jti, and fam (token family).
func RefreshTokenPair ¶
func RefreshTokenPair(ctx context.Context, signer Signer, refreshToken string, bl Blacklist, cfg TokenConfig, customClaims map[string]any) (TokenPair, error)
RefreshTokenPair validates refreshToken, checks the blacklist, revokes the old JTI, and issues a new token pair for the same uid. customClaims are merged into the new access token — re-fetch fresh permissions here so role changes take effect without revoking outstanding access tokens. Returns ErrTokenRevoked if the JTI is already on the blacklist (replay attack or re-use after rotation).
type Verifier ¶
Verifier validates JWT strings. Services that verify tokens but never issue them use a Verifier (e.g. NewRSAPublicKeyVerifier, NewECPublicKeyVerifier) instead of the full Signer.
func NewECPublicKeyVerifier ¶
NewECPublicKeyVerifier returns a Verifier backed by an ECDSA public key. Use this in services that verify tokens but never issue them.
func NewECPublicKeyVerifierFromPEM ¶
NewECPublicKeyVerifierFromPEM parses a PKIX PEM-encoded ECDSA public key.
func NewRSAPublicKeyVerifier ¶
NewRSAPublicKeyVerifier returns a Verifier backed by an RSA public key. Use this in services that verify tokens but never issue them.
func NewRSAPublicKeyVerifierFromPEM ¶
NewRSAPublicKeyVerifierFromPEM parses a PKIX or PKCS#1 PEM-encoded RSA public key.