You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
3.1 KiB
Go

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)
}