Security: refactor 'redirect_to' cookie to use 'Secure' flag (#19787)

* Refactor redirect_to cookie with secure flag in middleware

* Refactor redirect_to cookie with secure flag in api/login

* Refactor redirect_to cookie with secure flag in api/login_oauth

* Removed the deletion of 'Set-Cookie' header to prevent logout

* Removed the deletion of 'Set-Cookie' at top of api/login.go

* Add HttpOnly flag on redirect_to cookies where missing

* Refactor duplicated code

* Add tests

* Refactor cookie options

* Replace local function for deleting cookie

* Delete redundant calls

Co-authored-by: Sofia Papagiannaki <papagian@users.noreply.github.com>
This commit is contained in:
Jeffrey Descan
2020-01-10 15:55:30 +02:00
committed by Sofia Papagiannaki
co-authored by Sofia Papagiannaki
parent a3c99f4871
commit c5f906f472
6 changed files with 101 additions and 70 deletions
+1 -1
View File
@@ -47,7 +47,7 @@ func notAuthorized(c *m.ReqContext) {
return
}
c.SetCookie("redirect_to", url.QueryEscape(setting.AppSubUrl+c.Req.RequestURI), 0, setting.AppSubUrl+"/", nil, false, true)
WriteCookie(c.Resp, "redirect_to", url.QueryEscape(setting.AppSubUrl+c.Req.RequestURI), 0, newCookieOptions)
c.Redirect(setting.AppSubUrl + "/login")
}
+43
View File
@@ -0,0 +1,43 @@
package middleware
import (
"net/http"
"github.com/grafana/grafana/pkg/setting"
)
type CookieOptions struct {
Path string
Secure bool
SameSite http.SameSite
}
func newCookieOptions() CookieOptions {
return CookieOptions{
Path: setting.AppSubUrl + "/",
Secure: setting.CookieSecure,
SameSite: setting.CookieSameSite,
}
}
type GetCookieOptionsFunc func() CookieOptions
func DeleteCookie(w http.ResponseWriter, name string, getCookieOptionsFunc GetCookieOptionsFunc) {
WriteCookie(w, name, "", -1, getCookieOptionsFunc)
}
func WriteCookie(w http.ResponseWriter, name string, value string, maxAge int, getCookieOptionsFunc GetCookieOptionsFunc) {
options := getCookieOptionsFunc()
cookie := http.Cookie{
Name: name,
MaxAge: maxAge,
Value: value,
HttpOnly: true,
Path: options.Path,
Secure: options.Secure,
}
if options.SameSite != http.SameSiteDefaultMode {
cookie.SameSite = options.SameSite
}
http.SetCookie(w, &cookie)
}
+1 -15
View File
@@ -2,7 +2,6 @@ package middleware
import (
"fmt"
"net/http"
"net/url"
"strconv"
"strings"
@@ -253,20 +252,7 @@ func WriteSessionCookie(ctx *models.ReqContext, value string, maxLifetimeDays in
maxAge = int(maxAgeHours.Seconds())
}
ctx.Resp.Header().Del("Set-Cookie")
cookie := http.Cookie{
Name: setting.LoginCookieName,
Value: url.QueryEscape(value),
HttpOnly: true,
Path: setting.AppSubUrl + "/",
Secure: setting.CookieSecure,
MaxAge: maxAge,
}
if setting.CookieSameSite != http.SameSiteDefaultMode {
cookie.SameSite = setting.CookieSameSite
}
http.SetCookie(ctx.Resp, &cookie)
WriteCookie(ctx.Resp, setting.LoginCookieName, url.QueryEscape(value), maxAge, newCookieOptions)
}
func AddDefaultResponseHeaders() macaron.Handler {