Documentation
¶
Index ¶
- Constants
- Variables
- func DecryptPrivateKey(encryptedPayloadB64 string, secret string) ([]byte, error)
- func EncryptPrivateKey(rawKeyBytes []byte, secret string) (string, error)
- func JWKCacheKey(kid string) string
- func ParsePrivateKeyFromBytes(derBytes []byte) (crypto.PrivateKey, error)
- func ParsePublicKeyFromJWK(jwk *JWK) (crypto.PublicKey, error)
- func SignJWT(header JWTHeader, payload map[string]any, privKey crypto.PrivateKey, ...) (string, error)
- type Algorithm
- type Config
- type GetJWKSParams
- type GetJWKSResult
- type GetTokenParams
- type GetTokenResult
- type JWK
- type JWKRecord
- type JWKS
- type JWTHeader
- type JWTIssuedEventPayload
- type JWTRotateAfterEventPayload
- type JWTRotateBeforeEventPayload
- type JWTSignAfterEventPayload
- type JWTSignBeforeEventPayload
- type JWTVerifyAfterEventPayload
- type JWTVerifyBeforeEventPayload
- type Option
- func WithAlgorithm(alg Algorithm) Option
- func WithAudience(audience ...string) Option
- func WithClockSkewLeeway(leeway time.Duration) Option
- func WithDefinePayload(fn PayloadFunc) Option
- func WithDisablePrivateKeyEncryption(disable bool) Option
- func WithExpiration(duration time.Duration) Option
- func WithGetSubject(fn SubjectFunc) Option
- func WithGracePeriod(grace time.Duration) Option
- func WithIssuer(issuer string) Option
- func WithRSABits(bits int) Option
- func WithRotationInterval(interval time.Duration) Option
- func WithSecret(secret string) Option
- type PayloadFunc
- type Plugin
- func (p *Plugin) Authenticate() func(next http.Handler) http.Handler
- func (p *Plugin) Config() Config
- func (p *Plugin) GetJWKS(ctx context.Context, params GetJWKSParams) (*GetJWKSResult, error)
- func (p *Plugin) GetToken(ctx context.Context, params GetTokenParams) (*GetTokenResult, error)
- func (p *Plugin) ID() string
- func (p *Plugin) Init(ctx *plugin.Context) error
- func (p *Plugin) RotateKeys(ctx context.Context, params RotateKeysParams) (*RotateKeysResult, error)
- func (p *Plugin) Sign(ctx context.Context, params SignParams) (*SignResult, error)
- func (p *Plugin) Verify(ctx context.Context, params VerifyParams) (*VerifyResult, error)
- type Repository
- type RotateKeysParams
- type RotateKeysResult
- type SignParams
- type SignResult
- type SubjectFunc
- type VerifyParams
- type VerifyResult
Constants ¶
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" )
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).
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.
const ( ClaimsContextKey contextKey = "jwt_claims" SubjectContextKey contextKey = "jwt_subject" TokenContextKey contextKey = "jwt_token" )
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.
const PluginID = "jwt"
PluginID is the unique string identifier for the JWT plugin ("jwt").
Variables ¶
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 ¶
DecryptPrivateKey decrypts base64url-encoded AES-256-GCM ciphertext using the configured secret.
func EncryptPrivateKey ¶
EncryptPrivateKey encrypts raw private key bytes using AES-256-GCM authenticated encryption.
func JWKCacheKey ¶
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 ¶
ParsePublicKeyFromJWK extracts a crypto.PublicKey from an RFC 7517 JWK.
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 ¶
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 ¶
JWTHeader represents the JWS header structure conforming to RFC 7515 / RFC 7519.
func ExtractUnverifiedHeader ¶
ExtractUnverifiedHeader extracts the JWT header without signature verification to inspect kid/alg.
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 ¶
WithAlgorithm sets the asymmetric cryptographic algorithm used for signing tokens.
func WithAudience ¶
WithAudience sets the recipient audience values ("aud" claim) for issued JWT tokens.
func WithClockSkewLeeway ¶
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 ¶
WithDisablePrivateKeyEncryption disables AES-256-GCM encryption of private keys in storage.
func WithExpiration ¶
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 ¶
WithGracePeriod configures how long rotated/expired keys are preserved in JWKS for validation.
func WithIssuer ¶
WithIssuer sets the issuer identifier ("iss" claim) included in issued JWT tokens.
func WithRSABits ¶
WithRSABits sets the RSA key size in bits (minimum 2048).
func WithRotationInterval ¶
WithRotationInterval configures automatic key rotation interval.
func WithSecret ¶
WithSecret sets the symmetric secret key used for AES-256-GCM private key encryption in repository.
type PayloadFunc ¶
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
Authenticate returns a standard net/http middleware handler to authenticate JWT tokens from incoming Authorization headers.
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) Init ¶
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 ¶
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.