Add SameSite setting for cookies (#14900)

Add SameSite setting for cookies and rationalise the cookie setting code. Switches SameSite to Lax by default. 

There is a possible future extension of differentiating which cookies could be set at Strict by default but that is for a future PR.

Fix #5583

Signed-off-by: Andrew Thornton <art27@cantab.net>
This commit is contained in:
zeripath 2021-03-07 08:12:43 +00:00 committed by GitHub
parent beed5476e2
commit 9b261f52f0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 184 additions and 45 deletions

View file

@ -22,6 +22,8 @@ import (
"net/http"
"time"
"code.gitea.io/gitea/modules/web/middleware"
"github.com/unknwon/com"
)
@ -37,6 +39,8 @@ type CSRF interface {
GetCookiePath() string
// Return the flag value used for the csrf token.
GetCookieHTTPOnly() bool
// Return cookie domain
GetCookieDomain() string
// Return the token.
GetToken() string
// Validate by token.
@ -93,6 +97,11 @@ func (c *csrf) GetCookieHTTPOnly() bool {
return c.CookieHTTPOnly
}
// GetCookieDomain returns the flag value used for the csrf token.
func (c *csrf) GetCookieDomain() string {
return c.CookieDomain
}
// GetToken returns the current token. This is typically used
// to populate a hidden form in an HTML template.
func (c *csrf) GetToken() string {
@ -227,10 +236,14 @@ func Csrfer(opt CsrfOptions, ctx *Context) CSRF {
if opt.CookieLifeTime == 0 {
expires = time.Now().AddDate(0, 0, 1)
}
ctx.SetCookie(opt.Cookie, x.Token, opt.CookieLifeTime, opt.CookiePath, opt.CookieDomain, opt.Secure, opt.CookieHTTPOnly, expires,
func(c *http.Cookie) {
c.SameSite = opt.SameSite
},
middleware.SetCookie(ctx.Resp, opt.Cookie, x.Token,
opt.CookieLifeTime,
opt.CookiePath,
opt.CookieDomain,
opt.Secure,
opt.CookieHTTPOnly,
expires,
middleware.SameSite(opt.SameSite),
)
}
}
@ -248,14 +261,22 @@ func Csrfer(opt CsrfOptions, ctx *Context) CSRF {
func Validate(ctx *Context, x CSRF) {
if token := ctx.Req.Header.Get(x.GetHeaderName()); len(token) > 0 {
if !x.ValidToken(token) {
ctx.SetCookie(x.GetCookieName(), "", -1, x.GetCookiePath())
// Delete the cookie
middleware.SetCookie(ctx.Resp, x.GetCookieName(), "",
-1,
x.GetCookiePath(),
x.GetCookieDomain()) // FIXME: Do we need to set the Secure, httpOnly and SameSite values too?
x.Error(ctx.Resp)
}
return
}
if token := ctx.Req.FormValue(x.GetFormName()); len(token) > 0 {
if !x.ValidToken(token) {
ctx.SetCookie(x.GetCookieName(), "", -1, x.GetCookiePath())
// Delete the cookie
middleware.SetCookie(ctx.Resp, x.GetCookieName(), "",
-1,
x.GetCookiePath(),
x.GetCookieDomain()) // FIXME: Do we need to set the Secure, httpOnly and SameSite values too?
x.Error(ctx.Resp)
}
return