Skip to content

Commit 0fc55cd

Browse files
authored
Improve Garbage Collector (#162)
* Implement [TOTP] Cleanup Configuration - [+] feat(otpverifier): add cleanup interval constants and configuration - [+] Introduce cleanup interval constants (FastCleanup, MediumCleanup, SlowCleanup) to represent different cleanup frequencies for removing expired tokens in the TOTP verifier. - [+] Add a CleanupIntervals map to associate cleanup interval constants with their corresponding percentage of the TOTP period. - [+] Include the CleanupInterval field in the Config struct to allow configuring the cleanup interval when creating a new TOTPVerifier. - [+] Modify the startPeriodicCleanup method to use the configured cleanup interval percentage to determine the cleanup period. - [+] test(otpverifier): update TestTOTPVerifier_PeriodicCleanup test case - [+] Set the CleanupInterval to FastCleanup in the test configuration. - [+] Adjust the sleep duration to match the FastCleanup interval (100% of the token validity period) to ensure the cleanup process has occurred before verifying the token. * Docs [pkg.go.dev] Update Documentation - [+] docs(otpverifier): document CleanupIntervals options for TOTP verifier cleanup process - [+] refactor(otpverifier): update default cleanup interval comment to use consistent formatting
1 parent 5acecf7 commit 0fc55cd

File tree

4 files changed

+57
-11
lines changed

4 files changed

+57
-11
lines changed

internal/otpverifier/docs.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@
116116
// - [BLAKE3256]
117117
// - [BLAKE3384]
118118
// - [BLAKE3512]
119+
// - [CleanupIntervals]: The interval at which the cleanup process runs to remove expired tokens in the TOTP verifier. Available options are:
120+
// - [FastCleanup]
121+
// - [MediumCleanup]
122+
// - [SlowCleanup]
119123
//
120124
// # QR Code Configuration
121125
//

internal/otpverifier/otpverifier.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,39 @@ var SyncWindowRanges = map[int][]int{
160160
LowStrict: {5, 10},
161161
}
162162

163+
const (
164+
// FastCleanup represents the fastest cleanup interval for removing expired tokens in the TOTP verifier.
165+
// It is assigned a value of iota + 1, which evaluates to 1.
166+
// When FastCleanup is selected, the cleanup process runs every 25% of the TOTP period, providing the most frequent cleanup.
167+
FastCleanup = iota + 1
168+
169+
// MediumCleanup represents a medium cleanup interval for removing expired tokens in the TOTP verifier.
170+
// It is assigned the next sequential value of iota, which evaluates to 2.
171+
// When MediumCleanup is selected, the cleanup process runs every 50% of the TOTP period, providing a balanced cleanup frequency.
172+
MediumCleanup
173+
174+
// SlowCleanup represents the slowest cleanup interval for removing expired tokens in the TOTP verifier.
175+
// It is assigned the next sequential value of iota, which evaluates to 3.
176+
// When SlowCleanup is selected, the cleanup process runs every 75% of the TOTP period, providing the least frequent cleanup.
177+
SlowCleanup
178+
)
179+
180+
// CleanupIntervals is a map that associates cleanup interval constants with their corresponding percentage of the TOTP period.
181+
// The cleanup interval determines how frequently the cleanup process runs to remove expired tokens.
182+
//
183+
// The available cleanup intervals are:
184+
// - [FastCleanup]: The cleanup process runs every 25% of the TOTP period.
185+
// - [MediumCleanup]: The cleanup process runs every 50% of the TOTP period.
186+
// - [SlowCleanup]: The cleanup process runs every 75% of the TOTP period.
187+
//
188+
// Note: Choosing an appropriate cleanup interval is important to balance the need for timely removal of expired tokens
189+
// and the overhead of running the cleanup process too frequently. The default cleanup interval is [MediumCleanup].
190+
var CleanupIntervals = map[int]float64{
191+
FastCleanup: 0.25, // 25% of the TOTP period
192+
MediumCleanup: 0.50, // 50% of the TOTP period
193+
SlowCleanup: 0.75, // 75% of the TOTP period
194+
}
195+
163196
// TimeSource is a function type that returns the current time.
164197
type TimeSource func() time.Time
165198

@@ -189,6 +222,7 @@ type Config struct {
189222
CustomURITemplateParams map[string]string
190223
Hash string
191224
Crypto Crypto
225+
CleanupInterval int
192226
}
193227

194228
// QRCodeConfig represents the configuration for generating QR codes.

internal/otpverifier/otpverifier_test.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -181,11 +181,12 @@ func TestTOTPVerifier_PeriodicCleanup(t *testing.T) {
181181
secret := gotp.RandomSecret(16)
182182
period := 10 // Set the token validity period to 10 seconds
183183
config := otpverifier.Config{
184-
Secret: secret,
185-
Period: period,
186-
Digits: 6,
187-
Hash: otpverifier.SHA256,
188-
TimeSource: time.Now,
184+
Secret: secret,
185+
Period: period,
186+
Digits: 6,
187+
Hash: otpverifier.SHA256,
188+
TimeSource: otpverifier.DefaultConfig.TOTPTime,
189+
CleanupInterval: otpverifier.FastCleanup,
189190
}
190191

191192
verifier := otpverifier.NewTOTPVerifier(config)
@@ -195,7 +196,7 @@ func TestTOTPVerifier_PeriodicCleanup(t *testing.T) {
195196
verifier.Verify(token1)
196197

197198
// Wait Assistant garbage collector for periodic cleanup to occur (less than the token validity period)
198-
time.Sleep(time.Duration(period*3/4) * time.Second)
199+
time.Sleep(time.Duration(period*4/4) * time.Second)
199200

200201
// Simulate used tokens
201202
token2 := verifier.GenerateToken()

internal/otpverifier/totp.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ import (
1717

1818
// TOTPVerifier is a TOTP verifier that implements the OTPVerifier interface.
1919
type TOTPVerifier struct {
20-
config Config
21-
totp *gotp.TOTP
22-
UsedTokens *sync.Map
20+
config Config
21+
totp *gotp.TOTP
22+
UsedTokens *sync.Map
23+
CleanupInterval int
2324
}
2425

2526
// NewTOTPVerifier creates a new TOTPVerifier with the given configuration.
@@ -68,7 +69,8 @@ func NewTOTPVerifier(config ...Config) *TOTPVerifier {
6869
totp: totp,
6970
// Allocates 11 to 15 allocs/op without signature (depends on the hash function), which is relatively inexpensive for this TOTP synchronization window.
7071
// Without implementing a synchronization window similar to HOTP, it can lead to high vulnerability.
71-
UsedTokens: &sync.Map{},
72+
UsedTokens: &sync.Map{},
73+
CleanupInterval: c.CleanupInterval,
7274
}
7375

7476
// Start the periodic cleanup goroutine
@@ -209,7 +211,12 @@ func (v *TOTPVerifier) GenerateOTPURL(issuer, accountName string) string {
209211

210212
// startPeriodicCleanup starts a goroutine that periodically cleans up expired tokens.
211213
func (v *TOTPVerifier) startPeriodicCleanup() {
212-
cleanupPeriod := time.Duration(v.config.Period/2) * time.Second
214+
cleanupPeriodPercentage, ok := CleanupIntervals[v.CleanupInterval]
215+
if !ok {
216+
cleanupPeriodPercentage = CleanupIntervals[MediumCleanup] // Default to medium if invalid value is provided
217+
}
218+
219+
cleanupPeriod := time.Duration(float64(v.config.Period)*cleanupPeriodPercentage) * time.Second
213220
cleanupTicker := time.NewTicker(cleanupPeriod)
214221
defer cleanupTicker.Stop()
215222

0 commit comments

Comments
 (0)