Simplified the database layer by removing custom interface wrappers and using standard library *sql.DB and *sql.Tx types directly. Changes: - Removed DBConnection and DBTransaction interfaces from database.go - Removed NewDBConnection() wrapper function - Updated TokenGenerator to use *sql.DB instead of DBConnection - Updated all validation and revocation methods to accept *sql.Tx - Updated TableManager to work with *sql.DB directly - Updated all tests to use db.Begin() instead of custom wrappers - Fixed GeneratorConfig.DB field (was DBConn) - Updated documentation in doc.go with correct API usage Benefits: - Simpler API with fewer abstractions - Works directly with database/sql standard library - Compatible with GORM (via gormDB.DB()) and Bun (share same *sql.DB) - Easier to understand and maintain - No unnecessary wrapper layers Breaking changes: - GeneratorConfig.DBConn renamed to GeneratorConfig.DB - Removed NewDBConnection() function - pass *sql.DB directly - ValidateAccess/ValidateRefresh now accept *sql.Tx instead of DBTransaction - Token.Revoke/CheckNotRevoked now accept *sql.Tx instead of DBTransaction 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
136 lines
4.4 KiB
Go
136 lines
4.4 KiB
Go
// Package jwt provides JWT (JSON Web Token) generation and validation with token revocation support.
|
|
//
|
|
// This package implements JWT access and refresh tokens with the ability to revoke tokens
|
|
// using a database-backed blacklist. It supports multiple database backends including
|
|
// PostgreSQL, MySQL, SQLite, and MariaDB, and works with both standard library database/sql
|
|
// and popular ORMs like GORM and Bun.
|
|
//
|
|
// # Features
|
|
//
|
|
// - Access and refresh token generation
|
|
// - Token validation with expiration checking
|
|
// - Token revocation via database blacklist
|
|
// - Support for multiple database types (PostgreSQL, MySQL, SQLite, MariaDB)
|
|
// - Compatible with database/sql, GORM, and Bun ORMs
|
|
// - Automatic table creation and management
|
|
// - Database-native automatic cleanup (PostgreSQL functions, MySQL events)
|
|
// - Manual cleanup method for on-demand token cleanup
|
|
// - Token freshness tracking for sensitive operations
|
|
// - "Remember me" functionality with session vs persistent tokens
|
|
//
|
|
// # Basic Usage
|
|
//
|
|
// Create a token generator with database support:
|
|
//
|
|
// db, _ := sql.Open("postgres", "connection_string")
|
|
// gen, err := jwt.CreateGenerator(jwt.GeneratorConfig{
|
|
// AccessExpireAfter: 15, // 15 minutes
|
|
// RefreshExpireAfter: 1440, // 24 hours
|
|
// FreshExpireAfter: 5, // 5 minutes
|
|
// TrustedHost: "example.com",
|
|
// SecretKey: "your-secret-key",
|
|
// DB: db,
|
|
// DBType: jwt.DatabaseType{Type: jwt.DatabasePostgreSQL, Version: "15"},
|
|
// TableConfig: jwt.DefaultTableConfig(),
|
|
// })
|
|
//
|
|
// Generate tokens:
|
|
//
|
|
// accessToken, accessExp, err := gen.NewAccess(userID, true, false)
|
|
// refreshToken, refreshExp, err := gen.NewRefresh(userID, false)
|
|
//
|
|
// Validate tokens:
|
|
//
|
|
// tx, _ := db.Begin()
|
|
// token, err := gen.ValidateAccess(tx, accessToken)
|
|
// if err != nil {
|
|
// // Token is invalid or revoked
|
|
// }
|
|
// tx.Commit()
|
|
//
|
|
// Revoke tokens:
|
|
//
|
|
// tx, _ := db.Begin()
|
|
// err := token.Revoke(tx)
|
|
// tx.Commit()
|
|
//
|
|
// # Database Configuration
|
|
//
|
|
// The package automatically creates a blacklist table with the following schema:
|
|
//
|
|
// CREATE TABLE jwtblacklist (
|
|
// jti UUID PRIMARY KEY, -- Token unique identifier
|
|
// exp BIGINT NOT NULL, -- Expiration timestamp
|
|
// sub INT NOT NULL, -- Subject (user) ID
|
|
// created_at TIMESTAMP -- When token was blacklisted
|
|
// );
|
|
//
|
|
// # Cleanup
|
|
//
|
|
// For PostgreSQL, the package creates a cleanup function that can be called manually
|
|
// or scheduled with pg_cron:
|
|
//
|
|
// SELECT cleanup_jwtblacklist();
|
|
//
|
|
// For MySQL/MariaDB, the package creates a database event that runs automatically
|
|
// (requires event_scheduler to be enabled).
|
|
//
|
|
// Manual cleanup can be performed at any time:
|
|
//
|
|
// err := gen.Cleanup(context.Background())
|
|
//
|
|
// # Using with ORMs
|
|
//
|
|
// The package works with popular ORMs by using raw SQL queries. For GORM and Bun,
|
|
// wrap the underlying *sql.DB with NewDBConnection() when creating the generator:
|
|
//
|
|
// // GORM example
|
|
// gormDB, _ := gorm.Open(postgres.Open(dsn), &gorm.Config{})
|
|
// sqlDB, _ := gormDB.DB()
|
|
// gen, _ := jwt.CreateGenerator(jwt.GeneratorConfig{
|
|
// // ... config ...
|
|
// DB: sqlDB,
|
|
// })
|
|
//
|
|
// // Bun example
|
|
// sqlDB, _ := sql.Open("postgres", dsn)
|
|
// bunDB := bun.NewDB(sqlDB, pgdialect.New())
|
|
// gen, _ := jwt.CreateGenerator(jwt.GeneratorConfig{
|
|
// // ... config ...
|
|
// DB: sqlDB,
|
|
// })
|
|
//
|
|
// # Token Freshness
|
|
//
|
|
// Tokens can be marked as "fresh" for sensitive operations. Fresh tokens are typically
|
|
// required for actions like changing passwords or email addresses:
|
|
//
|
|
// token, err := gen.ValidateAccess(exec, tokenString)
|
|
// if time.Now().Unix() > token.Fresh {
|
|
// // Token is not fresh, require re-authentication
|
|
// }
|
|
//
|
|
// # Custom Table Names
|
|
//
|
|
// You can customize the blacklist table name:
|
|
//
|
|
// config := jwt.DefaultTableConfig()
|
|
// config.TableName = "my_token_blacklist"
|
|
//
|
|
// # Disabling Database Features
|
|
//
|
|
// To use JWT without revocation support (no database):
|
|
//
|
|
// gen, err := jwt.CreateGenerator(jwt.GeneratorConfig{
|
|
// AccessExpireAfter: 15,
|
|
// RefreshExpireAfter: 1440,
|
|
// FreshExpireAfter: 5,
|
|
// TrustedHost: "example.com",
|
|
// SecretKey: "your-secret-key",
|
|
// DB: nil, // No database
|
|
// })
|
|
//
|
|
// When DB is nil, revocation features are disabled and token validation
|
|
// will not check the blacklist.
|
|
package jwt
|