Added JWT Refresh token

This commit is contained in:
PB
2025-10-20 20:59:00 +02:00
parent 50b2127bd7
commit b58b07f0ac
4 changed files with 53 additions and 23 deletions

View File

@@ -12,5 +12,8 @@ API_CACHE_PASSWORD=12345678
API_MONGODB_URL=mongodb://mongodb:12345678@mongo-db:27017
# EVENTBUS_URL=amqp://guest:guest@api-eventbus:5672
JWT_SECRET_KEY=SomeFancySecretAndRandomString
JWT_TOKEN_EXPIRE_TIME=1 # hours
JWT_ACCESS_TOKEN_SECRET_KEY=SomeFancySecretAndRandomString
JWT_ACCESS_TOKEN_EXPIRE_TIME=1 # hours
JWT_REFRESH_TOKEN_SECRET_KEY=SomeFancySecretAndRandomStringAgain
JWT_REFRESH_TOKEN_EXPIRE_TIME=7 # days

View File

@@ -1,8 +1,7 @@
package server
import (
"os"
baseCnf "git.ego.freeddns.org/egommerce/go-api-pkg/config"
"github.com/gofiber/fiber/v2"
jwt "github.com/gofiber/jwt/v2"
)
@@ -12,7 +11,7 @@ import (
func JWTProtected() func(*fiber.Ctx) error {
// Create config for JWT authentication middleware.
config := jwt.Config{
SigningKey: []byte(os.Getenv("JWT_SECRET_KEY")),
SigningKey: []byte(baseCnf.GetEnv("JWT_ACCESS_TOKEN_SECRET_KEY", "FallbackAccessTokenSecret")),
ContextKey: "jwt", // used in private routes
ErrorHandler: jwtError,
}

View File

@@ -46,12 +46,13 @@ func (a *Auth) Login(login, passwd string) (string, error) {
return "", ErrLoginIncorrect
}
token, _ := jwtSrv.CreateToken(id)
if err = a.saveTokenToCache(token, id); err != nil {
accessToken, _ := jwtSrv.CreateAccessToken(id)
refreshToken, _ := jwtSrv.CreateRefreshToken(id)
if err = a.saveTokensToCache(accessToken, refreshToken, id); err != nil {
return "", ErrUnableToCacheToken
}
return token, nil
return accessToken, nil
}
func (a *Auth) Register(email, login, passwd string) (string, error) {
@@ -70,10 +71,15 @@ func (a *Auth) Register(email, login, passwd string) (string, error) {
return id, nil
}
func (a *Auth) saveTokenToCache(token, id string) error {
res := a.cache.Set(context.Background(), "auth:token:"+id, token, tokenExpireTime)
func (a *Auth) saveTokensToCache(accessToken, refreshToken, id string) error {
res := a.cache.Set(context.Background(), "auth:access_token:"+id, accessToken, accessTokenExpireTime)
if err := res.Err(); err != nil {
fmt.Println("failed to save token in redis: ", err.Error())
fmt.Println("failed to save access token in redis: ", err.Error())
}
res = a.cache.Set(context.Background(), "auth:refresh_token:"+id, refreshToken, refreshTokenExpireTime)
if err := res.Err(); err != nil {
fmt.Println("failed to save refresh token in redis: ", err.Error())
}
return nil

View File

@@ -10,33 +10,55 @@ import (
)
var (
tokenExpireTime time.Duration
accessTokenExpireTime time.Duration
refreshTokenExpireTime time.Duration
)
func init() {
min, _ := strconv.Atoi(baseCnf.GetEnv("JWT_TOKEN_EXPIRE_TIME", "5"))
tokenExpireTime = time.Duration(int(time.Hour) * min)
expAccessTokenTime, _ := strconv.Atoi(baseCnf.GetEnv("JWT_ACCESS_TOKEN_EXPIRE_TIME", "5"))
accessTokenExpireTime = time.Duration(int(time.Hour) * expAccessTokenTime) // hours
expRefreshTokenTime, _ := strconv.Atoi(baseCnf.GetEnv("JWT_REFRESH_TOKEN_EXPIRE_TIME", "7"))
refreshTokenExpireTime = time.Duration(int(time.Hour*24) * expRefreshTokenTime) // days
jwtSrv = &JWT{
tokenExpireTime,
[]byte(baseCnf.GetEnv("JWT_SECRET_KEY", "B413IlIv9nKQfsMCXTE0Cteo4yHgUEfqaLfjg73sNlh")),
accessTokenExpireTime,
[]byte(baseCnf.GetEnv("JWT_ACCESS_TOKEN_SECRET_KEY", "FallbackAccessTokenSecret")),
refreshTokenExpireTime,
[]byte(baseCnf.GetEnv("JWT_REFRESH_TOKEN_SECRET_KEY", "FallbackRefreshTokenSecret")),
}
}
type JWT struct {
tokenExpireTime time.Duration
tokenSecret []byte
accessTokenExpireTime time.Duration
accessTokenSecret []byte
refreshTokenExpireTime time.Duration
refreshTokenSecret []byte
}
func (s *JWT) CreateToken(id string) (string, error) {
func (s *JWT) CreateAccessToken(id string) (string, error) {
claims := &jwt.StandardClaims{
Id: id,
ExpiresAt: time.Now().Add(time.Duration(s.tokenExpireTime) * time.Minute).Unix(),
Subject: id,
IssuedAt: time.Now().Unix(),
ExpiresAt: time.Now().Add(s.accessTokenExpireTime).Unix(),
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString(s.tokenSecret)
return token.SignedString(s.accessTokenSecret)
}
func (s *JWT) CreateRefreshToken(id string) (string, error) {
claims := &jwt.StandardClaims{
Subject: id,
IssuedAt: time.Now().Unix(),
ExpiresAt: time.Now().Add(s.refreshTokenExpireTime).Unix(),
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString(s.accessTokenSecret)
}
func (s *JWT) ValidateToken(tokenStr string) error {
@@ -46,7 +68,7 @@ func (s *JWT) ValidateToken(tokenStr string) error {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return s.tokenSecret, nil
return s.accessTokenSecret, nil
})
if _, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {