Files
auth-service/internal/service/auth.go

143 lines
3.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package service
import (
"authorization/internal"
"authorization/internal/config"
"crypto/sha1"
"errors"
"fmt"
"time"
"github.com/golang-jwt/jwt"
)
const (
refresh = "refresh"
access = "access"
)
type tokenClaims struct {
jwt.StandardClaims
UserId int `json:"user_id"`
UserRole string `json:"user_role"`
TokenType string `json:"token_type"`
}
type AuthService struct {
userService UserService
tokenConfigs config.TokenConfig
}
func newAuthService(userService UserService) *AuthService {
return &AuthService{userService: userService}
}
func (s *AuthService) CreateUser(user internal.User) (int, error) {
user.Password = s.generatePasswordHash(user.Password)
return s.userService.CreateUser(user)
}
func (s *AuthService) GenerateToken(username string, password string) (string, string, error) {
user, err := s.userService.GetUser(username, s.generatePasswordHash(password))
if err != nil {
return "", "", err
}
accessTokenClaims := s.generateClaims(user.Id, user.UserRole, access)
refreshTokenClaims := s.generateClaims(user.Id, user.UserRole, refresh)
accessToken, err := accessTokenClaims.SignedString([]byte(s.tokenConfigs.AccessToken.GetSecretBytes()))
if err != nil {
return "", "", err
}
refreshToken, err := refreshTokenClaims.SignedString([]byte(s.tokenConfigs.RefreshToken.GetSecretBytes()))
if err != nil {
return "", "", err
}
return accessToken, refreshToken, nil
}
func (s *AuthService) ChangeUserRole(username string, userrole string) (string, error) {
user, err := s.userService.ChangeUserRole(username, userrole)
if err != nil {
return "", err
}
return user, nil
}
func (s *AuthService) generateClaims(userId int, userRole string, tokenType string) *jwt.Token {
tokenTTL := s.tokenConfigs.RefreshToken.GetTTL()
if tokenType == access {
tokenTTL = s.tokenConfigs.AccessToken.GetTTL()
}
return jwt.NewWithClaims(jwt.SigningMethodHS256, &tokenClaims{
jwt.StandardClaims{
ExpiresAt: time.Now().Add(tokenTTL).Unix(),
IssuedAt: time.Now().Unix(),
},
userId,
userRole,
tokenType,
})
}
func (s *AuthService) generatePasswordHash(password string) string {
hash := sha1.New()
hash.Write([]byte(password))
return fmt.Sprintf("%x", hash)
}
func (s *AuthService) ParseToken(accessToken string) (string, error) {
claims, err := s.parseTokenWithSecret(accessToken, s.tokenConfigs.AccessToken.GetSecretBytes())
if err != nil {
return "", err
}
return claims.UserRole, nil
}
func (s *AuthService) RefreshToken(refreshToken string) (string, string, error) {
// Парсим refresh token
claims, err := s.parseTokenWithSecret(refreshToken, s.tokenConfigs.RefreshToken.GetSecretBytes())
if err != nil {
return "", "", errors.New("invalid refresh token")
}
// Проверяем, что это именно refresh token
if claims.TokenType != refresh {
return "", "", errors.New("token is not a refresh token")
}
// Генерируем новую пару токенов
newAccessTokenClaims := s.generateClaims(claims.UserId, claims.UserRole, access)
newRefreshTokenClaims := s.generateClaims(claims.UserId, claims.UserRole, refresh)
newAccessToken, err := newAccessTokenClaims.SignedString([]byte(s.tokenConfigs.AccessToken.GetSecretBytes()))
if err != nil {
return "", "", err
}
newRefreshToken, err := newRefreshTokenClaims.SignedString([]byte(s.tokenConfigs.RefreshToken.GetSecretBytes()))
if err != nil {
return "", "", err
}
return newAccessToken, newRefreshToken, nil
}
// parseTokenWithSecret - общий метод для парсинга токена с заданным секретным ключом
func (s *AuthService) parseTokenWithSecret(tokenString string, secret []byte) (*tokenClaims, error) {
token, err := jwt.ParseWithClaims(tokenString, &tokenClaims{}, func(t *jwt.Token) (interface{}, error) {
return secret, nil
})
if err != nil {
return nil, err
}
claims, ok := token.Claims.(*tokenClaims)
if !ok {
return nil, errors.New("invalid token claims")
}
return claims, nil
}