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>tags/v1.15.0-dev
@@ -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 | |||
@@ -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`) | |||
@@ -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) | |||
} |
@@ -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 | |||
@@ -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), | |||
) | |||
}) | |||
@@ -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 | |||
@@ -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) | |||
@@ -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{}) { | |||
@@ -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)) | |||
} |
@@ -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) | |||
@@ -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 { | |||
@@ -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 | |||
} | |||
@@ -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 | |||
} | |||
@@ -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")) | |||