From 2d8af0510ea8e41591416d432fa9df288745592f Mon Sep 17 00:00:00 2001 From: Stavros Date: Fri, 26 Dec 2025 17:55:54 +0200 Subject: [PATCH] feat: refresh session cookie when session is active (#540) * feat: refresh session cookie when session is active * refactor: use current time to set new expiry --- .gitignore | 5 ++- internal/controller/proxy_controller.go | 12 +----- internal/controller/proxy_controller_test.go | 7 --- internal/middleware/context_middleware.go | 2 + internal/service/auth_service.go | 45 +++++++++++++++++--- 5 files changed, 46 insertions(+), 25 deletions(-) diff --git a/.gitignore b/.gitignore index 576aeee..0eefed8 100644 --- a/.gitignore +++ b/.gitignore @@ -33,4 +33,7 @@ # binary out /tinyauth.db -/resources \ No newline at end of file +/resources + +# debug files +__debug_* \ No newline at end of file diff --git a/internal/controller/proxy_controller.go b/internal/controller/proxy_controller.go index 50e4ed2..431c988 100644 --- a/internal/controller/proxy_controller.go +++ b/internal/controller/proxy_controller.go @@ -43,7 +43,8 @@ func NewProxyController(config ProxyControllerConfig, router *gin.RouterGroup, a func (controller *ProxyController) SetupRoutes() { proxyGroup := controller.router.Group("/auth") - proxyGroup.Any("/:proxy", controller.proxyHandler) + proxyGroup.GET("/:proxy", controller.proxyHandler) + proxyGroup.POST("/:proxy", controller.proxyHandler) } func (controller *ProxyController) proxyHandler(c *gin.Context) { @@ -68,15 +69,6 @@ func (controller *ProxyController) proxyHandler(c *gin.Context) { return } - if req.Proxy != "envoy" && c.Request.Method != http.MethodGet { - log.Warn().Str("method", c.Request.Method).Msg("Invalid method for proxy") - c.JSON(405, gin.H{ - "status": 405, - "message": "Method Not Allowed", - }) - return - } - isBrowser := strings.Contains(c.Request.Header.Get("Accept"), "text/html") if isBrowser { diff --git a/internal/controller/proxy_controller_test.go b/internal/controller/proxy_controller_test.go index f2999c1..d0de555 100644 --- a/internal/controller/proxy_controller_test.go +++ b/internal/controller/proxy_controller_test.go @@ -81,13 +81,6 @@ func TestProxyHandler(t *testing.T) { assert.Equal(t, 400, recorder.Code) - // Test invalid method - recorder = httptest.NewRecorder() - req = httptest.NewRequest("POST", "/api/auth/traefik", nil) - router.ServeHTTP(recorder, req) - - assert.Equal(t, 405, recorder.Code) - // Test logged out user (traefik/caddy) recorder = httptest.NewRecorder() req = httptest.NewRequest("GET", "/api/auth/traefik", nil) diff --git a/internal/middleware/context_middleware.go b/internal/middleware/context_middleware.go index c763ae3..3101bd9 100644 --- a/internal/middleware/context_middleware.go +++ b/internal/middleware/context_middleware.go @@ -66,6 +66,7 @@ func (m *ContextMiddleware) Middleware() gin.HandlerFunc { goto basic } + m.auth.RefreshSessionCookie(c) c.Set("context", &config.UserContext{ Username: cookie.Username, Name: cookie.Name, @@ -90,6 +91,7 @@ func (m *ContextMiddleware) Middleware() gin.HandlerFunc { goto basic } + m.auth.RefreshSessionCookie(c) c.Set("context", &config.UserContext{ Username: cookie.Username, Name: cookie.Name, diff --git a/internal/service/auth_service.go b/internal/service/auth_service.go index 2bfd29e..b55d77e 100644 --- a/internal/service/auth_service.go +++ b/internal/service/auth_service.go @@ -1,7 +1,6 @@ package service import ( - "context" "errors" "fmt" "regexp" @@ -44,7 +43,6 @@ type AuthService struct { loginMutex sync.RWMutex ldap *LdapService database *gorm.DB - ctx context.Context } func NewAuthService(config AuthServiceConfig, docker *DockerService, ldap *LdapService, database *gorm.DB) *AuthService { @@ -58,7 +56,6 @@ func NewAuthService(config AuthServiceConfig, docker *DockerService, ldap *LdapS } func (auth *AuthService) Init() error { - auth.ctx = context.Background() return nil } @@ -218,7 +215,7 @@ func (auth *AuthService) CreateSessionCookie(c *gin.Context, data *config.Sessio OAuthName: data.OAuthName, } - err = gorm.G[model.Session](auth.database).Create(auth.ctx, &session) + err = gorm.G[model.Session](auth.database).Create(c, &session) if err != nil { return err @@ -229,6 +226,40 @@ func (auth *AuthService) CreateSessionCookie(c *gin.Context, data *config.Sessio return nil } +func (auth *AuthService) RefreshSessionCookie(c *gin.Context) error { + cookie, err := c.Cookie(auth.config.SessionCookieName) + + if err != nil { + return err + } + + session, err := gorm.G[model.Session](auth.database).Where("uuid = ?", cookie).First(c) + + if err != nil { + return err + } + + currentTime := time.Now().Unix() + + if session.Expiry-currentTime > int64(time.Hour.Seconds()) { + return nil + } + + newExpiry := currentTime + int64(time.Hour.Seconds()) + + _, err = gorm.G[model.Session](auth.database).Where("uuid = ?", cookie).Updates(c, model.Session{ + Expiry: newExpiry, + }) + + if err != nil { + return err + } + + c.SetCookie(auth.config.SessionCookieName, cookie, int(time.Hour.Seconds()), "/", fmt.Sprintf(".%s", auth.config.CookieDomain), auth.config.SecureCookie, true) + + return nil +} + func (auth *AuthService) DeleteSessionCookie(c *gin.Context) error { cookie, err := c.Cookie(auth.config.SessionCookieName) @@ -236,7 +267,7 @@ func (auth *AuthService) DeleteSessionCookie(c *gin.Context) error { return err } - _, err = gorm.G[model.Session](auth.database).Where("uuid = ?", cookie).Delete(auth.ctx) + _, err = gorm.G[model.Session](auth.database).Where("uuid = ?", cookie).Delete(c) if err != nil { return err @@ -254,7 +285,7 @@ func (auth *AuthService) GetSessionCookie(c *gin.Context) (config.SessionCookie, return config.SessionCookie{}, err } - session, err := gorm.G[model.Session](auth.database).Where("uuid = ?", cookie).First(auth.ctx) + session, err := gorm.G[model.Session](auth.database).Where("uuid = ?", cookie).First(c) if err != nil { return config.SessionCookie{}, err @@ -267,7 +298,7 @@ func (auth *AuthService) GetSessionCookie(c *gin.Context) (config.SessionCookie, currentTime := time.Now().Unix() if currentTime > session.Expiry { - _, err = gorm.G[model.Session](auth.database).Where("uuid = ?", cookie).Delete(auth.ctx) + _, err = gorm.G[model.Session](auth.database).Where("uuid = ?", cookie).Delete(c) if err != nil { log.Error().Err(err).Msg("Failed to delete expired session") }