mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2025-10-27 20:25:41 +00:00
147 lines
4.3 KiB
Go
147 lines
4.3 KiB
Go
package auth_test
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
"tinyauth/internal/auth"
|
|
"tinyauth/internal/types"
|
|
)
|
|
|
|
var config = types.AuthConfig{
|
|
Users: types.Users{},
|
|
OauthWhitelist: "",
|
|
SessionExpiry: 3600,
|
|
}
|
|
|
|
func TestLoginRateLimiting(t *testing.T) {
|
|
// Initialize a new auth service with 3 max retries and 5 seconds timeout
|
|
config.LoginMaxRetries = 3
|
|
config.LoginTimeout = 5
|
|
authService := auth.NewAuth(config, nil, nil)
|
|
|
|
// Test identifier
|
|
identifier := "test_user"
|
|
|
|
// Test successful login - should not lock account
|
|
t.Log("Testing successful login")
|
|
|
|
authService.RecordLoginAttempt(identifier, true)
|
|
locked, _ := authService.IsAccountLocked(identifier)
|
|
|
|
if locked {
|
|
t.Fatalf("Account should not be locked after successful login")
|
|
}
|
|
|
|
// Test 2 failed attempts - should not lock account yet
|
|
t.Log("Testing 2 failed login attempts")
|
|
|
|
authService.RecordLoginAttempt(identifier, false)
|
|
authService.RecordLoginAttempt(identifier, false)
|
|
locked, _ = authService.IsAccountLocked(identifier)
|
|
|
|
if locked {
|
|
t.Fatalf("Account should not be locked after only 2 failed attempts")
|
|
}
|
|
|
|
// Add one more failed attempt (total 3) - should lock account with maxRetries=3
|
|
t.Log("Testing 3 failed login attempts")
|
|
authService.RecordLoginAttempt(identifier, false)
|
|
locked, remainingTime := authService.IsAccountLocked(identifier)
|
|
|
|
if !locked {
|
|
t.Fatalf("Account should be locked after reaching max retries")
|
|
}
|
|
if remainingTime <= 0 || remainingTime > 5 {
|
|
t.Fatalf("Expected remaining time between 1-5 seconds, got %d", remainingTime)
|
|
}
|
|
|
|
// Test reset after waiting for timeout - use 1 second timeout for fast testing
|
|
t.Log("Testing unlocking after timeout")
|
|
|
|
// Reinitialize auth service with a shorter timeout for testing
|
|
config.LoginTimeout = 1
|
|
config.LoginMaxRetries = 3
|
|
authService = auth.NewAuth(config, nil, nil)
|
|
|
|
// Add enough failed attempts to lock the account
|
|
for i := 0; i < 3; i++ {
|
|
authService.RecordLoginAttempt(identifier, false)
|
|
}
|
|
|
|
// Verify it's locked
|
|
locked, _ = authService.IsAccountLocked(identifier)
|
|
if !locked {
|
|
t.Fatalf("Account should be locked initially")
|
|
}
|
|
|
|
// Wait a bit and verify it gets unlocked after timeout
|
|
time.Sleep(1500 * time.Millisecond) // Wait longer than the timeout
|
|
locked, _ = authService.IsAccountLocked(identifier)
|
|
|
|
if locked {
|
|
t.Fatalf("Account should be unlocked after timeout period")
|
|
}
|
|
|
|
// Test disabled rate limiting
|
|
t.Log("Testing disabled rate limiting")
|
|
config.LoginMaxRetries = 0
|
|
config.LoginTimeout = 0
|
|
authService = auth.NewAuth(config, nil, nil)
|
|
|
|
for i := 0; i < 10; i++ {
|
|
authService.RecordLoginAttempt(identifier, false)
|
|
}
|
|
|
|
locked, _ = authService.IsAccountLocked(identifier)
|
|
if locked {
|
|
t.Fatalf("Account should not be locked when rate limiting is disabled")
|
|
}
|
|
}
|
|
|
|
func TestConcurrentLoginAttempts(t *testing.T) {
|
|
// Initialize a new auth service with 2 max retries and 5 seconds timeout
|
|
config.LoginMaxRetries = 2
|
|
config.LoginTimeout = 5
|
|
authService := auth.NewAuth(config, nil, nil)
|
|
|
|
// Test multiple identifiers
|
|
identifiers := []string{"user1", "user2", "user3"}
|
|
|
|
// Test that locking one identifier doesn't affect others
|
|
t.Log("Testing multiple identifiers")
|
|
|
|
// Add enough failed attempts to lock first user (2 attempts with maxRetries=2)
|
|
authService.RecordLoginAttempt(identifiers[0], false)
|
|
authService.RecordLoginAttempt(identifiers[0], false)
|
|
|
|
// Check if first user is locked
|
|
locked, _ := authService.IsAccountLocked(identifiers[0])
|
|
if !locked {
|
|
t.Fatalf("User1 should be locked after reaching max retries")
|
|
}
|
|
|
|
// Check that other users are not affected
|
|
for i := 1; i < len(identifiers); i++ {
|
|
locked, _ := authService.IsAccountLocked(identifiers[i])
|
|
if locked {
|
|
t.Fatalf("User%d should not be locked", i+1)
|
|
}
|
|
}
|
|
|
|
// Test successful login after failed attempts (but before lock)
|
|
t.Log("Testing successful login after failed attempts but before lock")
|
|
|
|
// One failed attempt for user2
|
|
authService.RecordLoginAttempt(identifiers[1], false)
|
|
|
|
// Successful login should reset the counter
|
|
authService.RecordLoginAttempt(identifiers[1], true)
|
|
|
|
// Now try a failed login again - should not be locked as counter was reset
|
|
authService.RecordLoginAttempt(identifiers[1], false)
|
|
locked, _ = authService.IsAccountLocked(identifiers[1])
|
|
if locked {
|
|
t.Fatalf("User2 should not be locked after successful login reset")
|
|
}
|
|
}
|