package auth import ( "crypto/rsa" "errors" "time" "github.com/arpinfidel/p2p-llm/db" "github.com/golang-jwt/jwt" "golang.org/x/crypto/bcrypt" ) type AuthService struct { keys *rsa.PrivateKey authRepo db.APIKeyRepository } func NewAuthService(privateKey *rsa.PrivateKey, authRepo db.APIKeyRepository) *AuthService { return &AuthService{ keys: privateKey, authRepo: authRepo, } } func (s *AuthService) HashAPIKey(apiKey string) (string, error) { hash, err := bcrypt.GenerateFromPassword([]byte(apiKey), bcrypt.DefaultCost) if err != nil { return "", err } return string(hash), nil } func (s *AuthService) VerifyAPIKey(apiKey, hash string) bool { err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(apiKey)) return err == nil } func (s *AuthService) GenerateJWT() (string, error) { token := jwt.New(jwt.SigningMethodRS256) claims := token.Claims.(jwt.MapClaims) claims["exp"] = time.Now().Add(time.Hour * 24).Unix() // Token expires in 24 hours claims["iat"] = time.Now().Unix() tokenString, err := token.SignedString(s.keys) if err != nil { return "", err } return tokenString, nil } func (s *AuthService) Authenticate(apiKey string) (string, error) { hash, err := s.authRepo.GetActiveKeyHash() if err != nil { return "", err } if !s.VerifyAPIKey(apiKey, hash) { return "", ErrInvalidAPIKey } return s.GenerateJWT() } var ( ErrInvalidAPIKey = errors.New("invalid API key") )