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
|
||||
app.Post("/login", controllers.LoginController)
|
||||
app.Post("/register", controllers.RegisterController)
|
||||
app.Post("/logout", controllers.LogoutController)
|
||||
app.Post("/session/info", controllers.SessionInfoController)
|
||||
|
||||
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})
|
||||
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