From 7c19febd7362a2e78146fb7c40baa54901703190 Mon Sep 17 00:00:00 2001 From: Frédéric Guillot Date: Thu, 28 Dec 2017 20:34:18 -0800 Subject: Add configurable HTTPS flag for secure cookie flag --- server/core/handler.go | 12 ++++++++++-- server/core/request.go | 5 ----- server/middleware/session.go | 18 ++++++++++-------- server/routes.go | 8 ++++---- server/server.go | 2 ++ server/ui/controller/login.go | 4 ++-- server/ui/controller/oauth2.go | 2 +- 7 files changed, 29 insertions(+), 22 deletions(-) (limited to 'server') diff --git a/server/core/handler.go b/server/core/handler.go index a5d84af..647d979 100644 --- a/server/core/handler.go +++ b/server/core/handler.go @@ -8,6 +8,7 @@ import ( "net/http" "time" + "github.com/miniflux/miniflux/config" "github.com/miniflux/miniflux/helper" "github.com/miniflux/miniflux/locale" "github.com/miniflux/miniflux/logger" @@ -16,6 +17,7 @@ import ( "github.com/miniflux/miniflux/storage" "github.com/gorilla/mux" + "github.com/tomasen/realip" ) // HandlerFunc is an application HTTP handler. @@ -23,6 +25,7 @@ type HandlerFunc func(ctx *Context, request *Request, response *Response) // Handler manages HTTP handlers and middlewares. type Handler struct { + cfg *config.Config store *storage.Storage translator *locale.Translator template *template.Engine @@ -34,7 +37,11 @@ type Handler struct { func (h *Handler) Use(f HandlerFunc) http.Handler { return h.middleware.WrapFunc(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { defer helper.ExecutionTime(time.Now(), r.URL.Path) - logger.Debug("[HTTP] %s %s", r.Method, r.URL.Path) + logger.Debug("[HTTP] %s %s %s", realip.RealIP(r), r.Method, r.URL.Path) + + if r.Header.Get("X-Forwarded-Proto") == "https" { + h.cfg.IsHTTPS = true + } ctx := NewContext(w, r, h.store, h.router, h.translator) request := NewRequest(w, r) @@ -51,8 +58,9 @@ func (h *Handler) Use(f HandlerFunc) http.Handler { } // NewHandler returns a new Handler. -func NewHandler(store *storage.Storage, router *mux.Router, template *template.Engine, translator *locale.Translator, middleware *middleware.Chain) *Handler { +func NewHandler(cfg *config.Config, store *storage.Storage, router *mux.Router, template *template.Engine, translator *locale.Translator, middleware *middleware.Chain) *Handler { return &Handler{ + cfg: cfg, store: store, translator: translator, router: router, diff --git a/server/core/request.go b/server/core/request.go index f21b808..f3a3652 100644 --- a/server/core/request.go +++ b/server/core/request.go @@ -36,11 +36,6 @@ func (r *Request) File(name string) (multipart.File, *multipart.FileHeader, erro return r.request.FormFile(name) } -// IsHTTPS returns if the request is made over HTTPS. -func (r *Request) IsHTTPS() bool { - return r.request.URL.Scheme == "https" -} - // Cookie returns the cookie value. func (r *Request) Cookie(name string) string { cookie, err := r.request.Cookie(name) diff --git a/server/middleware/session.go b/server/middleware/session.go index 2891b68..ad02bb2 100644 --- a/server/middleware/session.go +++ b/server/middleware/session.go @@ -8,6 +8,7 @@ import ( "context" "net/http" + "github.com/miniflux/miniflux/config" "github.com/miniflux/miniflux/logger" "github.com/miniflux/miniflux/model" "github.com/miniflux/miniflux/server/cookie" @@ -16,25 +17,26 @@ import ( // SessionMiddleware represents a session middleware. type SessionMiddleware struct { + cfg *config.Config store *storage.Storage } // Handler execute the middleware. -func (t *SessionMiddleware) Handler(next http.Handler) http.Handler { +func (s *SessionMiddleware) Handler(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var err error - session := t.getSessionValueFromCookie(r) + session := s.getSessionValueFromCookie(r) if session == nil { logger.Debug("[Middleware:Session] Session not found") - session, err = t.store.CreateSession() + session, err = s.store.CreateSession() if err != nil { logger.Error("[Middleware:Session] %v", err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } - http.SetCookie(w, cookie.New(cookie.CookieSessionID, session.ID, r.URL.Scheme == "https")) + http.SetCookie(w, cookie.New(cookie.CookieSessionID, session.ID, s.cfg.IsHTTPS)) } else { logger.Debug("[Middleware:Session] %s", session) } @@ -61,13 +63,13 @@ func (t *SessionMiddleware) Handler(next http.Handler) http.Handler { }) } -func (t *SessionMiddleware) getSessionValueFromCookie(r *http.Request) *model.Session { +func (s *SessionMiddleware) getSessionValueFromCookie(r *http.Request) *model.Session { sessionCookie, err := r.Cookie(cookie.CookieSessionID) if err == http.ErrNoCookie { return nil } - session, err := t.store.Session(sessionCookie.Value) + session, err := s.store.Session(sessionCookie.Value) if err != nil { logger.Error("[Middleware:Session] %v", err) return nil @@ -77,6 +79,6 @@ func (t *SessionMiddleware) getSessionValueFromCookie(r *http.Request) *model.Se } // NewSessionMiddleware returns a new SessionMiddleware. -func NewSessionMiddleware(s *storage.Storage) *SessionMiddleware { - return &SessionMiddleware{store: s} +func NewSessionMiddleware(cfg *config.Config, store *storage.Storage) *SessionMiddleware { + return &SessionMiddleware{cfg, store} } diff --git a/server/routes.go b/server/routes.go index 33d6dec..e56b8cc 100644 --- a/server/routes.go +++ b/server/routes.go @@ -33,17 +33,17 @@ func getRoutes(cfg *config.Config, store *storage.Storage, feedHandler *feed.Han feverController := fever.NewController(store) uiController := ui_controller.NewController(cfg, store, pool, feedHandler, opml.NewHandler(store)) - apiHandler := core.NewHandler(store, router, templateEngine, translator, middleware.NewChain( + apiHandler := core.NewHandler(cfg, store, router, templateEngine, translator, middleware.NewChain( middleware.NewBasicAuthMiddleware(store).Handler, )) - feverHandler := core.NewHandler(store, router, templateEngine, translator, middleware.NewChain( + feverHandler := core.NewHandler(cfg, store, router, templateEngine, translator, middleware.NewChain( middleware.NewFeverMiddleware(store).Handler, )) - uiHandler := core.NewHandler(store, router, templateEngine, translator, middleware.NewChain( + uiHandler := core.NewHandler(cfg, store, router, templateEngine, translator, middleware.NewChain( middleware.NewUserSessionMiddleware(store, router).Handler, - middleware.NewSessionMiddleware(store).Handler, + middleware.NewSessionMiddleware(cfg, store).Handler, )) router.Handle("/fever/", feverHandler.Use(feverController.Handler)) diff --git a/server/server.go b/server/server.go index 8107614..4627b83 100644 --- a/server/server.go +++ b/server/server.go @@ -38,6 +38,7 @@ func startServer(cfg *config.Config, handler *mux.Router) *http.Server { } if certDomain != "" && certCache != "" { + cfg.IsHTTPS = true server.Addr = ":https" certManager := autocert.Manager{ Cache: autocert.DirCache(certCache), @@ -51,6 +52,7 @@ func startServer(cfg *config.Config, handler *mux.Router) *http.Server { }() } else if certFile != "" && keyFile != "" { server.TLSConfig = &tls.Config{MinVersion: tls.VersionTLS12} + cfg.IsHTTPS = true go func() { logger.Info(`Listening on "%s" by using certificate "%s" and key "%s"`, server.Addr, certFile, keyFile) diff --git a/server/ui/controller/login.go b/server/ui/controller/login.go index da9531e..ef99c82 100644 --- a/server/ui/controller/login.go +++ b/server/ui/controller/login.go @@ -59,7 +59,7 @@ func (c *Controller) CheckLogin(ctx *core.Context, request *core.Request, respon logger.Info("[Controller:CheckLogin] username=%s just logged in", authForm.Username) - response.SetCookie(cookie.New(cookie.CookieUserSessionID, sessionToken, request.IsHTTPS())) + response.SetCookie(cookie.New(cookie.CookieUserSessionID, sessionToken, c.cfg.IsHTTPS)) response.Redirect(ctx.Route("unread")) } @@ -71,6 +71,6 @@ func (c *Controller) Logout(ctx *core.Context, request *core.Request, response * logger.Error("[Controller:Logout] %v", err) } - response.SetCookie(cookie.Expired(cookie.CookieUserSessionID, request.IsHTTPS())) + response.SetCookie(cookie.Expired(cookie.CookieUserSessionID, c.cfg.IsHTTPS)) response.Redirect(ctx.Route("login")) } diff --git a/server/ui/controller/oauth2.go b/server/ui/controller/oauth2.go index 5011b1a..25899ff 100644 --- a/server/ui/controller/oauth2.go +++ b/server/ui/controller/oauth2.go @@ -118,7 +118,7 @@ func (c *Controller) OAuth2Callback(ctx *core.Context, request *core.Request, re logger.Info("[Controller:OAuth2Callback] username=%s just logged in", user.Username) - response.SetCookie(cookie.New(cookie.CookieUserSessionID, sessionToken, request.IsHTTPS())) + response.SetCookie(cookie.New(cookie.CookieUserSessionID, sessionToken, c.cfg.IsHTTPS)) response.Redirect(ctx.Route("unread")) } -- cgit v1.2.3