From 7f917711662f469fec233545b88e386df25a59a3 Mon Sep 17 00:00:00 2001 From: H3ALY Date: Wed, 16 Apr 2025 10:32:34 +0100 Subject: [PATCH] Implement a stronger, reusable session timeout --- constants/session.go | 5 +++++ middleware/auth.go | 9 +++++--- middleware/sessiontimeout.go | 40 ++++++++++++++++++++++++++++++++++++ routes/accountroutes.go | 20 +++++++++--------- 4 files changed, 61 insertions(+), 13 deletions(-) create mode 100644 constants/session.go create mode 100644 middleware/sessiontimeout.go diff --git a/constants/session.go b/constants/session.go new file mode 100644 index 0000000..ef37552 --- /dev/null +++ b/constants/session.go @@ -0,0 +1,5 @@ +package constants + +import "time" + +const SessionDuration = 30 * time.Minute diff --git a/middleware/auth.go b/middleware/auth.go index 40c4bb2..fda7bd2 100644 --- a/middleware/auth.go +++ b/middleware/auth.go @@ -4,11 +4,10 @@ import ( "net/http" "time" + "synlotto-website/constants" "synlotto-website/helpers" ) -const SessionTimeout = 30 * time.Minute - func Auth(required bool) func(http.HandlerFunc) http.HandlerFunc { return func(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { @@ -23,7 +22,7 @@ func Auth(required bool) func(http.HandlerFunc) http.HandlerFunc { if ok { last, hasLast := session.Values["last_activity"].(time.Time) - if hasLast && time.Since(last) > SessionTimeout { + if hasLast && time.Since(last) > constants.SessionDuration { session.Options.MaxAge = -1 session.Save(r, w) @@ -43,3 +42,7 @@ func Auth(required bool) func(http.HandlerFunc) http.HandlerFunc { } } } + +func Protected(h http.HandlerFunc) http.HandlerFunc { + return Auth(true)(SessionTimeout(h)) +} diff --git a/middleware/sessiontimeout.go b/middleware/sessiontimeout.go new file mode 100644 index 0000000..a0c5662 --- /dev/null +++ b/middleware/sessiontimeout.go @@ -0,0 +1,40 @@ +package middleware + +import ( + "log" + "net/http" + "time" + + session "synlotto-website/handlers/session" + + "synlotto-website/constants" +) + +func SessionTimeout(next http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + sess, err := session.GetSession(w, r) + if err != nil { + http.Redirect(w, r, "/account/login", http.StatusSeeOther) + return + } + + last, ok := sess.Values["last_activity"].(time.Time) + if !ok || time.Since(last) > constants.SessionDuration { + sess.Options.MaxAge = -1 + _ = sess.Save(r, w) + + newSession, _ := session.GetSession(w, r) + newSession.Values["flash"] = "Your session has timed out." + _ = newSession.Save(r, w) + + log.Printf("Session timeout triggered") + http.Redirect(w, r, "/account/login", http.StatusSeeOther) + return + } + + sess.Values["last_activity"] = time.Now().UTC() + _ = sess.Save(r, w) + + next(w, r) + } +} diff --git a/routes/accountroutes.go b/routes/accountroutes.go index e80a0c1..2af5c32 100644 --- a/routes/accountroutes.go +++ b/routes/accountroutes.go @@ -9,17 +9,17 @@ import ( ) func SetupAccountRoutes(mux *http.ServeMux, db *sql.DB) { - mux.HandleFunc("/login", middleware.Auth(false)(handlers.Login)) + mux.HandleFunc("/login", middleware.Protected(handlers.Login)) mux.HandleFunc("/logout", handlers.Logout) - mux.HandleFunc("/signup", middleware.Auth(false)(handlers.Signup)) + mux.HandleFunc("/signup", middleware.Protected(handlers.Signup)) mux.HandleFunc("/account/tickets/add_ticket", handlers.AddTicket(db)) mux.HandleFunc("/account/tickets/my_tickets", handlers.GetMyTickets(db)) - mux.HandleFunc("/account/messages", middleware.Auth(true)(handlers.MessagesInboxHandler(db))) - mux.HandleFunc("/account/messages/read", middleware.Auth(true)(handlers.ReadMessageHandler(db))) - mux.HandleFunc("/account/messages/archive", middleware.Auth(true)(handlers.ArchiveMessageHandler(db))) - mux.HandleFunc("/account/messages/archived", middleware.Auth(true)(handlers.ArchivedMessagesHandler(db))) - mux.HandleFunc("/account/messages/restore", middleware.Auth(true)(handlers.RestoreMessageHandler(db))) - mux.HandleFunc("/account/messages/send", middleware.Auth(true)(handlers.SendMessageHandler(db))) - mux.HandleFunc("/account/notifications", middleware.Auth(true)(handlers.NotificationsHandler(db))) - mux.HandleFunc("/account/notifications/read", middleware.Auth(true)(handlers.MarkNotificationReadHandler(db))) + mux.HandleFunc("/account/messages", middleware.Protected(handlers.MessagesInboxHandler(db))) + mux.HandleFunc("/account/messages/read", middleware.Protected(handlers.ReadMessageHandler(db))) + mux.HandleFunc("/account/messages/archive", middleware.Protected(handlers.ArchiveMessageHandler(db))) + mux.HandleFunc("/account/messages/archived", middleware.Protected(handlers.ArchivedMessagesHandler(db))) + mux.HandleFunc("/account/messages/restore", middleware.Protected(handlers.RestoreMessageHandler(db))) + mux.HandleFunc("/account/messages/send", middleware.Protected(handlers.SendMessageHandler(db))) + mux.HandleFunc("/account/notifications", middleware.Protected(handlers.NotificationsHandler(db))) + mux.HandleFunc("/account/notifications/read", middleware.Protected(handlers.MarkNotificationReadHandler(db))) }