From 3921db6166e2da895257496bb76dd115556699d3 Mon Sep 17 00:00:00 2001 From: Grail Finder Date: Sat, 29 Mar 2025 11:12:53 +0300 Subject: init --- internal/handlers/middleware.go | 75 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 internal/handlers/middleware.go (limited to 'internal/handlers/middleware.go') diff --git a/internal/handlers/middleware.go b/internal/handlers/middleware.go new file mode 100644 index 0000000..8b871a2 --- /dev/null +++ b/internal/handlers/middleware.go @@ -0,0 +1,75 @@ +package handlers + +import ( + "context" + "crypto/hmac" + "crypto/sha256" + "encoding/base64" + "errors" + "net/http" +) + +func (h *Handlers) GetSession(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + cookieName := "session_token" + sessionCookie, err := r.Cookie(cookieName) + if err != nil { + msg := "auth failed; failed to get session token from cookies" + h.log.Debug(msg, "error", err) + next.ServeHTTP(w, r) + return + } + cookieValueB, err := base64.URLEncoding. + DecodeString(sessionCookie.Value) + if err != nil { + msg := "auth failed; failed to decode b64 cookie" + h.log.Debug(msg, "error", err) + next.ServeHTTP(w, r) + return + } + cookieValue := string(cookieValueB) + if len(cookieValue) < sha256.Size { + h.log.Warn("small cookie", "size", len(cookieValue)) + next.ServeHTTP(w, r) + return + } + // Split apart the signature and original cookie value. + signature := cookieValue[:sha256.Size] + sessionToken := cookieValue[sha256.Size:] + //verify signature + mac := hmac.New(sha256.New, []byte(h.cfg.CookieSecret)) + mac.Write([]byte(cookieName)) + mac.Write([]byte(sessionToken)) + expectedSignature := mac.Sum(nil) + if !hmac.Equal([]byte(signature), expectedSignature) { + h.log.Debug("cookie with an invalid sign") + next.ServeHTTP(w, r) + return + } + userSession, err := h.cacheGetSession(sessionToken) + if err != nil { + msg := "auth failed; session does not exists" + err = errors.New(msg) + h.log.Debug(msg, "error", err) + next.ServeHTTP(w, r) + return + } + if userSession.IsExpired() { + h.mc.RemoveKey(sessionToken) + msg := "session is expired" + h.log.Debug(msg, "error", err, "token", sessionToken) + next.ServeHTTP(w, r) + return + } + ctx := context.WithValue(r.Context(), + "username", userSession.Username) + if err := h.cacheSetSession(sessionToken, + userSession); err != nil { + msg := "failed to marshal user session" + h.log.Warn(msg, "error", err) + next.ServeHTTP(w, r) + return + } + next.ServeHTTP(w, r.WithContext(ctx)) + }) +} -- cgit v1.2.3