package auth import ( "testing" ) func TestHashAndCheckPassword(t *testing.T) { hash, err := HashPassword("my-password-123") if err != nil { t.Fatalf("HashPassword failed: %v", err) } if hash == "my-password-123" { t.Fatal("hash equals plaintext") } // Correct password if err := CheckPassword(hash, "my-password-123"); err != nil { t.Fatalf("CheckPassword rejected correct password: %v", err) } // Wrong password if err := CheckPassword(hash, "wrong-password"); err == nil { t.Fatal("CheckPassword accepted wrong password") } } func TestGenerateAndValidateToken(t *testing.T) { key := [32]byte{} copy(key[:], "test-jwt-secret-32-bytes-needed!") la := NewLocalAuth(key) claims := Claims{UserID: "u1", Username: "admin", Role: "admin"} token, err := la.GenerateToken(claims) if err != nil { t.Fatalf("GenerateToken failed: %v", err) } if token.Token == "" { t.Fatal("generated empty token") } // Validate the token got, err := la.ValidateToken(token.Token) if err != nil { t.Fatalf("ValidateToken failed: %v", err) } if got.UserID != "u1" || got.Username != "admin" || got.Role != "admin" { t.Fatalf("claims mismatch: %+v", got) } } func TestValidateInvalidToken(t *testing.T) { key := [32]byte{} copy(key[:], "test-jwt-secret-32-bytes-needed!") la := NewLocalAuth(key) _, err := la.ValidateToken("invalid-token-string") if err == nil { t.Fatal("ValidateToken should reject invalid token") } } func TestValidateTokenFromDifferentKey(t *testing.T) { key1 := [32]byte{} copy(key1[:], "first-jwt-secret-32-bytes-needed") la1 := NewLocalAuth(key1) key2 := [32]byte{} copy(key2[:], "other-jwt-secret-32-bytes-needed") la2 := NewLocalAuth(key2) claims := Claims{UserID: "u1", Username: "admin", Role: "admin"} token, err := la1.GenerateToken(claims) if err != nil { t.Fatalf("GenerateToken failed: %v", err) } // Token signed with key1 should not validate with key2 _, err = la2.ValidateToken(token.Token) if err == nil { t.Fatal("ValidateToken should reject token signed with different key") } } func TestHashPasswordDifferentOutputs(t *testing.T) { hash1, err := HashPassword("same-password") if err != nil { t.Fatalf("HashPassword 1 failed: %v", err) } hash2, err := HashPassword("same-password") if err != nil { t.Fatalf("HashPassword 2 failed: %v", err) } if hash1 == hash2 { t.Fatal("bcrypt should produce different hashes for same input (random salt)") } // Both should still verify if err := CheckPassword(hash1, "same-password"); err != nil { t.Fatal("hash1 should verify") } if err := CheckPassword(hash2, "same-password"); err != nil { t.Fatal("hash2 should verify") } } func TestTokenContainsClaims(t *testing.T) { key := [32]byte{} copy(key[:], "test-jwt-secret-32-bytes-needed!") la := NewLocalAuth(key) claims := Claims{UserID: "user-42", Username: "testuser", Role: "viewer"} token, err := la.GenerateToken(claims) if err != nil { t.Fatalf("GenerateToken failed: %v", err) } got, err := la.ValidateToken(token.Token) if err != nil { t.Fatalf("ValidateToken failed: %v", err) } if got.UserID != "user-42" { t.Fatalf("UserID mismatch: got %q, want %q", got.UserID, "user-42") } if got.Username != "testuser" { t.Fatalf("Username mismatch: got %q, want %q", got.Username, "testuser") } if got.Role != "viewer" { t.Fatalf("Role mismatch: got %q, want %q", got.Role, "viewer") } }