2024-10-13 13:31:58 +04:00

77 lines
1.7 KiB
Go

package jwt
import (
"errors"
"time"
"github.com/aykhans/oh-my-chat/internal/core/domain"
"github.com/golang-jwt/jwt/v5"
"github.com/google/uuid"
)
type JWTService struct {
key string
duration time.Duration
}
type tokenPayload struct {
UserID uuid.UUID `json:"user_id,omitempty"`
jwt.RegisteredClaims
}
func NewJWTService(duration time.Duration, key string) *JWTService {
return &JWTService{
key: key,
duration: duration,
}
}
func (jwtService *JWTService) CreateToken(
user *domain.User,
) (string, error) {
token := jwt.NewWithClaims(
jwt.SigningMethodHS256,
&tokenPayload{
UserID: user.ID,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(
time.Now().Add(jwtService.duration),
),
Audience: jwt.ClaimStrings{"user"},
IssuedAt: jwt.NewNumericDate(time.Now()),
},
},
)
tokenStr, err := token.SignedString([]byte(jwtService.key))
if err != nil {
return "", domain.ErrTokenCreation
}
return tokenStr, nil
}
func (jwtService *JWTService) VerifyToken(
token string,
) (*domain.AuthPayload, error) {
keyFunc := func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, domain.ErrInvalidToken
}
return []byte(jwtService.key), nil
}
parsedToken, err := jwt.ParseWithClaims(token, &tokenPayload{}, keyFunc)
if err != nil {
if errors.Is(err, jwt.ErrTokenExpired) {
return nil, domain.ErrExpiredToken
}
if errors.Is(err, jwt.ErrSignatureInvalid) {
return nil, domain.ErrInvalidToken
}
return nil, domain.ErrInternal
}
payload := parsedToken.Claims.(*tokenPayload)
return &domain.AuthPayload{UserID: payload.UserID}, nil
}