memory_ts.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package auth
  2. import (
  3. "context"
  4. "sync"
  5. "time"
  6. )
  7. // MemoryTokenStore implements TokenStore with in-memory storage
  8. type MemoryTokenStore struct {
  9. blacklist map[string]time.Time
  10. mutex sync.RWMutex
  11. // Optional cleaner to remove expired tokens
  12. cleanupInterval time.Duration
  13. stopCleanup chan struct{}
  14. }
  15. // NewMemoryTokenStore creates a new in-memory token store
  16. func NewMemoryTokenStore(cleanupInterval time.Duration) *MemoryTokenStore {
  17. store := &MemoryTokenStore{
  18. blacklist: make(map[string]time.Time),
  19. mutex: sync.RWMutex{},
  20. cleanupInterval: cleanupInterval,
  21. stopCleanup: make(chan struct{}),
  22. }
  23. // Start background cleanup if interval > 0
  24. if cleanupInterval > 0 {
  25. go store.startCleanupRoutine()
  26. }
  27. return store
  28. }
  29. // IsBlacklisted checks if a token is in the blacklist
  30. func (s *MemoryTokenStore) IsBlacklisted(ctx context.Context, token string) (bool, error) {
  31. s.mutex.RLock()
  32. defer s.mutex.RUnlock()
  33. expiry, exists := s.blacklist[token]
  34. if !exists {
  35. return false, nil
  36. }
  37. // If token has expired, we can remove it
  38. if time.Now().After(expiry) {
  39. // Don't remove here to avoid write lock during read operation
  40. return false, nil
  41. }
  42. return true, nil
  43. }
  44. // Blacklist adds a token to the blacklist
  45. func (s *MemoryTokenStore) Blacklist(ctx context.Context, token string, expiry time.Time) error {
  46. s.mutex.Lock()
  47. defer s.mutex.Unlock()
  48. s.blacklist[token] = expiry
  49. return nil
  50. }
  51. // startCleanupRoutine periodically removes expired tokens
  52. func (s *MemoryTokenStore) startCleanupRoutine() {
  53. ticker := time.NewTicker(s.cleanupInterval)
  54. defer ticker.Stop()
  55. for {
  56. select {
  57. case <-ticker.C:
  58. s.cleanup()
  59. case <-s.stopCleanup:
  60. return
  61. }
  62. }
  63. }
  64. // cleanup removes expired tokens from the blacklist
  65. func (s *MemoryTokenStore) cleanup() {
  66. now := time.Now()
  67. s.mutex.Lock()
  68. defer s.mutex.Unlock()
  69. for token, expiry := range s.blacklist {
  70. if now.After(expiry) {
  71. delete(s.blacklist, token)
  72. }
  73. }
  74. }
  75. // Close stops the cleanup goroutine
  76. func (s *MemoryTokenStore) Close() {
  77. if s.cleanupInterval > 0 {
  78. s.stopCleanup <- struct{}{}
  79. }
  80. }