jwt

package
v0.27.2 Latest Latest
Warning

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

Go to latest
Published: Aug 31, 2026 License: MIT Imports: 25 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// EventJWTSignBefore is emitted immediately before a JWT is constructed and signed.
	// Payload: *JWTSignBeforeEventPayload
	EventJWTSignBefore = "jwt:sign:before"

	// EventJWTSignAfter is emitted after a JWT has been successfully signed.
	// Payload: *JWTSignAfterEventPayload
	EventJWTSignAfter = "jwt:sign:after"

	// EventJWTVerifyBefore is emitted right before token verification begins.
	// Payload: *JWTVerifyBeforeEventPayload
	EventJWTVerifyBefore = "jwt:verify:before"

	// EventJWTVerifyAfter is emitted after token verification completes.
	// Payload: *JWTVerifyAfterEventPayload
	EventJWTVerifyAfter = "jwt:verify:after"

	// EventJWTRotateBefore is emitted before rotating key pairs.
	// Payload: *JWTRotateBeforeEventPayload
	EventJWTRotateBefore = "jwt:rotate:before"

	// EventJWTRotateAfter is emitted after a new key pair has been generated and persisted.
	// Payload: *JWTRotateAfterEventPayload
	EventJWTRotateAfter = "jwt:rotate:after"

	// EventJWTIssued is emitted when a new JWT is issued for an authenticated session.
	// Payload: *JWTIssuedEventPayload
	EventJWTIssued = "jwt:token:issued"
)
View Source
const (
	// ExtraKeySubject stores the subject identifier ("sub") within dynamic Extra metadata.
	// Expected type: string.
	ExtraKeySubject = "subject"

	// ExtraKeyClaims stores custom claims map within dynamic Extra metadata.
	// Expected type: map[string]any.
	ExtraKeyClaims = "claims"

	// ExtraKeyKeyID stores the active Key ID ("kid") within dynamic Extra metadata.
	// Expected type: string.
	ExtraKeyKeyID = "key_id"

	// ExtraKeySessionID stores the associated session identifier within dynamic Extra metadata.
	// Expected type: string.
	ExtraKeySessionID = "session_id"

	// ExtraKeyUserID stores the owner user identifier within dynamic Extra metadata.
	// Expected type: string.
	ExtraKeyUserID = "user_id"

	// ExtraKeyTokenSource identifies the extraction origin of the token (e.g., "header", "cookie", "param").
	// Expected type: string.
	ExtraKeyTokenSource = "token_source"
)

Standard Extra metadata keys that can be set or consumed in JWT operations (such as in SignParams.Extra, VerifyParams.Extra, and Event payloads).

View Source
const (
	// HeaderAuthorization is the standard RFC 7235 HTTP Authorization header name.
	HeaderAuthorization = "Authorization"

	// HeaderSetAuthJWT is the default HTTP response header name used to expose the issued JWT.
	HeaderSetAuthJWT = "set-auth-jwt"

	// HeaderAccessControlExposeHeaders is the standard CORS response header used to expose custom headers to client browsers.
	HeaderAccessControlExposeHeaders = "Access-Control-Expose-Headers"

	// BearerSchemePrefix is the standard case-insensitive scheme prefix preceding bearer tokens in Authorization headers.
	BearerSchemePrefix = "bearer "
)

Standard HTTP header and authentication scheme constants.

View Source
const (
	ClaimsContextKey  contextKey = "jwt_claims"
	SubjectContextKey contextKey = "jwt_subject"
	TokenContextKey   contextKey = "jwt_token"
)
View Source
const (
	// ContextKeyJWKPrefix is the key prefix used when caching active JWK keys in plugin.Context.
	ContextKeyJWKPrefix = "jwt:jwk:"
)

Shared plugin context keys used for internal state and JWK caching in plugin.Context.

View Source
const PluginID = "jwt"

PluginID is the unique string identifier for the JWT plugin ("jwt").

Variables

View Source
var (
	// ErrKeyNotFound is returned when no active or matching signing key is found in the repository.
	ErrKeyNotFound = errors.New("jwt: signing key not found in repository")

	// ErrInvalidToken is returned when a JWT string does not adhere to the 3-part RFC 7519 format.
	ErrInvalidToken = errors.New("jwt: invalid token format")

	// ErrTokenExpired is returned when a token's 'exp' claim is prior to the current verification time.
	ErrTokenExpired = errors.New("jwt: token has expired")

	// ErrTokenNotValidYet is returned when a token's 'nbf' claim is subsequent to the current verification time.
	ErrTokenNotValidYet = errors.New("jwt: token is not valid yet (nbf)")

	// ErrInvalidSignature is returned when cryptographic signature verification fails.
	ErrInvalidSignature = errors.New("jwt: invalid token signature")

	// ErrMissingKid is returned when a token's JWS header lacks the required 'kid' (Key ID) parameter.
	ErrMissingKid = errors.New("jwt: token header missing 'kid'")

	// ErrDecryptionFailed is returned when an encrypted private key cannot be decrypted with the configured secret.
	ErrDecryptionFailed = errors.New("jwt: failed to decrypt private key with configured secret")

	// ErrUnsupportedAlgorithm is returned when an unsupported or unrecognized signature algorithm is requested.
	ErrUnsupportedAlgorithm = errors.New("jwt: unsupported signature algorithm")

	// ErrSecretRequired is returned when private key encryption is enabled but no secret key is provided.
	ErrSecretRequired = errors.New("jwt: secret key is required for private key encryption")

	// ErrSessionNotFound is returned when attempting to generate a token for an invalid or missing session.
	ErrSessionNotFound = errors.New("jwt: session not found")

	// ErrSessionExpired is returned when the provided session has expired.
	ErrSessionExpired = errors.New("jwt: session has expired")
)

Functions

func DecryptPrivateKey

func DecryptPrivateKey(encryptedPayloadB64 string, secret string) ([]byte, error)

DecryptPrivateKey decrypts base64url-encoded AES-256-GCM ciphertext using the configured secret.

func EncryptPrivateKey

func EncryptPrivateKey(rawKeyBytes []byte, secret string) (string, error)

EncryptPrivateKey encrypts raw private key bytes using AES-256-GCM authenticated encryption.

func JWKCacheKey

func JWKCacheKey(kid string) string

JWKCacheKey formats the context store key used to track or cache a JWK key in the shared context.

func ParsePrivateKeyFromBytes

func ParsePrivateKeyFromBytes(derBytes []byte) (crypto.PrivateKey, error)

ParsePrivateKeyFromBytes reconstructs a crypto.PrivateKey from PKCS#8 DER bytes.

func ParsePublicKeyFromJWK

func ParsePublicKeyFromJWK(jwk *JWK) (crypto.PublicKey, error)

ParsePublicKeyFromJWK extracts a crypto.PublicKey from an RFC 7517 JWK.

func SignJWT

func SignJWT(header JWTHeader, payload map[string]any, privKey crypto.PrivateKey, alg Algorithm) (string, error)

SignJWT creates and cryptographically signs a compact serialized JWT (RFC 7519).

Types

type Algorithm

type Algorithm string

Algorithm defines the cryptographic signature algorithm type.

const (
	// AlgEdDSA represents Ed25519 signature algorithm (RFC 8037 / RFC 8032) - default.
	AlgEdDSA Algorithm = "EdDSA"

	// AlgES256 represents ECDSA using P-256 curve and SHA-256 (RFC 7518).
	AlgES256 Algorithm = "ES256"

	// AlgES512 represents ECDSA using P-521 curve and SHA-512 (RFC 7518).
	AlgES512 Algorithm = "ES512"

	// AlgRS256 represents RSASSA-PKCS1-v1_5 using SHA-256 (RFC 7518).
	AlgRS256 Algorithm = "RS256"

	// AlgPS256 represents RSASSA-PSS using SHA-256 and MGF1 (RFC 7518).
	AlgPS256 Algorithm = "PS256"
)

Supported JSON Web Signature (JWS) algorithm identifiers.

type Config

type Config struct {
	// Issuer defines the "iss" claim value included in generated tokens (default: "GoModularAuth").
	Issuer string

	// Audience defines the "aud" claim list validated and included in generated tokens.
	Audience []string

	// ExpirationTime defines the validity duration ("exp" claim) for issued tokens (default: 15 minutes).
	ExpirationTime time.Duration

	// Algorithm specifies the asymmetric signature algorithm to use (default: AlgEdDSA / Ed25519).
	Algorithm Algorithm

	// RSABits specifies the key size in bits when using RSA algorithms (RS256/PS256, default: 2048).
	RSABits int

	// RotationInterval defines how frequently active signing keys should be rotated (0 = rotation disabled).
	RotationInterval time.Duration

	// GracePeriod defines how long expired keys remain available in JWKS for token verification (default: 30 days).
	GracePeriod time.Duration

	// Secret defines the symmetric encryption key used to protect private keys in storage via AES-256-GCM.
	Secret string

	// DisablePrivateKeyEncryption specifies whether private keys should be stored unencrypted in repository.
	DisablePrivateKeyEncryption bool

	// ClockSkewLeeway defines the acceptable clock skew window during exp and nbf validation (default: 1 minute).
	ClockSkewLeeway time.Duration

	// DefinePayload is an optional custom callback to inject extra claims into session-based tokens.
	DefinePayload PayloadFunc

	// GetSubject is an optional custom callback to resolve the "sub" claim from session and user.
	GetSubject SubjectFunc
}

Config holds all configuration parameters for the JWT plugin.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns the default production configuration for the JWT plugin.

type GetJWKSParams

type GetJWKSParams struct {
	// IncludeExpired specifies whether to include keys older than the grace period (default: false).
	IncludeExpired bool `json:"include_expired,omitempty"`

	plugin.ExtraContainer
}

GetJWKSParams defines parameters to retrieve the public JSON Web Key Set.

type GetJWKSResult

type GetJWKSResult struct {
	// JWKS is the RFC 7517 JSON Web Key Set containing active and grace-period public keys.
	JWKS *JWKS `json:"jwks"`

	// KeysCount is the number of public keys included.
	KeysCount int `json:"keys_count"`
}

GetJWKSResult contains the public JWKS collection and metadata.

type GetTokenParams

type GetTokenParams struct {
	// Session is the active authenticated session (required).
	Session *entity.Session `json:"session"`

	// User is the authenticated user entity (optional, provides email/name for custom claims).
	User *entity.User `json:"user,omitempty"`

	// ExpiresIn overrides the default validity duration for this session token (optional).
	ExpiresIn time.Duration `json:"expires_in,omitempty"`

	plugin.ExtraContainer
}

GetTokenParams defines parameters to generate a signed JWT for an active session and user.

type GetTokenResult

type GetTokenResult struct {
	// Token is the issued compact JWT string.
	Token string `json:"token"`

	// KeyID is the key identifier used for the signature.
	KeyID string `json:"key_id"`

	// Algorithm is the cryptographic signature algorithm used.
	Algorithm Algorithm `json:"alg"`

	// ExpiresAt is the token expiration timestamp.
	ExpiresAt time.Time `json:"expires_at"`

	// HeaderValue is the formatted Authorization header string ("Bearer <token>").
	HeaderValue string `json:"header_value"`

	// AuthJWTHeader is the standard response header name ("set-auth-jwt").
	AuthJWTHeader string `json:"auth_jwt_header"`
}

GetTokenResult contains the generated session JWT and HTTP header representations.

type JWK

type JWK struct {
	// Kty is the Key Type ("OKP", "EC", "RSA").
	Kty string `json:"kty"`

	// Kid is the unique Key ID string.
	Kid string `json:"kid"`

	// Use specifies the intended public key use (usually "sig").
	Use string `json:"use,omitempty"`

	// Alg identifies the cryptographic algorithm intended for use with the key.
	Alg string `json:"alg,omitempty"`

	// Crv identifies the cryptographic curve (for "OKP" and "EC" keys).
	Crv string `json:"crv,omitempty"`

	// X contains the Base64URL-encoded public key coordinate (or public Ed25519 key).
	X string `json:"x,omitempty"`

	// Y contains the Base64URL-encoded Y coordinate (for EC keys).
	Y string `json:"y,omitempty"`

	// N contains the Base64URL-encoded RSA modulus.
	N string `json:"n,omitempty"`

	// E contains the Base64URL-encoded RSA exponent.
	E string `json:"e,omitempty"`
}

JWK represents a single JSON Web Key conforming to RFC 7517.

type JWKRecord

type JWKRecord struct {
	// ID is the unique Key ID ("kid") assigned to this key-pair.
	ID string `json:"id"`

	// PublicKey is the serialized JSON representation of the RFC 7517 public JWK.
	PublicKey string `json:"publicKey"`

	// PrivateKey is the serialized private key bytes or base64url-encoded AES-256-GCM ciphertext.
	PrivateKey string `json:"privateKey"`

	// Algorithm specifies the JWS signing algorithm (e.g. EdDSA, ES256, RS256).
	Algorithm Algorithm `json:"alg"`

	// Curve specifies the elliptic curve name for EC/OKP keys (e.g. "Ed25519", "P-256", "P-521").
	Curve string `json:"crv,omitempty"`

	// CreatedAt is the timestamp when the key-pair was generated.
	CreatedAt time.Time `json:"createdAt"`

	// ExpiresAt is the optional expiration timestamp after which this key is rotated out of active signing.
	ExpiresAt *time.Time `json:"expiresAt,omitempty"`
}

JWKRecord represents the persisted cryptographic key-pair record in the database.

func GenerateKeyPair

func GenerateKeyPair(alg Algorithm, rsaBits int) (*JWKRecord, crypto.PrivateKey, error)

GenerateKeyPair generates a new cryptographic key pair for the specified algorithm, creating a JWKRecord and returning the private key.

type JWKS

type JWKS struct {
	// Keys is the collection of public JSON Web Keys.
	Keys []JWK `json:"keys"`
}

JWKS represents a JSON Web Key Set conforming to RFC 7517.

type JWTHeader

type JWTHeader struct {
	Alg string `json:"alg"`
	Typ string `json:"typ"`
	Kid string `json:"kid"`
}

JWTHeader represents the JWS header structure conforming to RFC 7515 / RFC 7519.

func ExtractUnverifiedHeader

func ExtractUnverifiedHeader(tokenStr string) (*JWTHeader, error)

ExtractUnverifiedHeader extracts the JWT header without signature verification to inspect kid/alg.

func ParseAndVerifySignature

func ParseAndVerifySignature(tokenStr string, pubKey crypto.PublicKey, expectedAlg Algorithm) (*JWTHeader, map[string]any, error)

ParseAndVerifySignature parses the token, checks format, and verifies signature with the public key.

type JWTIssuedEventPayload

type JWTIssuedEventPayload struct {
	// Token is the issued compact JWT string.
	Token string

	// KeyID is the key identifier used for the signature.
	KeyID string

	// Subject is the "sub" claim value.
	Subject string

	// SessionID is the associated session identifier (if applicable).
	SessionID string

	// UserID is the associated user identifier (if applicable).
	UserID string
}

JWTIssuedEventPayload contains metadata when a JWT is issued for a session.

type JWTRotateAfterEventPayload

type JWTRotateAfterEventPayload struct {
	// NewKeyID is the identifier of the newly active key.
	NewKeyID string

	// Algorithm is the cryptographic algorithm of the new key.
	Algorithm Algorithm

	// CreatedAt is the timestamp when the new key was created.
	CreatedAt time.Time
}

JWTRotateAfterEventPayload contains details of the newly generated key pair.

type JWTRotateBeforeEventPayload

type JWTRotateBeforeEventPayload struct {
	// CurrentKeyID is the active key ID being rotated out.
	CurrentKeyID string

	// Params contains rotation configuration parameters.
	Params *RotateKeysParams
}

JWTRotateBeforeEventPayload contains parameters prior to key rotation.

type JWTSignAfterEventPayload

type JWTSignAfterEventPayload struct {
	// Token is the serialized compact JWT string.
	Token string

	// KeyID is the ID of the key used to sign the token.
	KeyID string

	// Algorithm is the cryptographic algorithm used.
	Algorithm Algorithm

	// ExpiresAt is the token expiration timestamp.
	ExpiresAt time.Time
}

JWTSignAfterEventPayload contains the resulting token details after signing.

type JWTSignBeforeEventPayload

type JWTSignBeforeEventPayload struct {
	// Params contains the mutable signing parameters (including Extra metadata).
	Params *SignParams

	// Subject is the resolved subject string ("sub").
	Subject string

	// Claims contains mutable custom payload claims.
	Claims map[string]any
}

JWTSignBeforeEventPayload contains payload data for pre-signing lifecycle interception.

type JWTVerifyAfterEventPayload

type JWTVerifyAfterEventPayload struct {
	// Token is the processed JWT string.
	Token string

	// Valid indicates whether the token signature and standard claims were valid.
	Valid bool

	// KeyID is the key ID extracted from the token header.
	KeyID string

	// Claims contains the unmarshaled payload claims (if valid).
	Claims map[string]any

	// Error contains the verification failure reason (if invalid).
	Error error
}

JWTVerifyAfterEventPayload reports the result of a token verification attempt.

type JWTVerifyBeforeEventPayload

type JWTVerifyBeforeEventPayload struct {
	// Token is the raw JWT string to verify.
	Token string

	// Params contains mutable verification parameters.
	Params *VerifyParams
}

JWTVerifyBeforeEventPayload contains pre-verification token data.

type Option

type Option func(*Config)

Option defines a functional configuration option for the JWT plugin.

func WithAlgorithm

func WithAlgorithm(alg Algorithm) Option

WithAlgorithm sets the asymmetric cryptographic algorithm used for signing tokens.

func WithAudience

func WithAudience(audience ...string) Option

WithAudience sets the recipient audience values ("aud" claim) for issued JWT tokens.

func WithClockSkewLeeway

func WithClockSkewLeeway(leeway time.Duration) Option

WithClockSkewLeeway sets the time window tolerance allowed when validating exp and nbf claims.

func WithDefinePayload

func WithDefinePayload(fn PayloadFunc) Option

WithDefinePayload configures a custom callback to generate custom claims for session tokens.

func WithDisablePrivateKeyEncryption

func WithDisablePrivateKeyEncryption(disable bool) Option

WithDisablePrivateKeyEncryption disables AES-256-GCM encryption of private keys in storage.

func WithExpiration

func WithExpiration(duration time.Duration) Option

WithExpiration sets the default validity duration for issued JWT tokens.

func WithGetSubject

func WithGetSubject(fn SubjectFunc) Option

WithGetSubject configures a custom callback to resolve the "sub" claim for session tokens.

func WithGracePeriod

func WithGracePeriod(grace time.Duration) Option

WithGracePeriod configures how long rotated/expired keys are preserved in JWKS for validation.

func WithIssuer

func WithIssuer(issuer string) Option

WithIssuer sets the issuer identifier ("iss" claim) included in issued JWT tokens.

func WithRSABits

func WithRSABits(bits int) Option

WithRSABits sets the RSA key size in bits (minimum 2048).

func WithRotationInterval

func WithRotationInterval(interval time.Duration) Option

WithRotationInterval configures automatic key rotation interval.

func WithSecret

func WithSecret(secret string) Option

WithSecret sets the symmetric secret key used for AES-256-GCM private key encryption in repository.

type PayloadFunc

type PayloadFunc func(session *entity.Session, user *entity.User) (map[string]any, error)

PayloadFunc defines a custom callback function to build additional custom claims for session-based JWTs.

type Plugin

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

Plugin implements RFC 7519 JSON Web Token issuance, verification, and JWKS key management.

func New

func New(repo Repository, opts ...Option) *Plugin

New creates a new JWT plugin instance configured with a key repository and functional options.

Arguments:

  • repo: Implementation of jwt.Repository interface (can be in-memory or database).
  • opts: Functional configuration options (WithIssuer, WithAlgorithm, WithSecret, etc.).

Returns:

  • *Plugin: The configured JWT plugin instance.

func (*Plugin) Authenticate added in v0.20.0

func (p *Plugin) Authenticate() func(next http.Handler) http.Handler

Authenticate returns a standard net/http middleware handler to authenticate JWT tokens from incoming Authorization headers.

func (*Plugin) Config

func (p *Plugin) Config() Config

Config returns the active configuration settings of the JWT plugin.

func (*Plugin) GetJWKS

func (p *Plugin) GetJWKS(ctx context.Context, params GetJWKSParams) (*GetJWKSResult, error)

GetJWKS retrieves the public JSON Web Key Set (RFC 7517) containing active and grace-period keys.

Brief Explanation:

Queries the repository for all persisted keys, filters out keys expired beyond the configured GracePeriod
(unless IncludeExpired is true), parses their public JWKs, and returns the assembled JWKS structure.

Arguments:

  • ctx: Request cancellation context.
  • params: GetJWKSParams specifying whether to include fully expired keys.

Returns:

  • *GetJWKSResult: Assembled JWKS containing public keys and count.
  • error: Database retrieval error.

Example:

res, err := jwtPlugin.GetJWKS(ctx, jwt.GetJWKSParams{})
if err != nil {
	log.Fatalf("Failed to retrieve JWKS: %v", err)
}
for _, k := range res.JWKS.Keys {
	fmt.Printf("Public Key ID: %s, Alg: %s\n", k.Kid, k.Alg)
}

func (*Plugin) GetToken

func (p *Plugin) GetToken(ctx context.Context, params GetTokenParams) (*GetTokenResult, error)

GetToken generates a signed JWT representing the provided session and user entity.

Brief Explanation:

Validates session parameters, resolves the token subject via GetSubject or session.UserID,
computes custom claims via DefinePayload, delegates to Sign, and emits EventJWTIssued.

Arguments:

  • ctx: Request cancellation context.
  • params: GetTokenParams containing the active session, user, and optional expiry override.

Returns:

  • *GetTokenResult: Issued JWT string, key identifier, algorithm, and formatted response headers.
  • error: ErrSessionNotFound, ErrSessionExpired, or signing error.

Example:

res, err := jwtPlugin.GetToken(ctx, jwt.GetTokenParams{
	Session: activeSession,
	User:    activeUser,
})
if err != nil {
	log.Fatalf("Failed to generate session JWT: %v", err)
}
w.Header().Set(res.AuthJWTHeader, res.Token)

func (*Plugin) ID

func (p *Plugin) ID() string

ID returns the unique identifier for the JWT plugin ("jwt").

func (*Plugin) Init

func (p *Plugin) Init(ctx *plugin.Context) error

Init initializes the plugin within the global GoModularAuth context and ensures an active signing key exists.

func (*Plugin) RotateKeys

func (p *Plugin) RotateKeys(ctx context.Context, params RotateKeysParams) (*RotateKeysResult, error)

RotateKeys forces the generation of a fresh active key pair, storing it in the repository.

Brief Explanation:

Generates a new key pair with the specified or configured algorithm, encrypts the private key
(if encryption is enabled), persists it to the repository, updates internal active references,
and emits EventJWTRotateAfter.

Arguments:

  • ctx: Request cancellation context.
  • params: RotateKeysParams containing optional algorithm or RSA bit size overrides.

Returns:

  • *RotateKeysResult: Details of the newly created and active key pair.
  • error: Key generation, encryption, or database write error.

Example:

res, err := jwtPlugin.RotateKeys(ctx, jwt.RotateKeysParams{})
if err != nil {
	log.Fatalf("Failed to rotate keys: %v", err)
}
fmt.Println("New active Key ID:", res.NewKey.ID)

func (*Plugin) Sign

func (p *Plugin) Sign(ctx context.Context, params SignParams) (*SignResult, error)

Sign creates and cryptographically signs a compact serialized JWT (RFC 7519) with the active private key.

Brief Explanation:

Emits EventJWTSignBefore, populates standard claims ("iss", "sub", "aud", "exp", "nbf", "iat", "jti")
along with custom claims, signs the token via the active cryptographic key, and emits EventJWTSignAfter.

Arguments:

  • ctx: Request cancellation context.
  • params: SignParams containing payload, subject, issuer, audience, and expiry overrides.

Returns:

  • *SignResult: Serialized token string, key metadata, and formatted header values.
  • error: Key resolution, serialization, or signing error.

Example:

res, err := jwtPlugin.Sign(ctx, jwt.SignParams{
	Subject: "user_12345",
	Payload: map[string]any{
		"role": "admin",
		"tenant": "org_987",
	},
	ExpiresIn: 1 * time.Hour,
})
if err != nil {
	log.Fatalf("Failed to sign token: %v", err)
}
fmt.Println("JWT:", res.Token)

func (*Plugin) Verify

func (p *Plugin) Verify(ctx context.Context, params VerifyParams) (*VerifyResult, error)

Verify parses and verifies the cryptographic signature and standard claims of a JWT.

Brief Explanation:

Strips any "Bearer " scheme prefix, extracts the header to obtain the Key ID ("kid"),
retrieves the matching public key from cache or repository, verifies the signature in constant time,
validates "exp", "nbf", "iss", and "aud" against configuration, and returns the claims map.

Arguments:

  • ctx: Request cancellation context.
  • params: VerifyParams containing the token string and optional validation overrides.

Returns:

  • *VerifyResult: Contains valid status, subject, claims, and parsed timestamps.
  • error: ErrInvalidToken, ErrMissingKid, ErrKeyNotFound, ErrInvalidSignature, or ErrTokenExpired.

Example:

res, err := jwtPlugin.Verify(ctx, jwt.VerifyParams{
	Token: "eyJhbGciOiJFZERTQSI...",
})
if err != nil {
	log.Fatalf("Token validation failed: %v", err)
}
fmt.Println("Verified subject:", res.Subject)
fmt.Println("Role claim:", res.Claims["role"])

type Repository

type Repository interface {
	// GetLatestKey retrieves the most recently created signing key record.
	//
	// Function:
	//   Used during initialization and token signing to acquire the active private key.
	//
	// Storage:
	//   Both (Cache-Aside Strategy) - Cached in memory/Redis to eliminate DB lookups per token signing.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//
	// Returns:
	//   - *JWKRecord: The latest active key record.
	//   - error: ErrKeyNotFound if no keys exist, or database error.
	//
	// Example SQL:
	//   SELECT id, public_key, private_key, alg, crv, created_at, expires_at FROM jwks ORDER BY created_at DESC LIMIT 1;
	//
	// Example Cache (In-Memory/Redis):
	//   val, err := rdb.Get(ctx, "jwks:latest").Bytes()
	GetLatestKey(ctx context.Context) (*JWKRecord, error)

	// GetKeyByID retrieves a specific key-pair record by its unique Key ID ("kid").
	//
	// Function:
	//   Used during token verification to locate the public/private key matching the token's header 'kid'.
	//
	// Storage:
	//   Both (Cache-Aside Strategy) - Cached in memory/Redis by kid.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - id: Unique Key ID string ("kid").
	//
	// Returns:
	//   - *JWKRecord: The matching key record.
	//   - error: ErrKeyNotFound if not found, or database error.
	//
	// Example SQL:
	//   SELECT id, public_key, private_key, alg, crv, created_at, expires_at FROM jwks WHERE id = $1 LIMIT 1;
	//
	// Example Cache (In-Memory/Redis):
	//   val, err := rdb.Get(ctx, "jwks:kid:" + id).Bytes()
	GetKeyByID(ctx context.Context, id string) (*JWKRecord, error)

	// GetAllKeys retrieves all persisted key records.
	//
	// Function:
	//   Used to assemble the public JWKS exposed to clients and microservices.
	//
	// Storage:
	//   Database (GORM / SQL) - Relational key set persistence.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//
	// Returns:
	//   - []*JWKRecord: Slice of all key records.
	//   - error: Database error if query fails.
	//
	// Example SQL:
	//   SELECT id, public_key, private_key, alg, crv, created_at, expires_at FROM jwks ORDER BY created_at DESC;
	GetAllKeys(ctx context.Context) ([]*JWKRecord, error)

	// CreateKey stores a newly generated key-pair record.
	//
	// Function:
	//   Invoked during initial bootstrap or key rotation to persist the new key pair.
	//
	// Storage:
	//   Database (GORM / SQL) - Persistent storage for cryptographic key pairs.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - record: Key pair record containing public JWK JSON and (optionally encrypted) private key.
	//
	// Returns:
	//   - error: Database error if insert fails.
	//
	// Example SQL:
	//   INSERT INTO jwks (id, public_key, private_key, alg, crv, created_at, expires_at) VALUES ($1, $2, $3, $4, $5, $6, $7);
	CreateKey(ctx context.Context, record *JWKRecord) error

	// DeleteKey deletes a key-pair record by its Key ID.
	//
	// Function:
	//   Optional maintenance operation for purging revoked or expired keys.
	//
	// Storage:
	//   Database (GORM / SQL) - Persistent record removal.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - id: Unique Key ID string to delete.
	//
	// Returns:
	//   - error: Database error if deletion fails.
	//
	// Example SQL:
	//   DELETE FROM jwks WHERE id = $1;
	DeleteKey(ctx context.Context, id string) error
}

Repository defines the persistent storage contract required by the JWT plugin to manage key-pairs. Implement this interface on your custom database adapter (e.g. PostgreSQL, MySQL, SQLite, MongoDB, GORM).

Implementation Example (GORM / SQL):

type GormJWKRepository struct {
	db *gorm.DB
}

func (r *GormJWKRepository) GetLatestKey(ctx context.Context) (*jwt.JWKRecord, error) {
	var rec jwt.JWKRecord
	err := r.db.WithContext(ctx).Order("created_at DESC").First(&rec).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, jwt.ErrKeyNotFound
		}
		return nil, err
	}
	return &rec, nil
}

func (r *GormJWKRepository) GetKeyByID(ctx context.Context, id string) (*jwt.JWKRecord, error) {
	var rec jwt.JWKRecord
	err := r.db.WithContext(ctx).Where("id = ?", id).First(&rec).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, jwt.ErrKeyNotFound
		}
		return nil, err
	}
	return &rec, nil
}

func (r *GormJWKRepository) GetAllKeys(ctx context.Context) ([]*jwt.JWKRecord, error) {
	var records []*jwt.JWKRecord
	err := r.db.WithContext(ctx).Order("created_at DESC").Find(&records).Error
	return records, err
}

func (r *GormJWKRepository) CreateKey(ctx context.Context, record *jwt.JWKRecord) error {
	return r.db.WithContext(ctx).Create(record).Error
}

func (r *GormJWKRepository) DeleteKey(ctx context.Context, id string) error {
	return r.db.WithContext(ctx).Where("id = ?", id).Delete(&jwt.JWKRecord{}).Error
}

Storage and Caching Recommendation (In-Memory Key Caching):

Cryptographic signing keys (JWKs) change infrequently. Caching the active signing key and public key set in local application memory avoids redundant database queries on token issuance.

Recommended In-Memory Decorator Example:

type CachedJWKRepository struct {
	dbRepo jwt.Repository
	mu     sync.RWMutex
	latest *jwt.JWKRecord
	byID   map[string]*jwt.JWKRecord
}

func (r *CachedJWKRepository) GetLatestKey(ctx context.Context) (*jwt.JWKRecord, error) {
	r.mu.RLock()
	if r.latest != nil {
		defer r.mu.RUnlock()
		return r.latest, nil
	}
	r.mu.RUnlock()
	rec, err := r.dbRepo.GetLatestKey(ctx)
	if err == nil {
		r.mu.Lock()
		r.latest = rec
		r.mu.Unlock()
	}
	return rec, err
}

type RotateKeysParams

type RotateKeysParams struct {
	// Algorithm optionally specifies a different algorithm for the new key (optional).
	Algorithm Algorithm `json:"alg,omitempty"`

	// RSABits optionally specifies the RSA bit length if rotating to an RSA key (optional).
	RSABits int `json:"rsa_bits,omitempty"`

	// ExpiresIn optionally sets an expiration date for the old active key (optional).
	ExpiresIn time.Duration `json:"expires_in,omitempty"`

	plugin.ExtraContainer
}

RotateKeysParams defines parameters to trigger an immediate key rotation.

type RotateKeysResult

type RotateKeysResult struct {
	// NewKey is the persisted record of the new active key pair.
	NewKey *JWKRecord `json:"new_key"`

	// JWK is the public JWK representation of the new key.
	JWK *JWK `json:"jwk"`

	// OldKeyID is the Key ID of the rotated previous key (if one was active).
	OldKeyID string `json:"old_key_id,omitempty"`
}

RotateKeysResult contains details of the newly created and active key pair.

type SignParams

type SignParams struct {
	// Payload contains custom application claims to include in the token (optional).
	Payload map[string]any `json:"payload,omitempty"`

	// Subject sets the "sub" claim value (optional, overrides default).
	Subject string `json:"subject,omitempty"`

	// Issuer overrides the default configured "iss" claim value (optional).
	Issuer string `json:"issuer,omitempty"`

	// Audience overrides the default configured "aud" claim list (optional).
	Audience []string `json:"audience,omitempty"`

	// ExpiresIn overrides the default validity duration for this specific token (optional).
	ExpiresIn time.Duration `json:"expires_in,omitempty"`

	// NotBefore optionally sets the "nbf" claim timestamp (optional).
	NotBefore *time.Time `json:"not_before,omitempty"`

	// KeyID explicitly specifies which persisted key to use for signing (optional; uses active key if empty).
	KeyID string `json:"key_id,omitempty"`

	plugin.ExtraContainer
}

SignParams defines parameters required to construct and sign a JSON Web Token.

type SignResult

type SignResult struct {
	// Token is the serialized RFC 7519 compact JWT string.
	Token string `json:"token"`

	// KeyID is the ID of the key that signed the token.
	KeyID string `json:"key_id"`

	// Algorithm is the cryptographic signature algorithm used.
	Algorithm Algorithm `json:"alg"`

	// ExpiresAt is the calculated expiration timestamp.
	ExpiresAt time.Time `json:"expires_at"`

	// HeaderValue is the formatted Authorization header string ("Bearer <token>").
	HeaderValue string `json:"header_value"`

	// AuthJWTHeader is the standard response header name ("set-auth-jwt").
	AuthJWTHeader string `json:"auth_jwt_header"`
}

SignResult contains the signed compact JWT string and associated metadata.

type SubjectFunc

type SubjectFunc func(session *entity.Session, user *entity.User) (string, error)

SubjectFunc defines a custom callback function to resolve the "sub" (subject) claim for a session/user.

type VerifyParams

type VerifyParams struct {
	// Token is the compact JWT string or authorization header value (required).
	Token string `json:"token"`

	// Issuer optionally enforces an expected "iss" claim match during verification.
	Issuer string `json:"issuer,omitempty"`

	// Audience optionally enforces expected "aud" claim recipients.
	Audience []string `json:"audience,omitempty"`

	// Leeway overrides the clock skew tolerance window for exp/nbf validation (optional).
	Leeway time.Duration `json:"leeway,omitempty"`

	plugin.ExtraContainer
}

VerifyParams defines parameters required to verify an incoming JWT string.

type VerifyResult

type VerifyResult struct {
	// Valid indicates whether the signature and standard claims are valid.
	Valid bool `json:"valid"`

	// Subject is the "sub" claim extracted from the payload.
	Subject string `json:"subject,omitempty"`

	// Claims contains all claims present in the token payload.
	Claims map[string]any `json:"claims"`

	// KeyID is the "kid" identifier of the key used to verify the signature.
	KeyID string `json:"key_id"`

	// Algorithm is the cryptographic algorithm specified in the JWS header.
	Algorithm Algorithm `json:"alg"`

	// ExpiresAt is the expiration time parsed from the "exp" claim (if present).
	ExpiresAt *time.Time `json:"expires_at,omitempty"`

	// IssuedAt is the timestamp parsed from the "iat" claim (if present).
	IssuedAt *time.Time `json:"issued_at,omitempty"`

	// NotBefore is the timestamp parsed from the "nbf" claim (if present).
	NotBefore *time.Time `json:"not_before,omitempty"`
}

VerifyResult contains the outcome of a successful JWT verification.

Jump to

Keyboard shortcuts

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