chat_back_go/internal/service/auth.go

95 lines
2.2 KiB
Go

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
}