feat(auth): Add logout route
This commit is contained in:
42
app/controllers/logout.go
Normal file
42
app/controllers/logout.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.secnex.io/secnex/auth-api/services"
|
||||||
|
"git.secnex.io/secnex/auth-api/utils"
|
||||||
|
"git.secnex.io/secnex/masterlog"
|
||||||
|
"github.com/go-playground/validator/v10"
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LogoutRequest struct {
|
||||||
|
SessionToken string `json:"token" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func LogoutController(c *fiber.Ctx) error {
|
||||||
|
var request LogoutRequest
|
||||||
|
if err := c.BodyParser(&request); err != nil {
|
||||||
|
return utils.NewErrorResponse(fiber.StatusBadRequest, &fiber.Map{
|
||||||
|
"message": "Invalid request body",
|
||||||
|
}).Send(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
masterlog.Debug("Processing logout request", map[string]interface{}{"session_token": request.SessionToken})
|
||||||
|
|
||||||
|
validate := validator.New()
|
||||||
|
if err := validate.Struct(request); err != nil {
|
||||||
|
return utils.NewErrorResponse(fiber.StatusBadRequest, &fiber.Map{
|
||||||
|
"message": "Invalid request body",
|
||||||
|
}).Send(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := services.Logout(request.SessionToken)
|
||||||
|
if err != nil {
|
||||||
|
return utils.NewErrorResponse(fiber.StatusInternalServerError, &fiber.Map{
|
||||||
|
"message": "Error logging out",
|
||||||
|
}).Send(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
return utils.NewHTTPResponse(fiber.StatusOK, &fiber.Map{
|
||||||
|
"message": "OK",
|
||||||
|
}, "", nil, nil).Send(c)
|
||||||
|
}
|
||||||
@@ -65,6 +65,7 @@ func main() {
|
|||||||
// Controllers
|
// Controllers
|
||||||
app.Post("/login", controllers.LoginController)
|
app.Post("/login", controllers.LoginController)
|
||||||
app.Post("/register", controllers.RegisterController)
|
app.Post("/register", controllers.RegisterController)
|
||||||
|
app.Post("/logout", controllers.LogoutController)
|
||||||
app.Post("/session/info", controllers.SessionInfoController)
|
app.Post("/session/info", controllers.SessionInfoController)
|
||||||
|
|
||||||
if config.ENV == "development" {
|
if config.ENV == "development" {
|
||||||
|
|||||||
@@ -97,3 +97,31 @@ func GetSessionCache(sessionID string) *SessionDetails {
|
|||||||
masterlog.Debug("Session retrieved from cache", map[string]interface{}{"session_id": sessionID, "user_id": sessionDetails.UserID})
|
masterlog.Debug("Session retrieved from cache", map[string]interface{}{"session_id": sessionID, "user_id": sessionDetails.UserID})
|
||||||
return &sessionDetails
|
return &sessionDetails
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DeleteSession(sessionID string) error {
|
||||||
|
masterlog.Debug("Deleting session from database and cache", map[string]interface{}{"session_id": sessionID})
|
||||||
|
if err := DeleteSessionCache(sessionID); err != nil {
|
||||||
|
masterlog.Debug("Failed to delete session from cache", map[string]interface{}{"error": err.Error(), "session_id": sessionID})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := database.DB.Where("id = ?", sessionID).Delete(&models.Session{}).Error; err != nil {
|
||||||
|
masterlog.Debug("Failed to delete session from database", map[string]interface{}{"error": err.Error(), "session_id": sessionID})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
masterlog.Debug("Session deleted from database and cache", map[string]interface{}{"session_id": sessionID})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteSessionCache(sessionID string) error {
|
||||||
|
masterlog.Debug("Deleting session from cache", map[string]interface{}{"session_id": sessionID})
|
||||||
|
if cache.Cache.Client == nil {
|
||||||
|
masterlog.Debug("Redis client not initialized", map[string]interface{}{"session_id": sessionID})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err := cache.Cache.Client.Do(cache.Cache.Context, cache.Cache.Client.B().Del().Key(sessionID).Build()).Error(); err != nil {
|
||||||
|
masterlog.Debug("Failed to delete session from cache", map[string]interface{}{"error": err.Error(), "session_id": sessionID})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
masterlog.Debug("Session deleted from cache", map[string]interface{}{"session_id": sessionID})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
51
app/services/logout.go
Normal file
51
app/services/logout.go
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.secnex.io/secnex/auth-api/config"
|
||||||
|
"git.secnex.io/secnex/auth-api/repositories"
|
||||||
|
"github.com/golang-jwt/jwt/v5"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Logout(sessionToken string) error {
|
||||||
|
claims, err := jwt.ParseWithClaims(sessionToken, &jwt.MapClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||||
|
return []byte(config.CONFIG.JwtSecret), nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !claims.Valid {
|
||||||
|
return errors.New("invalid token")
|
||||||
|
}
|
||||||
|
|
||||||
|
mapClaims := claims.Claims.(*jwt.MapClaims)
|
||||||
|
subValue, ok := (*mapClaims)["sub"]
|
||||||
|
if !ok {
|
||||||
|
return errors.New("sub claim not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
var sessionID string
|
||||||
|
switch v := subValue.(type) {
|
||||||
|
case string:
|
||||||
|
sessionID = v
|
||||||
|
case uuid.UUID:
|
||||||
|
sessionID = v.String()
|
||||||
|
default:
|
||||||
|
sessionID = fmt.Sprintf("%v", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = repositories.DeleteSessionCache(sessionID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = repositories.DeleteSession(sessionID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user