diff --git a/providers/session/session.go b/providers/session/session.go index 7cbc41a..7614144 100644 --- a/providers/session/session.go +++ b/providers/session/session.go @@ -1,5 +1,6 @@ package session +import "log" import "time" import "net/http" import "html/template" @@ -10,6 +11,7 @@ import "git.tebibyte.media/sashakoshka/go-util/container" import shttp "git.tebibyte.media/sashakoshka/step/http" const sessionIDCookieName = "step-session-id" +const secureSessionIDCookieName = "__Host-step-session-id" const defaultLifetime = 48 * time.Hour var _ step.FuncProviderFor = new(Provider) @@ -19,7 +21,8 @@ var _ step.Trimmer = new(Provider) // Provider provides session functions. type Provider struct { - Lifetime time.Duration + Lifetime time.Duration + InsecureCookie bool sessions usync.RWLocker[sessionMap] } @@ -53,6 +56,15 @@ func (this *Provider) Configure (config step.Meta) error { if err != nil { return err } this.Lifetime = lifetime } + if insecureCookieStr := config.Get("session.insecure-cookie"); insecureCookieStr != "" { + if insecureCookieStr != "true" && insecureCookieStr != "false" { + return step.ErrTypeMismatch + } + this.InsecureCookie = insecureCookieStr == "true" + if this.InsecureCookie { + log.Println("!!! session.insecure-cookie is active, this is not recommended") + } + } return nil } @@ -61,6 +73,7 @@ func (this *Provider) FuncMapFor (document *step.Document) template.FuncMap { stat := &state { document: document, sessions: &this.sessions, + insecureCookie: this.InsecureCookie, } return template.FuncMap { "sessionHTTP": stat.funcSessionHTTP, @@ -72,6 +85,7 @@ type state struct { document *step.Document sessions *usync.RWLocker[sessionMap] lifetime time.Duration + insecureCookie bool } func (this *state) funcSessionHTTP ( @@ -81,8 +95,10 @@ func (this *state) funcSessionHTTP ( *Session, error, ) { + cookieName := sessionIDCookieName + if !this.insecureCookie { cookieName = secureSessionIDCookieName } var id uuid.UUID - if cookie, err := req.Cookie(sessionIDCookieName); err == nil { + if cookie, err := req.Cookie(cookieName); err == nil { if parsed, err := uuid.Parse(cookie.Value); err == nil { id = parsed } @@ -108,14 +124,16 @@ func (this *state) funcSessionHTTP ( result = session } cookie := &http.Cookie { - Name: sessionIDCookieName, + Name: cookieName, Value: result.ID().String(), Expires: expiration, - Secure: true, - HttpOnly: true, SameSite: http.SameSiteStrictMode, Path: "/", } + if !this.insecureCookie { + cookie.Secure = true + cookie.HttpOnly = true + } underlyingRes := shttp.UnderlyingResponseWriter(res) http.SetCookie(underlyingRes, cookie) return result, nil