diff --git a/.travis.yml b/.travis.yml
index 7e04b10..9487d00 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -13,6 +13,7 @@ python:
   - "3.4"
   - "3.5"
   - "3.6"
+  - "3.7-dev"
 install:
     - pip install -e .[testsuite]
 script:
diff --git a/beaker/cookie.py b/beaker/cookie.py
index 8d8d0a4..729fbe3 100644
--- a/beaker/cookie.py
+++ b/beaker/cookie.py
@@ -11,6 +11,9 @@ cookie_pickles_properly = (
     sys.version_info >= (3, 4, 3)
 )
 
+# Add support for the SameSite attribute (obsolete when PY37 is unsupported).
+http_cookies.Morsel._reserved.setdefault('samesite', 'SameSite')
+
 
 # Adapted from Django.http.cookies and always enabled the bad_cookies
 # behaviour to cope with any invalid cookie key while keeping around
diff --git a/beaker/session.py b/beaker/session.py
index 442ba73..6b536d2 100644
--- a/beaker/session.py
+++ b/beaker/session.py
@@ -127,6 +127,8 @@ class Session(dict):
                                to keep backward compatibility with sessions generated before 1.8.0
                                set this to 48.
     :param crypto_type: encryption module to use
+    :param samesite: SameSite value for the cookie -- should be either 'Lax',
+                     'Strict', or None.
     """
     def __init__(self, request, id=None, invalidate_corrupt=False,
                  use_cookies=True, type=None, data_dir=None,
@@ -135,7 +137,7 @@ class Session(dict):
                  data_serializer='pickle', secret=None,
                  secure=False, namespace_class=None, httponly=False,
                  encrypt_key=None, validate_key=None, encrypt_nonce_bits=DEFAULT_NONCE_BITS,
-                 crypto_type='default',
+                 crypto_type='default', samesite='Lax',
                  **namespace_args):
         if not type:
             if data_dir:
@@ -178,6 +180,7 @@ class Session(dict):
         self.secret = secret
         self.secure = secure
         self.httponly = httponly
+        self.samesite = samesite
         self.encrypt_key = encrypt_key
         self.validate_key = validate_key
         self.encrypt_nonce_size = get_nonce_size(encrypt_nonce_bits)
@@ -246,6 +249,8 @@ class Session(dict):
             self.cookie[self.key]['domain'] = self._domain
         if self.secure:
             self.cookie[self.key]['secure'] = True
+        if self.samesite:
+            self.cookie[self.key]['samesite'] = self.samesite
         self._set_cookie_http_only()
         self.cookie[self.key]['path'] = self._path
 
@@ -556,13 +561,15 @@ class CookieSession(Session):
                                otherwise invalid data will cause an exception.
     :type invalidate_corrupt: bool
     :param crypto_type: The crypto module to use.
+    :param samesite: SameSite value for the cookie -- should be either 'Lax',
+                     'Strict', or None.
     """
     def __init__(self, request, key='beaker.session.id', timeout=None,
                  save_accessed_time=True, cookie_expires=True, cookie_domain=None,
                  cookie_path='/', encrypt_key=None, validate_key=None, secure=False,
                  httponly=False, data_serializer='pickle',
                  encrypt_nonce_bits=DEFAULT_NONCE_BITS, invalidate_corrupt=False,
-                 crypto_type='default',
+                 crypto_type='default', samesite='Lax',
                  **kwargs):
 
         self.crypto_module = get_crypto_module(crypto_type)
@@ -582,6 +589,7 @@ class CookieSession(Session):
         self.request['set_cookie'] = False
         self.secure = secure
         self.httponly = httponly
+        self.samesite = samesite
         self._domain = cookie_domain
         self._path = cookie_path
         self.invalidate_corrupt = invalidate_corrupt

Set SameSite option on session cookies
Documented here: https://blog.mozilla.org/security/2018/04/24/same-site-cookies-in-firefox-60/

Currently supported in Firefox and Chromium; it provides strong defense in depth against CSRF.
diff --git a/tests/test_cookie_domain_only.py b/tests/test_cookie_domain_only.py
index 4eef4dc..800da7f 100644
--- a/tests/test_cookie_domain_only.py
+++ b/tests/test_cookie_domain_only.py
@@ -61,6 +61,7 @@ def test_cookie_attributes_are_preserved():
     assert 'path=/app' in cookie.lower()
     assert 'secure' in cookie.lower()
     assert 'httponly' in cookie.lower()
+    assert 'samesite=lax' in cookie.lower()
 
 
 if __name__ == '__main__':

pip install -e .[testsuite]
parse_log_pytest
pytest
pytest
3.6
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
async-timeout==4.0.2
attrs @ file:///opt/conda/conda-bld/attrs_1642510447205/work
-e git+https://github.com/bbangert/beaker.git@c8f0a599f44d313b68a49c7a503ecbbec4286771#egg=Beaker
beautifulsoup4==4.12.3
certifi==2021.5.30
cffi==1.15.1
coverage==6.2
cryptography==40.0.2
greenlet==2.0.2
importlib-metadata @ file:///tmp/build/80754af9/importlib-metadata_1631916693255/work
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
mock==5.2.0
more-itertools @ file:///tmp/build/80754af9/more-itertools_1637733554872/work
nose==1.3.7
packaging @ file:///tmp/build/80754af9/packaging_1637314298585/work
pluggy @ file:///tmp/build/80754af9/pluggy_1615976315926/work
py @ file:///opt/conda/conda-bld/py_1644396412707/work
pycparser==2.21
pycryptodome==3.21.0
pymongo==4.1.1
pyparsing @ file:///tmp/build/80754af9/pyparsing_1635766073266/work
pytest==6.2.4
redis==4.3.6
soupsieve==2.3.2.post1
SQLAlchemy==1.4.54
toml @ file:///tmp/build/80754af9/toml_1616166611790/work
typing_extensions @ file:///opt/conda/conda-bld/typing_extensions_1647553014482/work
waitress==2.0.0
WebOb==1.8.9
WebTest==3.0.0
zipp @ file:///tmp/build/80754af9/zipp_1633618647012/work

name: beaker
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - attrs=21.4.0=pyhd3eb1b0_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - importlib-metadata=4.8.1=py36h06a4308_0
  - importlib_metadata=4.8.1=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - more-itertools=8.12.0=pyhd3eb1b0_0
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - packaging=21.3=pyhd3eb1b0_0
  - pip=21.2.2=py36h06a4308_0
  - pluggy=0.13.1=py36h06a4308_0
  - py=1.11.0=pyhd3eb1b0_0
  - pyparsing=3.0.4=pyhd3eb1b0_0
  - pytest=6.2.4=py36h06a4308_2
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - toml=0.10.2=pyhd3eb1b0_0
  - typing_extensions=4.1.1=pyh06a4308_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.6.0=pyhd3eb1b0_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - async-timeout==4.0.2
      - beautifulsoup4==4.12.3
      - cffi==1.15.1
      - coverage==6.2
      - cryptography==40.0.2
      - greenlet==2.0.2
      - mock==5.2.0
      - nose==1.3.7
      - pycparser==2.21
      - pycryptodome==3.21.0
      - pymongo==4.1.1
      - redis==4.3.6
      - soupsieve==2.3.2.post1
      - sqlalchemy==1.4.54
      - waitress==2.0.0
      - webob==1.8.9
      - webtest==3.0.0
prefix: /opt/conda/envs/beaker

tests/test_cookie_domain_only.py::test_cookie_attributes_are_preserved
tests/test_cookie_domain_only.py::test_increment
beaker/cookie.py .travis.yml beaker/session.py
beaker/cookie.py .travis.yml beaker/session.py