package handlers import ( "context" "crypto/hmac" "crypto/sha256" "encoding/base64" "gralias/models" "net/http" ) // LogRequests logs all HTTP requests with method, path and duration func LogRequests(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // start := time.Now() // Wrap response writer to capture status code next.ServeHTTP(w, r) // duration := time.Since(start) // log.Debug("request completed", // "method", r.Method, // "path", r.URL.RequestURI(), // "duration", duration.String(), // ) }) } func GetSession(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { sessionCookie, err := r.Cookie(models.AuthCookie) if err != nil { msg := "auth failed; failed to get session token from cookies" 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" log.Debug(msg, "error", err) next.ServeHTTP(w, r) return } cookieValue := string(cookieValueB) if len(cookieValue) < sha256.Size { 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(cfg.CookieSecret)) mac.Write([]byte(models.AuthCookie)) mac.Write([]byte(sessionToken)) expectedSignature := mac.Sum(nil) if !hmac.Equal([]byte(signature), expectedSignature) { log.Debug("cookie with an invalid sign") next.ServeHTTP(w, r) return } userSession, err := repo.SessionByToken(r.Context(), sessionToken) // userSession, err := cacheGetSession(sessionToken) // log.Debug("userSession from cache", "us", userSession) if err != nil { msg := "auth failed; session does not exists" log.Debug(msg, "error", err, "key", sessionToken) next.ServeHTTP(w, r) return } if userSession.IsExpired() { if err := repo.SessionDelete(r.Context(), sessionToken); err != nil { log.Error("failed to delete session", "error", err) } // cache.MemCache.RemoveKey(sessionToken) msg := "session is expired" log.Debug(msg, "error", err, "token", sessionToken) next.ServeHTTP(w, r) return } ctx := context.WithValue(r.Context(), models.CtxUsernameKey, userSession.Username) ctx = context.WithValue(ctx, models.CtxSessionKey, userSession) // if err := cacheSetSession(sessionToken, // userSession); err != nil { // msg := "failed to marshal user session" // log.Warn(msg, "error", err) // next.ServeHTTP(w, r) // return // } next.ServeHTTP(w, r.WithContext(ctx)) }) }