aboutsummaryrefslogtreecommitdiff
path: root/middleware
diff options
context:
space:
mode:
Diffstat (limited to 'middleware')
-rw-r--r--middleware/app_session.go29
-rw-r--r--middleware/basic_auth.go14
-rw-r--r--middleware/common_headers.go25
-rw-r--r--middleware/fever.go12
-rw-r--r--middleware/logging.go1
-rw-r--r--middleware/user_session.go15
6 files changed, 61 insertions, 35 deletions
diff --git a/middleware/app_session.go b/middleware/app_session.go
index 525cd661..e898ee34 100644
--- a/middleware/app_session.go
+++ b/middleware/app_session.go
@@ -6,9 +6,12 @@ package middleware
import (
"context"
+ "errors"
"net/http"
"github.com/miniflux/miniflux/http/cookie"
+ "github.com/miniflux/miniflux/http/request"
+ "github.com/miniflux/miniflux/http/response/html"
"github.com/miniflux/miniflux/logger"
"github.com/miniflux/miniflux/model"
)
@@ -17,20 +20,21 @@ import (
func (m *Middleware) AppSession(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var err error
- session := m.getSessionValueFromCookie(r)
+ session := m.getAppSessionValueFromCookie(r)
if session == nil {
- logger.Debug("[Middleware:Session] Session not found")
+ logger.Debug("[Middleware:AppSession] Session not found")
+
session, err = m.store.CreateSession()
if err != nil {
- logger.Error("[Middleware:Session] %v", err)
- http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
+ logger.Error("[Middleware:AppSession] %v", err)
+ html.ServerError(w, err)
return
}
http.SetCookie(w, cookie.New(cookie.CookieSessionID, session.ID, m.cfg.IsHTTPS, m.cfg.BasePath()))
} else {
- logger.Debug("[Middleware:Session] %s", session)
+ logger.Debug("[Middleware:AppSession] %s", session)
}
if r.Method == "POST" {
@@ -38,9 +42,8 @@ func (m *Middleware) AppSession(next http.Handler) http.Handler {
headerValue := r.Header.Get("X-Csrf-Token")
if session.Data.CSRF != formValue && session.Data.CSRF != headerValue {
- logger.Error(`[Middleware:Session] Invalid or missing CSRF token: Form="%s", Header="%s"`, formValue, headerValue)
- w.WriteHeader(http.StatusBadRequest)
- w.Write([]byte("Invalid or missing CSRF session!"))
+ logger.Error(`[Middleware:AppSession] Invalid or missing CSRF token: Form="%s", Header="%s"`, formValue, headerValue)
+ html.BadRequest(w, errors.New("invalid or missing CSRF"))
return
}
}
@@ -56,15 +59,15 @@ func (m *Middleware) AppSession(next http.Handler) http.Handler {
})
}
-func (m *Middleware) getSessionValueFromCookie(r *http.Request) *model.Session {
- sessionCookie, err := r.Cookie(cookie.CookieSessionID)
- if err == http.ErrNoCookie {
+func (m *Middleware) getAppSessionValueFromCookie(r *http.Request) *model.Session {
+ cookieValue := request.Cookie(r, cookie.CookieSessionID)
+ if cookieValue == "" {
return nil
}
- session, err := m.store.Session(sessionCookie.Value)
+ session, err := m.store.Session(cookieValue)
if err != nil {
- logger.Error("[Middleware:Session] %v", err)
+ logger.Error("[Middleware:AppSession] %v", err)
return nil
}
diff --git a/middleware/basic_auth.go b/middleware/basic_auth.go
index 9d7a4b2d..edea3338 100644
--- a/middleware/basic_auth.go
+++ b/middleware/basic_auth.go
@@ -8,6 +8,7 @@ import (
"context"
"net/http"
+ "github.com/miniflux/miniflux/http/response/json"
"github.com/miniflux/miniflux/logger"
)
@@ -15,35 +16,30 @@ import (
func (m *Middleware) BasicAuth(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
- errorResponse := `{"error_message": "Not Authorized"}`
username, password, authOK := r.BasicAuth()
if !authOK {
logger.Debug("[Middleware:BasicAuth] No authentication headers sent")
- w.WriteHeader(http.StatusUnauthorized)
- w.Write([]byte(errorResponse))
+ json.Unauthorized(w)
return
}
if err := m.store.CheckPassword(username, password); err != nil {
logger.Info("[Middleware:BasicAuth] Invalid username or password: %s", username)
- w.WriteHeader(http.StatusUnauthorized)
- w.Write([]byte(errorResponse))
+ json.Unauthorized(w)
return
}
user, err := m.store.UserByUsername(username)
if err != nil {
logger.Error("[Middleware:BasicAuth] %v", err)
- w.WriteHeader(http.StatusInternalServerError)
- w.Write([]byte(errorResponse))
+ json.ServerError(w, err)
return
}
if user == nil {
logger.Info("[Middleware:BasicAuth] User not found: %s", username)
- w.WriteHeader(http.StatusUnauthorized)
- w.Write([]byte(errorResponse))
+ json.Unauthorized(w)
return
}
diff --git a/middleware/common_headers.go b/middleware/common_headers.go
new file mode 100644
index 00000000..bdec580c
--- /dev/null
+++ b/middleware/common_headers.go
@@ -0,0 +1,25 @@
+// Copyright 2018 Frédéric Guillot. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+package middleware
+
+import (
+ "net/http"
+)
+
+// CommonHeaders sends common HTTP headers.
+func (m *Middleware) CommonHeaders(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("X-XSS-Protection", "1; mode=block")
+ w.Header().Set("X-Content-Type-Options", "nosniff")
+ w.Header().Set("X-Frame-Options", "DENY")
+ w.Header().Set("Content-Security-Policy", "default-src 'self'; img-src *; media-src *; frame-src *; child-src *")
+
+ if m.cfg.IsHTTPS && m.cfg.HasHSTS() {
+ w.Header().Set("Strict-Transport-Security", "max-age=31536000")
+ }
+
+ next.ServeHTTP(w, r)
+ })
+}
diff --git a/middleware/fever.go b/middleware/fever.go
index c9765fe5..78217e4a 100644
--- a/middleware/fever.go
+++ b/middleware/fever.go
@@ -8,27 +8,25 @@ import (
"context"
"net/http"
+ "github.com/miniflux/miniflux/http/response/json"
"github.com/miniflux/miniflux/logger"
)
// FeverAuth handles Fever API authentication.
func (m *Middleware) FeverAuth(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- logger.Debug("[Middleware:Fever]")
-
apiKey := r.FormValue("api_key")
+
user, err := m.store.UserByFeverToken(apiKey)
if err != nil {
- logger.Error("[Fever] %v", err)
- w.Header().Set("Content-Type", "application/json")
- w.Write([]byte(`{"api_version": 3, "auth": 0}`))
+ logger.Error("[Middleware:Fever] %v", err)
+ json.OK(w, map[string]int{"api_version": 3, "auth": 0})
return
}
if user == nil {
logger.Info("[Middleware:Fever] Fever authentication failure")
- w.Header().Set("Content-Type", "application/json")
- w.Write([]byte(`{"api_version": 3, "auth": 0}`))
+ json.OK(w, map[string]int{"api_version": 3, "auth": 0})
return
}
diff --git a/middleware/logging.go b/middleware/logging.go
index 6fc506a3..a6c141b5 100644
--- a/middleware/logging.go
+++ b/middleware/logging.go
@@ -8,6 +8,7 @@ import (
"net/http"
"github.com/miniflux/miniflux/logger"
+
"github.com/tomasen/realip"
)
diff --git a/middleware/user_session.go b/middleware/user_session.go
index 2cb9f8a9..b27858fc 100644
--- a/middleware/user_session.go
+++ b/middleware/user_session.go
@@ -9,6 +9,8 @@ import (
"net/http"
"github.com/miniflux/miniflux/http/cookie"
+ "github.com/miniflux/miniflux/http/request"
+ "github.com/miniflux/miniflux/http/response"
"github.com/miniflux/miniflux/http/route"
"github.com/miniflux/miniflux/logger"
"github.com/miniflux/miniflux/model"
@@ -19,17 +21,18 @@ import (
// UserSession handles the user session middleware.
func (m *Middleware) UserSession(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- session := m.getSessionFromCookie(r)
+ session := m.getUserSessionFromCookie(r)
if session == nil {
logger.Debug("[Middleware:UserSession] Session not found")
if m.isPublicRoute(r) {
next.ServeHTTP(w, r)
} else {
- http.Redirect(w, r, route.Path(m.router, "login"), http.StatusFound)
+ response.Redirect(w, r, route.Path(m.router, "login"))
}
} else {
logger.Debug("[Middleware:UserSession] %s", session)
+
ctx := r.Context()
ctx = context.WithValue(ctx, UserIDContextKey, session.UserID)
ctx = context.WithValue(ctx, IsAuthenticatedContextKey, true)
@@ -58,13 +61,13 @@ func (m *Middleware) isPublicRoute(r *http.Request) bool {
}
}
-func (m *Middleware) getSessionFromCookie(r *http.Request) *model.UserSession {
- sessionCookie, err := r.Cookie(cookie.CookieUserSessionID)
- if err == http.ErrNoCookie {
+func (m *Middleware) getUserSessionFromCookie(r *http.Request) *model.UserSession {
+ cookieValue := request.Cookie(r, cookie.CookieUserSessionID)
+ if cookieValue == "" {
return nil
}
- session, err := m.store.UserSessionByToken(sessionCookie.Value)
+ session, err := m.store.UserSessionByToken(cookieValue)
if err != nil {
logger.Error("[Middleware:UserSession] %v", err)
return nil