no cookie domain by default

This commit is contained in:
David Lord 2023-04-12 12:38:22 -07:00
parent fa0ceb62f2
commit c24f8c8199
No known key found for this signature in database
GPG key ID: 7A1C87E3F5BC42A8
5 changed files with 34 additions and 125 deletions

View file

@ -3,6 +3,7 @@ import pkgutil
import socket
import sys
import typing as t
import warnings
from datetime import datetime
from functools import lru_cache
from functools import update_wrapper
@ -662,7 +663,16 @@ def is_ip(value: str) -> bool:
:return: True if string is an IP address
:rtype: bool
.. deprecated:: 2.3
Will be removed in Flask 2.4.
"""
warnings.warn(
"The 'is_ip' function is deprecated and will be removed in Flask 2.4.",
DeprecationWarning,
stacklevel=2,
)
for family in (socket.AF_INET, socket.AF_INET6):
try:
socket.inet_pton(family, value)

View file

@ -1,6 +1,5 @@
import hashlib
import typing as t
import warnings
from collections.abc import MutableMapping
from datetime import datetime
from datetime import timezone
@ -9,7 +8,6 @@ from itsdangerous import BadSignature
from itsdangerous import URLSafeTimedSerializer
from werkzeug.datastructures import CallbackDict
from .helpers import is_ip
from .json.tag import TaggedJSONSerializer
if t.TYPE_CHECKING: # pragma: no cover
@ -181,62 +179,17 @@ class SessionInterface:
return app.config["SESSION_COOKIE_NAME"]
def get_cookie_domain(self, app: "Flask") -> t.Optional[str]:
"""Returns the domain that should be set for the session cookie.
"""The value of the ``Domain`` parameter on the session cookie. If not set,
browsers will only send the cookie to the exact domain it was set from.
Otherwise, they will send it to any subdomain of the given value as well.
Uses ``SESSION_COOKIE_DOMAIN`` if it is configured, otherwise
falls back to detecting the domain based on ``SERVER_NAME``.
Uses the :data:`SESSION_COOKIE_DOMAIN` config.
Once detected (or if not set at all), ``SESSION_COOKIE_DOMAIN`` is
updated to avoid re-running the logic.
.. versionchanged:: 2.3
Not set by default, does not fall back to ``SERVER_NAME``.
"""
rv = app.config["SESSION_COOKIE_DOMAIN"]
# set explicitly, or cached from SERVER_NAME detection
# if False, return None
if rv is not None:
return rv if rv else None
rv = app.config["SERVER_NAME"]
# server name not set, cache False to return none next time
if not rv:
app.config["SESSION_COOKIE_DOMAIN"] = False
return None
# chop off the port which is usually not supported by browsers
# remove any leading '.' since we'll add that later
rv = rv.rsplit(":", 1)[0].lstrip(".")
if "." not in rv:
# Chrome doesn't allow names without a '.'. This should only
# come up with localhost. Hack around this by not setting
# the name, and show a warning.
warnings.warn(
f"{rv!r} is not a valid cookie domain, it must contain"
" a '.'. Add an entry to your hosts file, for example"
f" '{rv}.localdomain', and use that instead."
)
app.config["SESSION_COOKIE_DOMAIN"] = False
return None
ip = is_ip(rv)
if ip:
warnings.warn(
"The session cookie domain is an IP address. This may not work"
" as intended in some browsers. Add an entry to your hosts"
' file, for example "localhost.localdomain", and use that'
" instead."
)
# if this is not an ip and app is mounted at the root, allow subdomain
# matching by adding a '.' prefix
if self.get_cookie_path(app) == "/" and not ip:
rv = f".{rv}"
app.config["SESSION_COOKIE_DOMAIN"] = rv
return rv
return rv if rv else None
def get_cookie_path(self, app: "Flask") -> str:
"""Returns the path for which the cookie should be valid. The