package auth import ( "context" "crypto/rand" "encoding/hex" "fmt" "time" "github.com/golang-jwt/jwt/v5" ) // MockAuthService provides mock authentication functionality type MockAuthService struct { secretKey []byte issuer string } // Claims represents JWT claims for mock authentication type Claims struct { UserID string `json:"user_id"` Username string `json:"username"` Email string `json:"email"` Roles []string `json:"roles"` jwt.RegisteredClaims } // NewMockAuthService creates a new mock authentication service func NewMockAuthService(issuer string) (*MockAuthService, error) { // Generate a random secret key for development secretKey := make([]byte, 32) if _, err := rand.Read(secretKey); err != nil { return nil, fmt.Errorf("failed to generate secret key: %w", err) } return &MockAuthService{ secretKey: secretKey, issuer: issuer, }, nil } // GenerateToken generates a JWT token for a user func (m *MockAuthService) GenerateToken(userID, username, email string, roles []string) (string, error) { now := time.Now() claims := Claims{ UserID: userID, Username: username, Email: email, Roles: roles, RegisteredClaims: jwt.RegisteredClaims{ Issuer: m.issuer, Subject: userID, Audience: []string{"knowfoolery"}, ExpiresAt: jwt.NewNumericDate(now.Add(time.Hour * 24)), // 24 hours NotBefore: jwt.NewNumericDate(now), IssuedAt: jwt.NewNumericDate(now), }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString(m.secretKey) } // ValidateToken validates a JWT token func (m *MockAuthService) ValidateToken(ctx context.Context, tokenString string) (*Claims, error) { token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) { // Validate signing method if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) } return m.secretKey, nil }) if err != nil { return nil, fmt.Errorf("failed to parse token: %w", err) } if !token.Valid { return nil, fmt.Errorf("invalid token") } claims, ok := token.Claims.(*Claims) if !ok { return nil, fmt.Errorf("invalid token claims") } return claims, nil } // CreateMockUsers creates some mock users for testing func (m *MockAuthService) CreateMockUsers() map[string]string { tokens := make(map[string]string) // Create admin user token adminToken, _ := m.GenerateToken("admin-1", "admin", "admin@knowfoolery.com", []string{"admin", "player"}) tokens["admin"] = adminToken // Create regular player token playerToken, _ := m.GenerateToken("player-1", "john_doe", "john@example.com", []string{"player"}) tokens["player"] = playerToken // Create another player token player2Token, _ := m.GenerateToken("player-2", "jane_smith", "jane@example.com", []string{"player"}) tokens["player2"] = player2Token return tokens } // GetSecretHex returns the secret key as hex string (for debugging/testing only) func (m *MockAuthService) GetSecretHex() string { return hex.EncodeToString(m.secretKey) }