From 53baf4d6ac5907bb6d14b9a2c98302c9732d2615 Mon Sep 17 00:00:00 2001 From: dogukanoksuz Date: Fri, 19 Jul 2024 08:12:46 +0000 Subject: [PATCH] feat: All token system moved to JWT instead of random DB generated string --- app/handlers/extension.go | 7 +--- app/handlers/external.go | 7 +--- app/handlers/file.go | 7 +--- app/handlers/job.go | 7 +--- app/middleware/auth/new.go | 61 ++++++++++++++---------------- app/models/token.go | 14 ------- go.mod | 1 + go.sum | 2 + internal/liman/auth.go | 13 ------- internal/user_token/user_token.go | 62 +++++++------------------------ pkg/utils/server.go | 5 +++ 11 files changed, 53 insertions(+), 133 deletions(-) delete mode 100644 app/models/token.go diff --git a/app/handlers/extension.go b/app/handlers/extension.go index 7dfcc950..4600059d 100644 --- a/app/handlers/extension.go +++ b/app/handlers/extension.go @@ -49,11 +49,6 @@ func ExtensionRunner(c *fiber.Ctx) error { formValues := helpers.GetFormData(c) - token := c.FormValue("token") - if len(c.FormValue("liman-token")) > 0 { - token = c.FormValue("liman-token") - } - command, err := sandbox.GenerateCommand( extension, credentials, @@ -63,7 +58,7 @@ func ExtensionRunner(c *fiber.Ctx) error { Extension: c.FormValue("extension_id"), Server: c.FormValue("server_id"), RequestData: formValues, - Token: token, + Token: c.Locals("token").(string), BaseURL: c.FormValue("lmnbaseurl", c.Get("origin")), Locale: c.FormValue("locale", helpers.Env("APP_LANG", "tr")), LogID: c.Locals("log_id").(string), diff --git a/app/handlers/external.go b/app/handlers/external.go index a2fea5a3..f8d80b93 100644 --- a/app/handlers/external.go +++ b/app/handlers/external.go @@ -54,11 +54,6 @@ func ExternalAPI(c *fiber.Ctx) error { formValues := helpers.GetFormData(c) - token := c.FormValue("token") - if len(c.FormValue("liman-token")) > 0 { - token = c.FormValue("liman-token") - } - command, err := sandbox.GenerateCommand( extension, credentials, @@ -68,7 +63,7 @@ func ExternalAPI(c *fiber.Ctx) error { Extension: c.FormValue("extension_id"), Server: c.FormValue("server_id"), RequestData: formValues, - Token: token, + Token: c.Locals("token").(string), BaseURL: c.FormValue("lmnbaseurl", c.Get("origin")), Locale: c.FormValue("locale", helpers.Env("APP_LANG", "tr")), LogID: c.Locals("log_id").(string), diff --git a/app/handlers/file.go b/app/handlers/file.go index 3f65fe9b..e35f9bf1 100644 --- a/app/handlers/file.go +++ b/app/handlers/file.go @@ -134,11 +134,6 @@ func DownloadFile(c *fiber.Ctx) error { formValues := helpers.GetFormData(c) - token := c.FormValue("token") - if len(c.FormValue("liman-token")) > 0 { - token = c.FormValue("liman-token") - } - _, err = sandbox.GenerateCommand( extension, credentials, @@ -148,7 +143,7 @@ func DownloadFile(c *fiber.Ctx) error { Extension: c.FormValue("extension_id"), Server: c.FormValue("server_id"), RequestData: formValues, - Token: token, + Token: c.Locals("token").(string), BaseURL: c.FormValue("lmnbaseurl", c.Get("origin")), Locale: c.FormValue("locale", helpers.Env("APP_LANG", "tr")), LogID: c.Locals("log_id").(string), diff --git a/app/handlers/job.go b/app/handlers/job.go index f044325c..845f3b30 100644 --- a/app/handlers/job.go +++ b/app/handlers/job.go @@ -45,11 +45,6 @@ func BackgroundJob(c *fiber.Ctx) error { formValues := helpers.GetFormData(c) - token := c.FormValue("token") - if len(c.FormValue("liman-token")) > 0 { - token = c.FormValue("liman-token") - } - command, err := sandbox.GenerateCommand( extension, credentials, @@ -59,7 +54,7 @@ func BackgroundJob(c *fiber.Ctx) error { Extension: c.FormValue("extension_id"), Server: c.FormValue("server_id"), RequestData: formValues, - Token: token, + Token: c.Locals("token").(string), BaseURL: c.FormValue("lmnbaseurl", c.Get("origin")), Locale: c.FormValue("locale", helpers.Env("APP_LANG", "tr")), }, diff --git a/app/middleware/auth/new.go b/app/middleware/auth/new.go index 061d280a..61842c14 100644 --- a/app/middleware/auth/new.go +++ b/app/middleware/auth/new.go @@ -22,64 +22,56 @@ type Cookie struct { // authorization Middleware auths users before requests func authorization(c *fiber.Ctx) error { - cookie := new(Cookie) - c.CookieParser(cookie) + if len(c.FormValue("liman-token")) > 0 { + user, err := liman.AuthWithAccessToken( + strings.Trim(c.FormValue("liman-token"), ""), + ) - if len(cookie.Token) > 0 { - decoded, err := url.QueryUnescape(cookie.Token) if err != nil { - logger.FiberError(fiber.StatusUnauthorized, "invalid authorization token (cookie), "+err.Error()) + return logger.FiberError(fiber.StatusUnauthorized, err.Error()) } - if len(decoded) < 1 { - return logger.FiberError(fiber.StatusUnauthorized, "authorization token is missing") - } + c.Locals("user_id", user) + return c.Next() + } - code, err := helpers.LaravelAesDecrypt("token", decoded) + if len(string(c.Request().Header.Peek("Authorization"))) > 0 { + code, err := helpers.LaravelAesDecrypt("token", c.FormValue("token")) if err != nil { - return logger.FiberError(fiber.StatusUnauthorized, "invalid authorization token (cookie), "+err.Error()) + return jwtValidation(c, c.FormValue("token")) } return jwtValidation(c, code) } - if len(c.FormValue("token")) > 0 { - user, err := liman.AuthWithToken( - strings.Trim(c.FormValue("token"), ""), - ) + cookie := new(Cookie) + c.CookieParser(cookie) + if len(cookie.Token) > 0 { + decoded, err := url.QueryUnescape(cookie.Token) if err != nil { - return logger.FiberError(fiber.StatusUnauthorized, err.Error()) + logger.FiberError(fiber.StatusUnauthorized, "invalid authorization token (cookie), "+err.Error()) } - c.Locals("user_id", user) - return c.Next() - } - - if len(c.FormValue("liman-token")) > 0 { - user, err := liman.AuthWithAccessToken( - strings.Trim(c.FormValue("liman-token"), ""), - ) + if len(decoded) < 1 { + return logger.FiberError(fiber.StatusUnauthorized, "authorization token is missing") + } + code, err := helpers.LaravelAesDecrypt("token", decoded) if err != nil { - return logger.FiberError(fiber.StatusUnauthorized, err.Error()) + return jwtValidation(c, decoded) } - c.Locals("user_id", user) - return c.Next() + return jwtValidation(c, code) } - if len(string(c.Request().Header.Peek("Authorization"))) > 0 { - user, err := liman.AuthWithToken( - strings.Trim(string(c.Request().Header.Peek("Authorization")), ""), - ) - + if len(c.FormValue("token")) > 0 { + code, err := helpers.LaravelAesDecrypt("token", c.FormValue("token")) if err != nil { - return logger.FiberError(fiber.StatusUnauthorized, err.Error()) + return jwtValidation(c, c.FormValue("token")) } - c.Locals("user_id", user) - return c.Next() + return jwtValidation(c, code) } return logger.FiberError(fiber.StatusUnauthorized, "authorization token is missing") @@ -99,6 +91,7 @@ func jwtValidation(c *fiber.Ctx, code string) error { if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { c.Locals("user_id", claims["sub"]) + c.Locals("token", code) return c.Next() } else { return logger.FiberError(fiber.StatusUnauthorized, "invalid authorization token") diff --git a/app/models/token.go b/app/models/token.go deleted file mode 100644 index 5866534a..00000000 --- a/app/models/token.go +++ /dev/null @@ -1,14 +0,0 @@ -package models - -// TokenModel Structure of the tokens tableD -type Token struct { - ID string `json:"id"` - UserID string `json:"user_id"` - Token string `json:"token"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` -} - -func (Token) TableName() string { - return "tokens" -} diff --git a/go.mod b/go.mod index 4a3f24b8..e2168c5c 100644 --- a/go.mod +++ b/go.mod @@ -52,6 +52,7 @@ require ( github.com/andybalholm/brotli v1.0.6 // indirect github.com/avast/retry-go v3.0.0+incompatible github.com/dariubs/gorm-jsonb v0.1.5 + github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/go-sql-driver/mysql v1.7.1 // indirect github.com/hirochachacha/go-smb2 v1.1.0 github.com/jackc/pgpassfile v1.0.0 // indirect diff --git a/go.sum b/go.sum index 3fce4fce..c039087a 100644 --- a/go.sum +++ b/go.sum @@ -19,6 +19,8 @@ github.com/dariubs/gorm-jsonb v0.1.5/go.mod h1:e6GXwMviS3e9QxADNOWWZq0WBTdxpK2So github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/geoffgarside/ber v1.1.0 h1:qTmFG4jJbwiSzSXoNJeHcOprVzZ8Ulde2Rrrifu5U9w= github.com/geoffgarside/ber v1.1.0/go.mod h1:jVPKeCbj6MvQZhwLYsGwaGI52oUorHoHKNecGT85ZCc= github.com/go-co-op/gocron v1.35.3 h1:it2WjWnabS8eJZ+P68WroBe+ZWyJ3kVjRD6KXdpr5yI= diff --git a/internal/liman/auth.go b/internal/liman/auth.go index 74777aca..17b39006 100644 --- a/internal/liman/auth.go +++ b/internal/liman/auth.go @@ -7,19 +7,6 @@ import ( "github.com/limanmys/render-engine/pkg/logger" ) -// AuthWithToken Auth user with proprietary Liman token -func AuthWithToken(token string) (string, error) { - tokenObj := &models.Token{} - - err := database.Connection().First(&tokenObj, "token = ?", token).Error - - if err != nil || len(tokenObj.UserID) < 1 { - return "", logger.FiberError(fiber.StatusUnauthorized, "authorization token is not valid") - } - - return tokenObj.UserID, nil -} - // AuthWithAccessToken Auth user with generated access token func AuthWithAccessToken(token string) (string, error) { tokenObj := &models.AccessToken{} diff --git a/internal/user_token/user_token.go b/internal/user_token/user_token.go index 79712485..d3012632 100644 --- a/internal/user_token/user_token.go +++ b/internal/user_token/user_token.go @@ -1,63 +1,29 @@ package user_token import ( + "os" "time" - "github.com/google/uuid" - "github.com/limanmys/render-engine/app/models" - "github.com/limanmys/render-engine/internal/database" - gorandom "github.com/zekiahmetbayar/go-random" + "github.com/dgrijalva/jwt-go" ) -// Create a new token or retrieve old one +// Create a new token for user purpose of internal use func Create(user_id string) (string, error) { - // Search token on database - var token models.Token - database.Connection().Model(&models.Token{}).Where("user_id = ?", user_id).First(&token) - - // If token does not exists, create token - if token.ID == "" { - // Create new id for token - uid := uuid.New() - // Generate token - token := generate() - // Create token on database - if err := database.Connection().Model(&models.Token{}).Create(models.Token{ - ID: uid.String(), - CreatedAt: time.Now().Format(time.RFC3339), - UpdatedAt: time.Now().Format(time.RFC3339), - UserID: user_id, - Token: token, - }).Error; err != nil { - return "", err - } - - return token, nil - } - // Get token update date - updateDate, err := time.Parse(time.RFC3339, token.UpdatedAt) - if err != nil { - return "", err - } - // If token updated after 6 hours - if time.Since(updateDate).Hours() > 6 { - // TODO: Update token - token_str := generate() - if err := database.Connection().Model(&token).Update("token", token_str).Error; err != nil { - return "", err - } - return token_str, nil + // Define the JWT claims + claims := jwt.MapClaims{ + "sub": user_id, + "exp": time.Now().Add(time.Minute * 15).Unix(), // Token expiration time } - return token.Token, nil -} + // Create the JWT token + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) -// Generate a new token -func generate() string { - token, err := gorandom.String(false, true, false, 32) + // Sign the token with a secret key + // Replace "your-secret-key" with your actual secret key + tokenString, err := token.SignedString([]byte(os.Getenv("JWT_SECRET"))) if err != nil { - return "" + return "", err } - return token + return tokenString, nil } diff --git a/pkg/utils/server.go b/pkg/utils/server.go index f6ea4644..3d440129 100644 --- a/pkg/utils/server.go +++ b/pkg/utils/server.go @@ -7,6 +7,7 @@ import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/compress" + "github.com/gofiber/fiber/v2/middleware/cors" "github.com/gofiber/fiber/v2/middleware/recover" "github.com/gofiber/helmet/v2" "github.com/limanmys/render-engine/app/middleware/app_logger" @@ -42,6 +43,10 @@ func CreateServer() { app.Use(auth.New()) app.Use(permission.New()) app.Use(app_logger.New()) + app.Use(cors.New(cors.Config{ + AllowOrigins: "*", + AllowCredentials: true, + })) // Mount routes routes.Install(app)