package service import ( "fmt" "github.com/golang-jwt/jwt/v5" "golang.org/x/crypto/bcrypt" "net/http" "strconv" "strings" "time" "git.urec56.ru/urec/chat_back_go/config" "git.urec56.ru/urec/chat_back_go/internal/domain" "git.urec56.ru/urec/chat_back_go/internal/logger" ) const maxBcryptPasswordLen = 72 type authService struct { cfg config.JWT parser Parser l *logger.Logger } func newAuthService(cfg config.JWT, l *logger.Logger) *authService { return &authService{cfg: cfg, parser: jwt.NewParser(), l: l} } func (s *authService) keyFunc(*jwt.Token) (interface{}, error) { return s.cfg.SecretKey, nil } func (s *authService) ExtractAuthToken(r *http.Request) (string, error) { token := r.Header.Get("Authorization") tokenData := strings.Split(token, " ") if len(tokenData) != 2 || strings.ToLower(tokenData[0]) != "bearer" { return "", domain.TokenError } return tokenData[1], nil } func (s *authService) DecodeAuthToken(token string) (int, error) { val, err := s.parser.Parse(token, s.keyFunc) if err != nil { return 0, domain.TokenError } sub, err := val.Claims.GetSubject() if err != nil { return 0, domain.TokenError } userID, err := strconv.Atoi(sub) if err != nil { return 0, domain.TokenError } return userID, nil } func (s *authService) EncodeAuthToken(userID int) (string, error) { claims := jwt.MapClaims{ "sub": fmt.Sprintf("%d", userID), "iat": time.Now().Unix(), "exp": time.Now().Add(time.Hour * 24 * 30).Unix(), // срок действия 30 дней } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) tokenString, err := token.SignedString(s.cfg.SecretKey) if err != nil { s.l.Errorf("singing jwt: %v", err) return "", domain.InternalServerError } return tokenString, nil } func (s *authService) HashPassword(p string) (string, error) { hash, err := bcrypt.GenerateFromPassword([]byte(p)[:maxBcryptPasswordLen], bcrypt.DefaultCost) if err != nil { s.l.Errorf("error during password hashing: %s", err) return "", domain.HashingError } return string(hash), nil } func (s *authService) VerifyHashedPassword(p, hp string) bool { if err := bcrypt.CompareHashAndPassword([]byte(hp), []byte(p)); err != nil { return false } return true }