Added JWT Refresh token
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user