package middleware import ( "net/http" "sync" ) // In-memory session store — swap for Redis/DB in production var ( sessionStore = make(map[string]bool) mu sync.RWMutex ) // RegisterSession adds a token to the store (call this after login) func RegisterSession(token string) { mu.Lock() defer mu.Unlock() sessionStore[token] = true } // RevokeSession removes a token (call this on logout) func RevokeSession(token string) { mu.Lock() defer mu.Unlock() delete(sessionStore, token) } // RequireSession is the middleware — wraps any handler that needs auth func RequireSession(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { cookie, err := r.Cookie("session") if err != nil { // No cookie at all http.Redirect(w, r, "/login", http.StatusSeeOther) return } mu.RLock() valid := sessionStore[cookie.Value] mu.RUnlock() if !valid { // Cookie exists but token is unknown/expired http.SetCookie(w, &http.Cookie{ Name: "session", Value: "", Path: "/", HttpOnly: true, Secure: true, MaxAge: -1, // delete it }) http.Redirect(w, r, "/login", http.StatusSeeOther) return } next.ServeHTTP(w, r) }) }