Token Blacklist
The blacklist is used to invalidate tokens before they expire, suitable for user logout, password changes, permission changes, etc.
How It Works
text
Revoke(token) → Extract jti + exp → Write to BlacklistStore
Validate(token) → Verify signature → Check blacklist → Return resultBuilt-in Memory Storage
Memory storage is used by default and works out of the box:
go
cfg := jwt.DefaultConfig()
cfg.SecretKey = "hmac-key-that-has-at-least-32-bytes!"
// Blacklist is automatically enabled with DefaultBlacklistConfig()Configuration
go
cfg.Blacklist.CleanupInterval = 5 * time.Minute // Cleanup interval
cfg.Blacklist.MaxSize = 100000 // Max entries
cfg.Blacklist.EnableAutoCleanup = true // Auto cleanup| Field | Default | Description |
|---|---|---|
CleanupInterval | 5m | Expired entry cleanup interval |
MaxSize | 100000 | Max entries |
EnableAutoCleanup | true | Auto cleanup (forced to true) |
Auto Cleanup
Built-in storage forces EnableAutoCleanup to true, preventing unbounded memory growth.
Revoking Tokens
go
// Revoke
err := processor.Revoke(accessToken)
if err != nil {
panic(err)
}
// Check
revoked, err := processor.IsRevoked(accessToken)
fmt.Println("Revoked:", revoked) // true
// Revoked tokens will fail validation
_, _, err = processor.Validate(accessToken)
// err → jwt.ErrTokenRevokedCustom Storage Backend
Implement the BlacklistStore interface to connect external storage (Redis, databases, etc.):
go
type BlacklistStore interface {
Add(tokenID string, expiresAt time.Time) error
Contains(tokenID string) (bool, error)
Close() error
}Redis Example
go
type RedisStore struct {
client *redis.Client
}
func (s *RedisStore) Add(tokenID string, expiresAt time.Time) error {
ttl := time.Until(expiresAt)
if ttl <= 0 {
return nil // Already expired, no need to store
}
return s.client.Set(ctx, "blacklist:"+tokenID, "1", ttl).Err()
}
func (s *RedisStore) Contains(tokenID string) (bool, error) {
n, err := s.client.Exists(ctx, "blacklist:"+tokenID).Result()
return n > 0, err
}
func (s *RedisStore) Close() error {
return s.client.Close()
}Use custom storage:
go
cfg.Blacklist.Store = &RedisStore{client: rdb}TTL Optimization
Use time.Until(expiresAt) as Redis TTL — tokens are automatically removed from the blacklist after expiration without additional cleanup.
Production Recommendations
Important
- Built-in memory storage is not shared across processes; use external storage for multi-instance deployments
- When
MaxSizeis reached, newly revoked tokens evict the oldest entries - Custom storage implementations should handle network timeouts and retries
Next Steps
- API Reference → BlacklistStore — Interface definition
- API Reference → BlacklistConfig — Configuration fields
- API Reference → Revoke — Revoke method
- Advanced Examples — Redis blacklist example