created: jwt provider
This commit is contained in:
parent
7e5010ac78
commit
bc2038ef34
3 changed files with 139 additions and 0 deletions
|
|
@ -3,6 +3,7 @@ package config
|
||||||
type Config struct {
|
type Config struct {
|
||||||
AppConf AppConfig
|
AppConf AppConfig
|
||||||
DBConf DatabaseConfig
|
DBConf DatabaseConfig
|
||||||
|
JWTConf JWTConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
type AppConfig struct {
|
type AppConfig struct {
|
||||||
|
|
@ -23,6 +24,13 @@ type DatabaseConfig struct {
|
||||||
LogLevel string
|
LogLevel string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type JWTConfig struct {
|
||||||
|
Secret string
|
||||||
|
Issuer string
|
||||||
|
AccessExpire string
|
||||||
|
RefreshExpire string
|
||||||
|
}
|
||||||
|
|
||||||
func NewConfig() *Config {
|
func NewConfig() *Config {
|
||||||
return &Config{
|
return &Config{
|
||||||
AppConf: AppConfig{
|
AppConf: AppConfig{
|
||||||
|
|
@ -42,5 +50,12 @@ func NewConfig() *Config {
|
||||||
DBName: getEnv("DB_NAME", ""),
|
DBName: getEnv("DB_NAME", ""),
|
||||||
LogLevel: getEnv("DB_LOGLEVEL", ""),
|
LogLevel: getEnv("DB_LOGLEVEL", ""),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
JWTConf: JWTConfig{
|
||||||
|
Secret: getEnv("JWT_SECRET", ""),
|
||||||
|
Issuer: getEnv("JWT_ISSUER", ""),
|
||||||
|
AccessExpire: getEnv("JWT_ACCESS_EXPIRE", ""),
|
||||||
|
RefreshExpire: getEnv("JWT_REFRESH_EXPIRE", ""),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
7
internal/interfaces/jwtProvider.go
Normal file
7
internal/interfaces/jwtProvider.go
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
package interfaces
|
||||||
|
|
||||||
|
type JWTProvider interface {
|
||||||
|
CreateAccessToken(userUuid string) (string, error)
|
||||||
|
CreateRefreshToken(userUuid, tokenUuid string) (string, int64, error)
|
||||||
|
Parse(token string) (string, string, error)
|
||||||
|
}
|
||||||
117
internal/provider/token/service.go
Normal file
117
internal/provider/token/service.go
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
package token
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/golang-jwt/jwt/v5"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type JWT struct {
|
||||||
|
SecretKey string
|
||||||
|
Issuer string
|
||||||
|
AccessExpire time.Duration
|
||||||
|
RefreshExpire time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
type Deps struct {
|
||||||
|
SecretKey string
|
||||||
|
Issuer string
|
||||||
|
AccessExpire string
|
||||||
|
RefreshExpire string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewJWT(deps Deps) *JWT {
|
||||||
|
return &JWT{
|
||||||
|
SecretKey: deps.SecretKey,
|
||||||
|
Issuer: deps.Issuer,
|
||||||
|
AccessExpire: duration(deps.AccessExpire),
|
||||||
|
RefreshExpire: duration(deps.RefreshExpire),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *JWT) CreateAccessToken(userUuid string) (string, error) {
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
|
||||||
|
"exp": now.Add(j.AccessExpire).Unix(),
|
||||||
|
"iat": now.Unix(),
|
||||||
|
"iss": j.Issuer,
|
||||||
|
"nbf": now.Unix(),
|
||||||
|
"sub": userUuid,
|
||||||
|
})
|
||||||
|
|
||||||
|
signedToken, err := token.SignedString([]byte(j.SecretKey))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return signedToken, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *JWT) CreateRefreshToken(userUuid, tokenUuid string) (string, int64, error) {
|
||||||
|
now := time.Now()
|
||||||
|
exp := now.Add(j.RefreshExpire).Unix()
|
||||||
|
|
||||||
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
|
||||||
|
"exp": exp,
|
||||||
|
"iat": now.Unix(),
|
||||||
|
"iss": j.Issuer,
|
||||||
|
"nbf": now.Unix(),
|
||||||
|
"sub": userUuid,
|
||||||
|
"tkn": tokenUuid,
|
||||||
|
})
|
||||||
|
|
||||||
|
signedToken, err := token.SignedString([]byte(j.SecretKey))
|
||||||
|
if err != nil {
|
||||||
|
return "", 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return signedToken, exp, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *JWT) Parse(token string) (string, string, error) {
|
||||||
|
if strings.HasPrefix(token, "Bearer ") {
|
||||||
|
token = strings.TrimPrefix(token, "Bearer ")
|
||||||
|
}
|
||||||
|
|
||||||
|
parse, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
|
||||||
|
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||||
|
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
|
||||||
|
}
|
||||||
|
return []byte(j.SecretKey), nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if claims, ok := parse.Claims.(jwt.MapClaims); ok && parse.Valid {
|
||||||
|
userUuid := claims["sub"].(string)
|
||||||
|
|
||||||
|
var refreshUuid string
|
||||||
|
if tkn, exists := claims["tkn"]; exists {
|
||||||
|
if tknStr, okay := tkn.(string); okay {
|
||||||
|
refreshUuid = tknStr
|
||||||
|
} else {
|
||||||
|
return "", "", fmt.Errorf("invalid type for 'tkn' claim")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return userUuid, refreshUuid, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", "", fmt.Errorf("invalid token")
|
||||||
|
}
|
||||||
|
|
||||||
|
func duration(minutes string) time.Duration {
|
||||||
|
dur, err := strconv.Atoi(minutes)
|
||||||
|
if err != nil {
|
||||||
|
return time.Duration(10) * time.Minute
|
||||||
|
}
|
||||||
|
|
||||||
|
return time.Duration(dur) * time.Minute
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue