Repository: expressjs/session

Issue:
Support sameSite 'auto' the same as for secureCookie
Hello I would like to set the cookie `sameSite` value to `"none"` for secure connections and to `"lax"` for http connections (As `none` requires a secure connection).

The `secure` option supports `"auto"` which will check on request, if the connection is secure and set `secure` to `true` and to `false` otherwise. I would like a similar option for `sameSite` as it would really help in my situation where I cannot determine up front if the site is served http-only, but if it IS accessed on https I really need `sameSite` to be set to `"none"` to support some SAML authentication scenarios.

The fix is rather simple. In index.js I just put in:

````javascript
  store.generate = function(req){
    req.sessionID = generateId(req);
    req.session = new Session(req);
    req.session.cookie = new Cookie(cookieOptions);

    if (cookieOptions.secure === 'auto') {
      req.session.cookie.secure = issecure(req, trustProxy);
      // support for sameSite 'auto':
      if (cookieOptions.sameSite === 'auto') {
        req.session.cookie.sameSite = req.session.cookie.secure ? 'none' : 'lax';
      }
    }
  };
````

I am just wondering if a pull request is appreciated?


Discussion:

Solution patch:
diff --git a/HISTORY.md b/HISTORY.md
index e12d0a0..60cf6db 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -2,6 +2,10 @@
 
 ### 🚀 Improvements
 
+* Add sameSite 'auto' support for automatic SameSite attribute configuration
+
+    Added `sameSite: 'auto'` option for cookie configuration that automatically sets `SameSite=None` for HTTPS and `SameSite=Lax` for HTTP connections, simplifying cookie handling across different environments.
+
 * deps: use tilde notation for dependencies
 
 1.18.2 / 2025-07-17
diff --git a/README.md b/README.md
index b880e6b..4f19ce5 100644
--- a/README.md
+++ b/README.md
@@ -130,6 +130,7 @@ By default, this is `false`.
   - `'lax'` will set the `SameSite` attribute to `Lax` for lax same site enforcement.
   - `'none'` will set the `SameSite` attribute to `None` for an explicit cross-site cookie.
   - `'strict'` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
+  - `'auto'` will set the `SameSite` attribute to `None` for secure connections and `Lax` for non-secure connections.
 
 More information about the different enforcement levels can be found in
 [the specification][rfc-6265bis-03-4.1.2.7].
@@ -141,6 +142,14 @@ the future. This also means many clients may ignore this attribute until they un
 that requires that the `Secure` attribute be set to `true` when the `SameSite` attribute has been
 set to `'none'`. Some web browsers or other clients may be adopting this specification.
 
+The `cookie.sameSite` option can also be set to the special value `'auto'` to have
+this setting automatically match the determined security of the connection. When the connection
+is secure (HTTPS), the `SameSite` attribute will be set to `None` to enable cross-site usage.
+When the connection is not secure (HTTP), the `SameSite` attribute will be set to `Lax` for
+better security while maintaining functionality. This is useful when the Express `"trust proxy"`
+setting is properly setup to simplify development vs production configuration, particularly
+for SAML authentication scenarios.
+
 ##### cookie.secure
 
 Specifies the `boolean` value for the `Secure` `Set-Cookie` attribute. When truthy,
diff --git a/index.js b/index.js
index 85a0330..1ee99eb 100644
--- a/index.js
+++ b/index.js
@@ -160,8 +160,14 @@ function session(options) {
     req.session = new Session(req);
     req.session.cookie = new Cookie(cookieOptions);
 
+    var isSecure = issecure(req, trustProxy);
+
     if (cookieOptions.secure === 'auto') {
-      req.session.cookie.secure = issecure(req, trustProxy);
+      req.session.cookie.secure = isSecure;
+    }
+
+    if (cookieOptions.sameSite === 'auto') {
+      req.session.cookie.sameSite = isSecure ? 'none' : 'lax';
     }
   };
 
diff --git a/package.json b/package.json
index 42d244b..0f7d92e 100644
--- a/package.json
+++ b/package.json
@@ -42,7 +42,7 @@
   },
   "scripts": {
     "lint": "eslint . && node ./scripts/lint-readme.js",
-    "test": "./test/support/gencert.sh && mocha --require test/support/env --check-leaks --bail --no-exit --reporter spec test/",
+    "test": "./test/support/gencert.sh && mocha --require test/support/env --check-leaks --no-exit --reporter spec test/",
     "test-ci": "nyc --reporter=lcov --reporter=text npm test",
     "test-cov": "nyc npm test",
     "version": "node scripts/version-history.js && git add HISTORY.md"



Test patch:
diff --git a/test/session.js b/test/session.js
index a7d79b7..31f4707 100644
--- a/test/session.js
+++ b/test/session.js
@@ -801,6 +801,173 @@ describe('session()', function(){
         })
       })
     })
+
+    describe('when "sameSite" set to "auto"', function () {
+      describe('basic functionality', function () {
+        before(function () {
+          function setup (req) {
+            req.secure = JSON.parse(req.headers['x-secure'])
+          }
+
+          function respond (req, res) {
+            res.end(String(req.secure))
+          }
+
+          this.server = createServer(setup, { cookie: { sameSite: 'auto' } }, respond)
+        })
+
+        it('should set SameSite=None for secure connections', function (done) {
+          request(this.server)
+          .get('/')
+          .set('X-Secure', 'true')
+          .expect(shouldSetCookieWithAttributeAndValue('connect.sid', 'SameSite', 'None'))
+          .expect(200, 'true', done)
+        })
+
+        it('should set SameSite=Lax for insecure connections', function (done) {
+          request(this.server)
+          .get('/')
+          .set('X-Secure', 'false')
+          .expect(shouldSetCookieWithAttributeAndValue('connect.sid', 'SameSite', 'Lax'))
+          .expect(200, 'false', done)
+        })
+      })
+
+      describe('with proxy settings', function () {
+        describe('when "proxy" is "true"', function () {
+          before(function () {
+            this.server = createServer({ proxy: true, cookie: { sameSite: 'auto' }})
+          })
+
+          it('should set SameSite=None when X-Forwarded-Proto is https', function (done) {
+            request(this.server)
+            .get('/')
+            .set('X-Forwarded-Proto', 'https')
+            .expect(shouldSetCookieWithAttributeAndValue('connect.sid', 'SameSite', 'None'))
+            .expect(200, done)
+          })
+
+          it('should set SameSite=Lax when X-Forwarded-Proto is http', function (done) {
+            request(this.server)
+            .get('/')
+            .set('X-Forwarded-Proto', 'http')
+            .expect(shouldSetCookieWithAttributeAndValue('connect.sid', 'SameSite', 'Lax'))
+            .expect(200, done)
+          })
+        })
+
+        describe('when "proxy" is "false"', function () {
+          before(function () {
+            this.server = createServer({ proxy: false, cookie: { sameSite: 'auto' }})
+          })
+
+          it('should set SameSite=Lax when X-Forwarded-Proto is https', function (done) {
+            request(this.server)
+            .get('/')
+            .set('X-Forwarded-Proto', 'https')
+            .expect(shouldSetCookieWithAttributeAndValue('connect.sid', 'SameSite', 'Lax'))
+            .expect(200, done)
+          })
+        })
+      })
+
+      describe('combined with secure auto', function() {
+        describe('when "secure" is "auto"', function () {
+          before(function () {
+            function setup (req) {
+              req.secure = JSON.parse(req.headers['x-secure'])
+            }
+
+            function respond (req, res) {
+              res.end(String(req.secure))
+            }
+
+            this.server = createServer(setup, { cookie: { secure: 'auto', sameSite: 'auto' } }, respond)
+          })
+
+          it('should set both Secure and SameSite=None when secure', function (done) {
+            request(this.server)
+              .get('/')
+              .set('X-Secure', 'true')
+              .expect(shouldSetCookieWithAttribute('connect.sid', 'Secure'))
+              .expect(shouldSetCookieWithAttributeAndValue('connect.sid', 'SameSite', 'None'))
+              .expect(200, 'true', done)
+          })
+
+          it('should set neither Secure nor SameSite=None when insecure', function (done) {
+            request(this.server)
+              .get('/')
+              .set('X-Secure', 'false')
+              .expect(shouldSetCookieWithoutAttribute('connect.sid', 'Secure'))
+              .expect(shouldSetCookieWithAttributeAndValue('connect.sid', 'SameSite', 'Lax'))
+              .expect(200, 'false', done)
+          })
+        })
+
+        describe('when "secure" is "false"', function () {
+          before(function () {
+            function setup (req) {
+              req.secure = JSON.parse(req.headers['x-secure'])
+            }
+
+            function respond (req, res) {
+              res.end(String(req.secure))
+            }
+
+            this.server = createServer(setup, { cookie: { secure: false, sameSite: 'auto' } }, respond)
+          })
+
+          it('should set SameSite=None without Secure when secure', function (done) {
+            request(this.server)
+              .get('/')
+              .set('X-Secure', 'true')
+              .expect(shouldSetCookieWithoutAttribute('connect.sid', 'Secure'))
+              .expect(shouldSetCookieWithAttributeAndValue('connect.sid', 'SameSite', 'None'))
+              .expect(200, 'true', done)
+          })
+
+          it('should set SameSite=Lax without Secure when insecure', function (done) {
+            request(this.server)
+              .get('/')
+              .set('X-Secure', 'false')
+              .expect(shouldSetCookieWithoutAttribute('connect.sid', 'Secure'))
+              .expect(shouldSetCookieWithAttributeAndValue('connect.sid', 'SameSite', 'Lax'))
+              .expect(200, 'false', done)
+          })
+        })
+
+        describe('when "secure" is "true"', function () {
+          before(function () {
+            function setup (req) {
+              req.secure = JSON.parse(req.headers['x-secure'])
+            }
+
+            function respond (req, res) {
+              res.end(String(req.secure))
+            }
+
+            this.server = createServer(setup, { cookie: { secure: true, sameSite: 'auto' } }, respond)
+          })
+
+          it('should set both Secure and SameSite=None when secure', function (done) {
+            request(this.server)
+              .get('/')
+              .set('X-Secure', 'true')
+              .expect(shouldSetCookieWithAttribute('connect.sid', 'Secure'))
+              .expect(shouldSetCookieWithAttributeAndValue('connect.sid', 'SameSite', 'None'))
+              .expect(200, 'true', done)
+          })
+
+          it('should not set cookie when insecure', function (done) {
+            request(this.server)
+              .get('/')
+              .set('X-Secure', 'false')
+              .expect(shouldNotHaveHeader('Set-Cookie'))
+              .expect(200, 'false', done)
+          })
+        })
+      })
+    })
   })
 
   describe('genid option', function(){