otp.go 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. package user
  2. import (
  3. "bytes"
  4. "crypto/sha1"
  5. "encoding/hex"
  6. "fmt"
  7. "github.com/0xJacky/Nginx-UI/internal/cache"
  8. "github.com/0xJacky/Nginx-UI/internal/crypto"
  9. "github.com/0xJacky/Nginx-UI/model"
  10. "github.com/google/uuid"
  11. "github.com/pkg/errors"
  12. "github.com/pquerna/otp/totp"
  13. "time"
  14. )
  15. var (
  16. ErrOTPCode = errors.New("invalid otp code")
  17. ErrRecoveryCode = errors.New("invalid recovery code")
  18. )
  19. func VerifyOTP(user *model.Auth, otp, recoveryCode string) (err error) {
  20. if otp != "" {
  21. decrypted, err := crypto.AesDecrypt(user.OTPSecret)
  22. if err != nil {
  23. return err
  24. }
  25. if ok := totp.Validate(otp, string(decrypted)); !ok {
  26. return ErrOTPCode
  27. }
  28. } else {
  29. recoverCode, err := hex.DecodeString(recoveryCode)
  30. if err != nil {
  31. return err
  32. }
  33. k := sha1.Sum(user.OTPSecret)
  34. if !bytes.Equal(k[:], recoverCode) {
  35. return ErrRecoveryCode
  36. }
  37. }
  38. return
  39. }
  40. func secureSessionIDCacheKey(sessionId string) string {
  41. return fmt.Sprintf("otp_secure_session:_%s", sessionId)
  42. }
  43. func SetSecureSessionID(userId int) (sessionId string) {
  44. sessionId = uuid.NewString()
  45. cache.Set(secureSessionIDCacheKey(sessionId), userId, 5*time.Minute)
  46. return
  47. }
  48. func VerifySecureSessionID(sessionId string, userId int) bool {
  49. if v, ok := cache.Get(secureSessionIDCacheKey(sessionId)); ok {
  50. if v.(int) == userId {
  51. return true
  52. }
  53. }
  54. return false
  55. }