package auth import ( "strings" "time" "git.gocasts.ir/ebhomengo/niki/entity" "github.com/golang-jwt/jwt/v4" ) type Config struct { SignKey string `koanf:"sign_key"` AccessExpirationTime time.Duration `koanf:"access_expiration_time"` RefreshExpirationTime time.Duration `koanf:"refresh_expiration_time"` AccessSubject string `koanf:"access_subject"` RefreshSubject string `koanf:"refresh_subject"` } type Service struct { Config Config } func New(cfg Config) Service { return Service{ Config: cfg, } } func (s Service) CreateAccessToken(user entity.Authenticable) (string, error) { return s.createToken(user.ID, user.Role, s.Config.AccessSubject, s.Config.AccessExpirationTime) } func (s Service) CreateRefreshToken(user entity.Authenticable) (string, error) { return s.createToken(user.ID, user.Role, s.Config.RefreshSubject, s.Config.RefreshExpirationTime) } func (s Service) ParseToken(bearerToken string) (*Claims, error) { // https://pkg.go.dev/github.com/golang-jwt/jwt/v5#example-ParseWithClaims-CustomClaimsType tokenStr := strings.Replace(bearerToken, "Bearer ", "", 1) token, err := jwt.ParseWithClaims(tokenStr, &Claims{}, func(token *jwt.Token) (interface{}, error) { return []byte(s.Config.SignKey), nil }) if err != nil { return nil, err } if claims, ok := token.Claims.(*Claims); ok && token.Valid { return claims, nil } return nil, err } func (s Service) createToken(userID uint, role, subject string, expireDuration time.Duration) (string, error) { // create a signer for rsa 256 // TODO - replace with rsa 256 RS256 - https://github.com/golang-jwt/jwt/blob/main/http_example_test.go // set our claims claims := Claims{ RegisteredClaims: jwt.RegisteredClaims{ Subject: subject, ExpiresAt: jwt.NewNumericDate(time.Now().Add(expireDuration)), }, UserID: userID, Role: role, } // TODO - add sign method to config accessToken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) tokenString, err := accessToken.SignedString([]byte(s.Config.SignKey)) if err != nil { return "", err } return tokenString, nil }