]> source.dussan.org Git - gitea.git/commitdiff
Add SameSite setting for cookies (#14900)
authorzeripath <art27@cantab.net>
Sun, 7 Mar 2021 08:12:43 +0000 (08:12 +0000)
committerGitHub <noreply@github.com>
Sun, 7 Mar 2021 08:12:43 +0000 (08:12 +0000)
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>
14 files changed:
custom/conf/app.example.ini
docs/content/doc/advanced/config-cheat-sheet.en-us.md
modules/auth/sso/sso.go
modules/context/auth.go
modules/context/context.go
modules/context/csrf.go
modules/setting/session.go
modules/web/middleware/cookie.go
modules/web/middleware/locale.go
routers/home.go
routers/install.go
routers/user/auth.go
routers/user/auth_openid.go
routers/user/setting/profile.go

index a6965c2cf642b0bc977fe210f59b2f48dd6e95e8..b86c8f1fae3294f68357a98ebefe38c8a5cf7355 100644 (file)
@@ -794,6 +794,8 @@ COOKIE_SECURE = false
 GC_INTERVAL_TIME = 86400
 ; Session life time in seconds, default is 86400 (1 day)
 SESSION_LIFE_TIME = 86400
+; SameSite settings. Either "none", "lax", or "strict"
+SAME_SITE=lax
 
 [picture]
 AVATAR_UPLOAD_PATH = data/avatars
index 9a9eb1d466b2c554946e6434f287a3dc09ba5823..70870d3ec5e11164923738fc0bfe2da4b20ea239 100644 (file)
@@ -557,6 +557,8 @@ Define allowed algorithms and their minimum key length (use -1 to disable a type
 - `COOKIE_NAME`: **i\_like\_gitea**: The name of the cookie used for the session ID.
 - `GC_INTERVAL_TIME`: **86400**: GC interval in seconds.
 - `SESSION_LIFE_TIME`: **86400**: Session life time in seconds, default is 86400 (1 day)
+- `DOMAIN`: **\<empty\>**: Sets the cookie Domain
+- `SAME_SITE`: **lax** \[strict, lax, none\]: Set the SameSite setting for the cookie.
 
 ## Picture (`picture`)
 
index 437bf3af7a938f68e492a2789094bb792b56ab37..e670f1a8a7193e83bdbe49cd6c7a53eefa6f0da2 100644 (file)
@@ -13,7 +13,6 @@ import (
 
        "code.gitea.io/gitea/models"
        "code.gitea.io/gitea/modules/log"
-       "code.gitea.io/gitea/modules/setting"
        "code.gitea.io/gitea/modules/web/middleware"
 )
 
@@ -129,8 +128,8 @@ func handleSignIn(resp http.ResponseWriter, req *http.Request, sess SessionStore
                }
        }
 
-       middleware.SetCookie(resp, "lang", user.Language, nil, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true)
+       middleware.SetLocaleCookie(resp, user.Language, 0)
 
        // Clear whatever CSRF has right now, force to generate a new one
-       middleware.SetCookie(resp, setting.CSRFCookieName, "", -1, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true)
+       middleware.DeleteCSRFCookie(resp)
 }
index 8be6ed1907e500b669dfdcf391bab7adf889fe60..3b4d7fc5958c48db28f1e92d7ee33556674357da 100644 (file)
@@ -9,6 +9,7 @@ import (
        "code.gitea.io/gitea/models"
        "code.gitea.io/gitea/modules/log"
        "code.gitea.io/gitea/modules/setting"
+       "code.gitea.io/gitea/modules/web/middleware"
 )
 
 // ToggleOptions contains required or check options
@@ -41,7 +42,7 @@ func Toggle(options *ToggleOptions) func(ctx *Context) {
                                        ctx.Data["Title"] = ctx.Tr("auth.must_change_password")
                                        ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/change_password"
                                        if ctx.Req.URL.Path != "/user/events" {
-                                               ctx.SetCookie("redirect_to", setting.AppSubURL+ctx.Req.URL.RequestURI(), 0, setting.AppSubURL)
+                                               middleware.SetRedirectToCookie(ctx.Resp, setting.AppSubURL+ctx.Req.URL.RequestURI())
                                        }
                                        ctx.Redirect(setting.AppSubURL + "/user/settings/change_password")
                                        return
@@ -69,7 +70,7 @@ func Toggle(options *ToggleOptions) func(ctx *Context) {
                if options.SignInRequired {
                        if !ctx.IsSigned {
                                if ctx.Req.URL.Path != "/user/events" {
-                                       ctx.SetCookie("redirect_to", setting.AppSubURL+ctx.Req.URL.RequestURI(), 0, setting.AppSubURL)
+                                       middleware.SetRedirectToCookie(ctx.Resp, setting.AppSubURL+ctx.Req.URL.RequestURI())
                                }
                                ctx.Redirect(setting.AppSubURL + "/user/login")
                                return
@@ -84,7 +85,7 @@ func Toggle(options *ToggleOptions) func(ctx *Context) {
                if !options.SignOutRequired && !ctx.IsSigned &&
                        len(ctx.GetCookie(setting.CookieUserName)) > 0 {
                        if ctx.Req.URL.Path != "/user/events" {
-                               ctx.SetCookie("redirect_to", setting.AppSubURL+ctx.Req.URL.RequestURI(), 0, setting.AppSubURL)
+                               middleware.SetRedirectToCookie(ctx.Resp, setting.AppSubURL+ctx.Req.URL.RequestURI())
                        }
                        ctx.Redirect(setting.AppSubURL + "/user/login")
                        return
index c06784c1165824cb29f54fef5682685fe16e3f5e..eecc81406d0e077673d04e19c6a39babe1623726 100644 (file)
@@ -386,9 +386,28 @@ func (ctx *Context) Redirect(location string, status ...int) {
        http.Redirect(ctx.Resp, ctx.Req, location, code)
 }
 
-// SetCookie set cookies to web browser
-func (ctx *Context) SetCookie(name string, value string, others ...interface{}) {
-       middleware.SetCookie(ctx.Resp, name, value, others...)
+// SetCookie convenience function to set most cookies consistently
+// CSRF and a few others are the exception here
+func (ctx *Context) SetCookie(name, value string, expiry int) {
+       middleware.SetCookie(ctx.Resp, name, value,
+               expiry,
+               setting.AppSubURL,
+               setting.SessionConfig.Domain,
+               setting.SessionConfig.Secure,
+               true,
+               middleware.SameSite(setting.SessionConfig.SameSite))
+}
+
+// DeleteCookie convenience function to delete most cookies consistently
+// CSRF and a few others are the exception here
+func (ctx *Context) DeleteCookie(name string) {
+       middleware.SetCookie(ctx.Resp, name, "",
+               -1,
+               setting.AppSubURL,
+               setting.SessionConfig.Domain,
+               setting.SessionConfig.Secure,
+               true,
+               middleware.SameSite(setting.SessionConfig.SameSite))
 }
 
 // GetCookie returns given cookie value from request header.
@@ -399,6 +418,11 @@ func (ctx *Context) GetCookie(name string) string {
 // GetSuperSecureCookie returns given cookie value from request header with secret string.
 func (ctx *Context) GetSuperSecureCookie(secret, name string) (string, bool) {
        val := ctx.GetCookie(name)
+       return ctx.CookieDecrypt(secret, val)
+}
+
+// CookieDecrypt returns given value from with secret string.
+func (ctx *Context) CookieDecrypt(secret, val string) (string, bool) {
        if val == "" {
                return "", false
        }
@@ -414,14 +438,21 @@ func (ctx *Context) GetSuperSecureCookie(secret, name string) (string, bool) {
 }
 
 // SetSuperSecureCookie sets given cookie value to response header with secret string.
-func (ctx *Context) SetSuperSecureCookie(secret, name, value string, others ...interface{}) {
+func (ctx *Context) SetSuperSecureCookie(secret, name, value string, expiry int) {
+       text := ctx.CookieEncrypt(secret, value)
+
+       ctx.SetCookie(name, text, expiry)
+}
+
+// CookieEncrypt encrypts a given value using the provided secret
+func (ctx *Context) CookieEncrypt(secret, value string) string {
        key := pbkdf2.Key([]byte(secret), []byte(secret), 1000, 16, sha256.New)
        text, err := com.AESGCMEncrypt(key, []byte(value))
        if err != nil {
                panic("error encrypting cookie: " + err.Error())
        }
 
-       ctx.SetCookie(name, hex.EncodeToString(text), others...)
+       return hex.EncodeToString(text)
 }
 
 // GetCookieInt returns cookie result in int type.
@@ -533,6 +564,7 @@ func getCsrfOpts() CsrfOptions {
                Header:         "X-Csrf-Token",
                CookieDomain:   setting.SessionConfig.Domain,
                CookiePath:     setting.SessionConfig.CookiePath,
+               SameSite:       setting.SessionConfig.SameSite,
        }
 }
 
@@ -597,17 +629,17 @@ func Contexter() func(next http.Handler) http.Handler {
                                                middleware.Domain(setting.SessionConfig.Domain),
                                                middleware.HTTPOnly(true),
                                                middleware.Secure(setting.SessionConfig.Secure),
-                                               //middlewares.SameSite(opt.SameSite), FIXME: we need a samesite config
+                                               middleware.SameSite(setting.SessionConfig.SameSite),
                                        )
                                        return
                                }
 
-                               ctx.SetCookie("macaron_flash", "", -1,
+                               middleware.SetCookie(ctx.Resp, "macaron_flash", "", -1,
                                        setting.SessionConfig.CookiePath,
                                        middleware.Domain(setting.SessionConfig.Domain),
                                        middleware.HTTPOnly(true),
                                        middleware.Secure(setting.SessionConfig.Secure),
-                                       //middleware.SameSite(), FIXME: we need a samesite config
+                                       middleware.SameSite(setting.SessionConfig.SameSite),
                                )
                        })
 
index 4a26664bf36b8c0cc1a4cfb705e60e08ccf7c2e2..ba0e9f6cde773d7478e4e03a4f16041d6a48db0b 100644 (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
index eb5e1a1875fa4fd65a4d239e9c4fd345ad34541b..97666c5e53da1714d44db9c30a1e94b463cb6042 100644 (file)
@@ -5,6 +5,7 @@
 package setting
 
 import (
+       "net/http"
        "path"
        "path/filepath"
        "strings"
@@ -31,10 +32,13 @@ var (
                Secure bool
                // Cookie domain name. Default is empty.
                Domain string
+               // SameSite declares if your cookie should be restricted to a first-party or same-site context. Valid strings are "none", "lax", "strict". Default is "lax"
+               SameSite http.SameSite
        }{
                CookieName:  "i_like_gitea",
                Gclifetime:  86400,
                Maxlifetime: 86400,
+               SameSite:    http.SameSiteLaxMode,
        }
 )
 
@@ -52,6 +56,15 @@ func newSessionService() {
        SessionConfig.Gclifetime = sec.Key("GC_INTERVAL_TIME").MustInt64(86400)
        SessionConfig.Maxlifetime = sec.Key("SESSION_LIFE_TIME").MustInt64(86400)
        SessionConfig.Domain = sec.Key("DOMAIN").String()
+       samesiteString := sec.Key("SAME_SITE").In("lax", []string{"none", "lax", "strict"})
+       switch strings.ToLower(samesiteString) {
+       case "none":
+               SessionConfig.SameSite = http.SameSiteNoneMode
+       case "strict":
+               SessionConfig.SameSite = http.SameSiteStrictMode
+       default:
+               SessionConfig.SameSite = http.SameSiteLaxMode
+       }
 
        json := jsoniter.ConfigCompatibleWithStandardLibrary
        shadowConfig, err := json.Marshal(SessionConfig)
index 83e365f9c48103465e86b7d10d2338ca724db950..cfcc2bbac787eafa5d4aca43543704cc2a12d4ea 100644 (file)
@@ -76,6 +76,47 @@ func NewCookie(name, value string, maxAge int) *http.Cookie {
        }
 }
 
+// SetRedirectToCookie convenience function to set the RedirectTo cookie consistently
+func SetRedirectToCookie(resp http.ResponseWriter, value string) {
+       SetCookie(resp, "redirect_to", value,
+               0,
+               setting.AppSubURL,
+               "",
+               setting.SessionConfig.Secure,
+               true,
+               SameSite(setting.SessionConfig.SameSite))
+}
+
+// DeleteRedirectToCookie convenience function to delete most cookies consistently
+func DeleteRedirectToCookie(resp http.ResponseWriter) {
+       SetCookie(resp, "redirect_to", "",
+               -1,
+               setting.AppSubURL,
+               "",
+               setting.SessionConfig.Secure,
+               true,
+               SameSite(setting.SessionConfig.SameSite))
+}
+
+// DeleteSesionConfigPathCookie convenience function to delete SessionConfigPath cookies consistently
+func DeleteSesionConfigPathCookie(resp http.ResponseWriter, name string) {
+       SetCookie(resp, name, "",
+               -1,
+               setting.SessionConfig.CookiePath,
+               setting.SessionConfig.Domain,
+               setting.SessionConfig.Secure,
+               true,
+               SameSite(setting.SessionConfig.SameSite))
+}
+
+// DeleteCSRFCookie convenience function to delete SessionConfigPath cookies consistently
+func DeleteCSRFCookie(resp http.ResponseWriter) {
+       SetCookie(resp, setting.CSRFCookieName, "",
+               -1,
+               setting.SessionConfig.CookiePath,
+               setting.SessionConfig.Domain) // FIXME: Do we need to set the Secure, httpOnly and SameSite values too?
+}
+
 // SetCookie set the cookies
 // TODO: Copied from gitea.com/macaron/macaron and should be improved after macaron removed.
 func SetCookie(resp http.ResponseWriter, name string, value string, others ...interface{}) {
index 449095f6113427ed6ff313db8001bd3bec15ef6d..a08e5aaeec7a15ef630c7d95a2f3be4c79554fa3 100644 (file)
@@ -7,6 +7,7 @@ package middleware
 import (
        "net/http"
 
+       "code.gitea.io/gitea/modules/setting"
        "code.gitea.io/gitea/modules/translation"
 
        "github.com/unknwon/i18n"
@@ -42,8 +43,30 @@ func Locale(resp http.ResponseWriter, req *http.Request) translation.Locale {
        }
 
        if changeLang {
-               SetCookie(resp, "lang", lang, 1<<31-1)
+               SetLocaleCookie(resp, lang, 1<<31-1)
        }
 
        return translation.NewLocale(lang)
 }
+
+// SetLocaleCookie convenience function to set the locale cookie consistently
+func SetLocaleCookie(resp http.ResponseWriter, lang string, expiry int) {
+       SetCookie(resp, "lang", lang, expiry,
+               setting.AppSubURL,
+               setting.SessionConfig.Domain,
+               setting.SessionConfig.Secure,
+               true,
+               SameSite(setting.SessionConfig.SameSite))
+}
+
+// DeleteLocaleCookie convenience function to delete the locale cookie consistently
+// Setting the lang cookie will trigger the middleware to reset the language ot previous state.
+func DeleteLocaleCookie(resp http.ResponseWriter) {
+       SetCookie(resp, "lang", "",
+               -1,
+               setting.AppSubURL,
+               setting.SessionConfig.Domain,
+               setting.SessionConfig.Secure,
+               true,
+               SameSite(setting.SessionConfig.SameSite))
+}
index f82ee9808b2c422c28bd07530ab6074b8c2f1d71..6505a4180df03e23852dd0fba9d4b30d23071d56 100644 (file)
@@ -17,6 +17,7 @@ import (
        "code.gitea.io/gitea/modules/setting"
        "code.gitea.io/gitea/modules/structs"
        "code.gitea.io/gitea/modules/util"
+       "code.gitea.io/gitea/modules/web/middleware"
        "code.gitea.io/gitea/routers/user"
 )
 
@@ -46,7 +47,7 @@ func Home(ctx *context.Context) {
                } else if ctx.User.MustChangePassword {
                        ctx.Data["Title"] = ctx.Tr("auth.must_change_password")
                        ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/change_password"
-                       ctx.SetCookie("redirect_to", setting.AppSubURL+ctx.Req.URL.RequestURI(), 0, setting.AppSubURL)
+                       middleware.SetRedirectToCookie(ctx.Resp, setting.AppSubURL+ctx.Req.URL.RequestURI())
                        ctx.Redirect(setting.AppSubURL + "/user/settings/change_password")
                } else {
                        user.Dashboard(ctx)
index cfe5582f2b55a750201c5ef126e9e889830f9a7e..7f01738efef6cf6b2dd52210f290a691e3109e2e 100644 (file)
@@ -424,9 +424,10 @@ func InstallPost(ctx *context.Context) {
                }
 
                days := 86400 * setting.LogInRememberDays
-               ctx.SetCookie(setting.CookieUserName, u.Name, days, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true)
+               ctx.SetCookie(setting.CookieUserName, u.Name, days)
+
                ctx.SetSuperSecureCookie(base.EncodeMD5(u.Rands+u.Passwd),
-                       setting.CookieRememberName, u.Name, days, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true)
+                       setting.CookieRememberName, u.Name, days)
 
                // Auto-login for admin
                if err = ctx.Session.Set("uid", u.ID); err != nil {
index 2d5e7bf4499fe20e51e419aae03cf5ebc3da5c10..e5e8cc1151f8374ce1c644e546d0b2e2c15a43fc 100644 (file)
@@ -24,6 +24,7 @@ import (
        "code.gitea.io/gitea/modules/setting"
        "code.gitea.io/gitea/modules/timeutil"
        "code.gitea.io/gitea/modules/web"
+       "code.gitea.io/gitea/modules/web/middleware"
        "code.gitea.io/gitea/routers/utils"
        "code.gitea.io/gitea/services/externalaccount"
        "code.gitea.io/gitea/services/mailer"
@@ -64,8 +65,8 @@ func AutoSignIn(ctx *context.Context) (bool, error) {
        defer func() {
                if !isSucceed {
                        log.Trace("auto-login cookie cleared: %s", uname)
-                       ctx.SetCookie(setting.CookieUserName, "", -1, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true)
-                       ctx.SetCookie(setting.CookieRememberName, "", -1, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true)
+                       ctx.DeleteCookie(setting.CookieUserName)
+                       ctx.DeleteCookie(setting.CookieRememberName)
                }
        }()
 
@@ -95,7 +96,7 @@ func AutoSignIn(ctx *context.Context) (bool, error) {
                return false, err
        }
 
-       ctx.SetCookie(setting.CSRFCookieName, "", -1, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true)
+       middleware.DeleteCSRFCookie(ctx.Resp)
        return true, nil
 }
 
@@ -109,13 +110,13 @@ func checkAutoLogin(ctx *context.Context) bool {
 
        redirectTo := ctx.Query("redirect_to")
        if len(redirectTo) > 0 {
-               ctx.SetCookie("redirect_to", redirectTo, 0, setting.AppSubURL, "", setting.SessionConfig.Secure, true)
+               middleware.SetRedirectToCookie(ctx.Resp, redirectTo)
        } else {
                redirectTo = ctx.GetCookie("redirect_to")
        }
 
        if isSucceed {
-               ctx.SetCookie("redirect_to", "", -1, setting.AppSubURL, "", setting.SessionConfig.Secure, true)
+               middleware.DeleteRedirectToCookie(ctx.Resp)
                ctx.RedirectToFirst(redirectTo, setting.AppSubURL+string(setting.LandingPageURL))
                return true
        }
@@ -497,9 +498,9 @@ func handleSignIn(ctx *context.Context, u *models.User, remember bool) {
 func handleSignInFull(ctx *context.Context, u *models.User, remember bool, obeyRedirect bool) string {
        if remember {
                days := 86400 * setting.LogInRememberDays
-               ctx.SetCookie(setting.CookieUserName, u.Name, days, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true)
+               ctx.SetCookie(setting.CookieUserName, u.Name, days)
                ctx.SetSuperSecureCookie(base.EncodeMD5(u.Rands+u.Passwd),
-                       setting.CookieRememberName, u.Name, days, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true)
+                       setting.CookieRememberName, u.Name, days)
        }
 
        _ = ctx.Session.Delete("openid_verified_uri")
@@ -530,10 +531,10 @@ func handleSignInFull(ctx *context.Context, u *models.User, remember bool, obeyR
                }
        }
 
-       ctx.SetCookie("lang", u.Language, nil, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true)
+       middleware.SetLocaleCookie(ctx.Resp, u.Language, 0)
 
        // Clear whatever CSRF has right now, force to generate a new one
-       ctx.SetCookie(setting.CSRFCookieName, "", -1, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true)
+       middleware.DeleteCSRFCookie(ctx.Resp)
 
        // Register last login
        u.SetLastLogin()
@@ -543,7 +544,7 @@ func handleSignInFull(ctx *context.Context, u *models.User, remember bool, obeyR
        }
 
        if redirectTo := ctx.GetCookie("redirect_to"); len(redirectTo) > 0 && !utils.IsExternalURL(redirectTo) {
-               ctx.SetCookie("redirect_to", "", -1, setting.AppSubURL, "", setting.SessionConfig.Secure, true)
+               middleware.DeleteRedirectToCookie(ctx.Resp)
                if obeyRedirect {
                        ctx.RedirectToFirst(redirectTo)
                }
@@ -649,7 +650,7 @@ func handleOAuth2SignIn(u *models.User, gothUser goth.User, ctx *context.Context
                }
 
                // Clear whatever CSRF has right now, force to generate a new one
-               ctx.SetCookie(setting.CSRFCookieName, "", -1, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true)
+               middleware.DeleteCSRFCookie(ctx.Resp)
 
                // Register last login
                u.SetLastLogin()
@@ -664,7 +665,7 @@ func handleOAuth2SignIn(u *models.User, gothUser goth.User, ctx *context.Context
                }
 
                if redirectTo := ctx.GetCookie("redirect_to"); len(redirectTo) > 0 {
-                       ctx.SetCookie("redirect_to", "", -1, setting.AppSubURL, "", setting.SessionConfig.Secure, true)
+                       middleware.DeleteRedirectToCookie(ctx.Resp)
                        ctx.RedirectToFirst(redirectTo)
                        return
                }
@@ -1042,11 +1043,11 @@ func LinkAccountPostRegister(ctx *context.Context) {
 func HandleSignOut(ctx *context.Context) {
        _ = ctx.Session.Flush()
        _ = ctx.Session.Destroy(ctx.Resp, ctx.Req)
-       ctx.SetCookie(setting.CookieUserName, "", -1, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true)
-       ctx.SetCookie(setting.CookieRememberName, "", -1, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true)
-       ctx.SetCookie(setting.CSRFCookieName, "", -1, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true)
-       ctx.SetCookie("lang", "", -1, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true) // Setting the lang cookie will trigger the middleware to reset the language ot previous state.
-       ctx.SetCookie("redirect_to", "", -1, setting.AppSubURL)                                                            // logout default should set redirect to to default
+       ctx.DeleteCookie(setting.CookieUserName)
+       ctx.DeleteCookie(setting.CookieRememberName)
+       middleware.DeleteCSRFCookie(ctx.Resp)
+       middleware.DeleteLocaleCookie(ctx.Resp)
+       middleware.DeleteRedirectToCookie(ctx.Resp)
 }
 
 // SignOut sign out from login status
@@ -1623,7 +1624,7 @@ func MustChangePasswordPost(ctx *context.Context) {
        log.Trace("User updated password: %s", u.Name)
 
        if redirectTo := ctx.GetCookie("redirect_to"); len(redirectTo) > 0 && !utils.IsExternalURL(redirectTo) {
-               ctx.SetCookie("redirect_to", "", -1, setting.AppSubURL)
+               middleware.DeleteRedirectToCookie(ctx.Resp)
                ctx.RedirectToFirst(redirectTo)
                return
        }
index e79085e94d400558c4086f2b6bb74fe3afa876ce..967e8aad2d436b599c3cfd01498bbd0201bdffaa 100644 (file)
@@ -20,6 +20,7 @@ import (
        "code.gitea.io/gitea/modules/setting"
        "code.gitea.io/gitea/modules/timeutil"
        "code.gitea.io/gitea/modules/web"
+       "code.gitea.io/gitea/modules/web/middleware"
        "code.gitea.io/gitea/services/mailer"
 )
 
@@ -47,13 +48,13 @@ func SignInOpenID(ctx *context.Context) {
 
        redirectTo := ctx.Query("redirect_to")
        if len(redirectTo) > 0 {
-               ctx.SetCookie("redirect_to", redirectTo, 0, setting.AppSubURL, "", setting.SessionConfig.Secure, true)
+               middleware.SetRedirectToCookie(ctx.Resp, redirectTo)
        } else {
                redirectTo = ctx.GetCookie("redirect_to")
        }
 
        if isSucceed {
-               ctx.SetCookie("redirect_to", "", -1, setting.AppSubURL, "", setting.SessionConfig.Secure, true)
+               middleware.DeleteRedirectToCookie(ctx.Resp)
                ctx.RedirectToFirst(redirectTo)
                return
        }
index 7e90a7ccec3cf6a224bc4b05f5074ec803b3b991..38e371196a9918794310001d4c27a3adb9cdf15f 100644 (file)
@@ -21,6 +21,7 @@ import (
        "code.gitea.io/gitea/modules/setting"
        "code.gitea.io/gitea/modules/util"
        "code.gitea.io/gitea/modules/web"
+       "code.gitea.io/gitea/modules/web/middleware"
 
        "github.com/unknwon/i18n"
 )
@@ -116,7 +117,7 @@ func ProfilePost(ctx *context.Context) {
        }
 
        // Update the language to the one we just set
-       ctx.SetCookie("lang", ctx.User.Language, nil, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true)
+       middleware.SetLocaleCookie(ctx.Resp, ctx.User.Language, 0)
 
        log.Trace("User settings updated: %s", ctx.User.Name)
        ctx.Flash.Success(i18n.Tr(ctx.User.Language, "settings.update_profile_success"))