chore: update session and challenge repo -- using Redis for caching session and challenge verifying -- added api handler docs
This commit is contained in:
@@ -17,14 +17,15 @@ import (
|
||||
|
||||
type AuthService interface {
|
||||
GenerateChallenge(ctx context.Context, pubKey string) (*domain.Challenge, error)
|
||||
Authenticate(ctx context.Context, pubKey string, signature string, challenge *domain.Challenge, chainID uint, ipAddress, userAgent string) (*UserToken, error)
|
||||
Authenticate(ctx context.Context, pubKey string, signature string, chainID uint, ipAddress, userAgent string) (*UserToken, error)
|
||||
}
|
||||
|
||||
type authService struct {
|
||||
userRepo domain.UserRepo
|
||||
sessionRepo domain.SessionRepo
|
||||
challengeExp uint
|
||||
cfg config.JWT
|
||||
userRepo domain.UserRepo
|
||||
sessionRepo domain.SessionRepo
|
||||
challengeRepo domain.ChallengeRepo
|
||||
challengeExp uint
|
||||
cfg config.JWT
|
||||
}
|
||||
|
||||
type UserToken struct {
|
||||
@@ -36,14 +37,16 @@ type UserToken struct {
|
||||
func NewAuthService(
|
||||
userRepo domain.UserRepo,
|
||||
sessionRepo domain.SessionRepo,
|
||||
challengeRepo domain.ChallengeRepo,
|
||||
challengeExp uint,
|
||||
cfg config.JWT,
|
||||
) AuthService {
|
||||
return &authService{
|
||||
userRepo: userRepo,
|
||||
sessionRepo: sessionRepo,
|
||||
challengeExp: challengeExp,
|
||||
cfg: cfg,
|
||||
userRepo: userRepo,
|
||||
sessionRepo: sessionRepo,
|
||||
challengeRepo: challengeRepo,
|
||||
challengeExp: challengeExp,
|
||||
cfg: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,19 +57,32 @@ func (s *authService) GenerateChallenge(ctx context.Context, pubKey string) (*do
|
||||
}
|
||||
|
||||
challenge := &domain.Challenge{
|
||||
Message: uuid.New(),
|
||||
Message: uuid.New().String(),
|
||||
TimeStamp: time.Now().UTC(),
|
||||
ExpiresAt: time.Now().Add(time.Duration(s.challengeExp) * time.Minute),
|
||||
}
|
||||
|
||||
// Save challenge to Redis
|
||||
err = s.challengeRepo.Create(ctx, pubKey, challenge)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to save challenge: %w", err)
|
||||
}
|
||||
|
||||
return challenge, nil
|
||||
}
|
||||
|
||||
func (s *authService) Authenticate(ctx context.Context, pubKey string, signature string, challenge *domain.Challenge, chainID uint, ipAddress, userAgent string) (*UserToken, error) {
|
||||
func (s *authService) Authenticate(ctx context.Context, pubKey string, signature string, chainID uint, ipAddress, userAgent string) (*UserToken, error) {
|
||||
_, err := common.IsValidPublicKey(pubKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid public key: %w", err)
|
||||
}
|
||||
|
||||
// Retrieve challenge from Redis
|
||||
challenge, err := s.challengeRepo.GetByPubKey(ctx, pubKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to retrieve challenge: %w", err)
|
||||
}
|
||||
|
||||
isValid, err := challenge.Verify(pubKey, signature)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("signature verification failed: %w", err)
|
||||
@@ -75,6 +91,13 @@ func (s *authService) Authenticate(ctx context.Context, pubKey string, signature
|
||||
if !isValid {
|
||||
return nil, errors.New("invalid signature")
|
||||
}
|
||||
|
||||
// Delete the challenge after successful verification to prevent replay attacks
|
||||
err = s.challengeRepo.Delete(ctx, pubKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to delete challenge: %w", err)
|
||||
}
|
||||
|
||||
user, err := s.userRepo.GetByPubKey(ctx, pubKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
Reference in New Issue
Block a user