jwt

package
v1.5.0 Latest Latest
Warning

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

Go to latest
Published: Mar 30, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package jwt defines the domain models and types used by the jwt plugin.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AccessToken

type AccessToken struct {
	// AccessToken is the JWT access token (use for API requests)
	AccessToken string `json:"access_token"`

	// AccessExpiry is when the access token expires (UTC)
	AccessExpiry time.Time `json:"access_expiry"`

	// TokenType is the auth scheme name returned to clients.
	// Aegis returns the constant "Bearer".
	TokenType string `json:"token_type"`
}

AccessToken represents a single access token response.

This is returned by the /getAccessToken endpoint when only an access token is needed (without a refresh token).

Example response:

{
  "access_token": "eyJhbGc...",
  "access_expiry": "2024-01-01T12:15:00Z"
}

type Claims

type Claims struct {
	// UserID is the authenticated user's ID
	// Used for quick user lookup without database query
	UserID string `json:"user_id"`

	// TokenType indicates if this is an "access" or "refresh" token
	// Access tokens can be used for API requests
	// Refresh tokens can only be used to get new access tokens
	TokenType string `json:"token_type"`
}

Claims defines the structure of JWT token claims.

JWT claims are the payload embedded in the token. These are NOT encrypted, only signed - anyone can decode and read them. Don't include sensitive data.

Standard claims (JWT spec):

  • iss: Issuer (from Config.Issuer)
  • sub: Subject (UserID)
  • exp: Expiration time
  • iat: Issued at time
  • jti: JWT ID (for revocation tracking)

Custom claims (Aegis):

  • user_id: User ID for quick lookup
  • token_type: "access" or "refresh"

Example token payload:

{
  "iss": "aegis",
  "sub": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
  "exp": 1704114900,
  "iat": 1704114000,
  "user_id": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
  "token_type": "access"
}

type JWK

type JWK struct {
	// Kid is the Key ID (unique identifier for this key)
	// Used in JWT header to identify which key was used for signing
	// Format: timestamp-based or UUID
	Kid string `json:"kid"`

	// KeyData is the JSON-encoded JWK (includes public/private key material)
	// Stored as BYTEA/BLOB in database
	// For RSA: Contains n (modulus), e (exponent), d (private exponent)
	KeyData []byte `json:"keyData"`

	// Algorithm is the cryptographic algorithm (e.g., "RS256", "ES256")
	// Currently only RS256 (RSA with SHA-256) is supported
	Algorithm string `json:"algorithm"`

	// Use indicates the key purpose:
	//   - "sig": Signature/verification (most common)
	//   - "enc": Encryption/decryption (future feature)
	Use string `json:"use"`

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

	// ExpiresAt is when the key should be deleted from storage
	// Set to CreatedAt + KeyRetention duration
	// nil means the key never expires (not recommended)
	ExpiresAt *time.Time `json:"expiresAt,omitempty"`
}

JWK represents a JSON Web Key stored in the database.

JWKs are cryptographic keys used for signing and verifying JWT tokens. They are stored in the database to support:

  • Key rotation: Generate new keys periodically
  • Key retention: Keep old keys for verifying existing tokens
  • Multi-server: Share keys across multiple application instances

Key Lifecycle:

  1. Generate: Create RSA key pair (private + public)
  2. Store: Save to database with expiry time
  3. Use: Sign tokens with private key, verify with public key
  4. Rotate: Generate new key, keep old key for verification
  5. Expire: Delete keys after retention period

Database Schema:

CREATE TABLE jwk_keys (
  kid VARCHAR(255) PRIMARY KEY,
  key_data BYTEA NOT NULL,
  algorithm VARCHAR(50) NOT NULL,
  use VARCHAR(50) NOT NULL,
  created_at TIMESTAMP NOT NULL,
  expires_at TIMESTAMP
);

type JWKS

type JWKS struct {
	// Keys is the array of public keys
	Keys []map[string]any `json:"keys"`
}

JWKS represents a JSON Web Key Set response.

This is returned by the /.well-known/jwks.json endpoint and contains the public keys used to verify JWT signatures.

Example response:

{
  "keys": [
    {
      "kty": "RSA",
      "use": "sig",
      "kid": "access-1234567890",
      "n": "...",
      "e": "AQAB"
    }
  ]
}

type LogoutResponse

type LogoutResponse struct {
	UserID string `json:"user_id"`
}

LogoutResponse is the data payload returned by POST /logout.

type Provider

type Provider interface {
	// GenerateTokenPair creates an access token + refresh token for a user.
	// Returns token strings and expiry times.
	GenerateTokenPair(userID string) (*TokenPair, error)

	// ValidateToken validates a JWT token and returns the claims.
	// Checks signature, expiry, issuer, and token type.
	ValidateToken(token string) (*Claims, error)

	// RefreshTokens validates a refresh token and generates a new token pair.
	// Old refresh token is invalidated (single-use refresh tokens).
	RefreshTokens(refreshToken string) (*TokenPair, error)

	// BlacklistToken adds a token to the blacklist (for logout/revocation).
	// Requires Redis for distributed blacklist.
	BlacklistToken(token string) error
}

Provider defines an interface for custom JWT token generation and validation.

Implement this interface to customize JWT token handling:

  • Custom claims structure
  • Custom signing algorithms
  • Custom token validation logic
  • Integration with external JWT services

The default implementation (Plugin) uses RSA signing with database-backed keys. Most applications don't need a custom provider.

type Store

type Store interface {
	// GetCurrentJWK retrieves the most recent active key for signing.
	//
	// This is used during token generation to get the private key for signing.
	// Returns the newest non-expired key matching the algorithm and use.
	//
	// Parameters:
	//   - ctx: Context for cancellation and timeouts
	//   - algorithm: Key algorithm (e.g., "RS256")
	//   - use: Key use ("sig" for signing, "enc" for encryption)
	//
	// Returns:
	//   - jwk.Key: The most recent active key
	//   - error: Database errors or "key not found"
	//
	// Example:
	//
	//	privateKey, err := store.GetCurrentJWK(ctx, "RS256", "sig")
	//	if err != nil {
	//		// No active key - generate new one
	//	}
	GetCurrentJWK(ctx context.Context, algorithm, use string) (jwk.Key, error)

	// StoreJWK persists a JWK to the database with expiry.
	//
	// This is used during:
	//   - Initial key generation (plugin initialization)
	//   - Key rotation (periodic background job)
	//
	// The key is stored with an expiry time for automatic cleanup.
	// Expired keys are kept to verify old tokens until cleanup.
	//
	// Parameters:
	//   - ctx: Context for cancellation and timeouts
	//   - key: JWK to store (includes private/public key material)
	//   - algorithm: Key algorithm (e.g., "RS256")
	//   - use: Key use ("sig" or "enc")
	//   - expiresAt: When to delete this key (nil = never expires)
	//
	// Returns:
	//   - error: Database errors or duplicate key ID
	//
	// Example:
	//
	//	expiresAt := time.Now().Add(30 * 24 * time.Hour)
	//	err := store.StoreJWK(ctx, privateKey, "RS256", "sig", &expiresAt)
	StoreJWK(ctx context.Context, key jwk.Key, algorithm, use string, expiresAt *time.Time) error

	// DeleteExpiredJWKS removes all expired keys from storage.
	//
	// This is called periodically to clean up old keys that are no longer needed.
	// Only deletes keys where:
	//   - expires_at IS NOT NULL (keys with expiry set)
	//   - expires_at < NOW() (expiry time has passed)
	//
	// Note: Keys are kept past their "active" period to verify old tokens.
	// The expiry should be set to created_at + KeyRetention duration.
	//
	// Parameters:
	//   - ctx: Context for cancellation and timeouts
	//
	// Returns:
	//   - error: Database errors
	//
	// Example:
	//
	//	if err := store.DeleteExpiredJWKS(ctx); err != nil {
	//		log.Printf("Failed to cleanup expired keys: %v", err)
	//	}
	DeleteExpiredJWKS(ctx context.Context) error

	// ListJWKS returns all active (non-expired) keys.
	//
	// This is used by:
	//   - JWKS endpoint: Expose public keys for token verification
	//   - Token validation: Find key by kid (key ID) for signature verification
	//
	// Only returns keys where:
	//   - expires_at IS NULL (never expires), OR
	//   - expires_at > NOW() (not yet expired)
	//
	// Parameters:
	//   - ctx: Context for cancellation and timeouts
	//
	// Returns:
	//   - []JWK: List of active keys (includes both public and private keys)
	//   - error: Database errors
	//
	// Example:
	//
	//	keys, err := store.ListJWKS(ctx)
	//	for _, key := range keys {
	//		fmt.Printf("Key: %s, Algorithm: %s\n", key.Kid, key.Algorithm)
	//	}
	ListJWKS(ctx context.Context) ([]JWK, error)
}

Store defines the interface for JWT token and key storage operations.

This interface abstracts database operations for JWK (JSON Web Key) storage, allowing different storage backends:

  • SQL databases: PostgreSQL, MySQL, SQLite (default)
  • NoSQL databases: MongoDB, DynamoDB (custom implementation)
  • Cloud key vaults: AWS KMS, Google Cloud KMS (custom implementation)

The default implementation (DefaultStore) uses SQL with sqlc-generated queries.

Key Storage Requirements:

  • Persistence: Keys must survive application restarts
  • Multi-server: Keys must be shared across application instances
  • Key rotation: Support storing multiple active keys
  • Key expiry: Automatic cleanup of expired keys

Thread Safety:

Implementations must be thread-safe for concurrent access from:

  • Token generation requests (read current key)
  • Key rotation background job (write new keys)
  • Token validation requests (read all active keys)
  • JWKS endpoint requests (list public keys)

type TokenPair

type TokenPair struct {
	// AccessToken is the JWT access token (use for API requests)
	AccessToken string `json:"access_token"`

	// AccessExpiry is when the access token expires (UTC)
	AccessExpiry time.Time `json:"access_expiry"`

	// RefreshToken is the JWT refresh token (use to get new access token)
	RefreshToken string `json:"refresh_token"`

	// RefreshExpiry is when the refresh token expires (UTC)
	RefreshExpiry time.Time `json:"refresh_expiry"`
}

TokenPair represents a complete set of access and refresh tokens.

This is returned by token generation and refresh endpoints. Clients should:

  • Store access token for API requests (short-lived)
  • Store refresh token securely for obtaining new access tokens (long-lived)
  • Use refresh token before access token expires

Example response:

{
  "access_token": "eyJhbGc...",
  "access_expiry": "2024-01-01T12:15:00Z",
  "refresh_token": "eyJhbGc...",
  "refresh_expiry": "2024-01-08T12:00:00Z"
}

Jump to

Keyboard shortcuts

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