Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New toolbar cookie + Secure session/csrf cookies #1387

Merged
merged 15 commits into from
Aug 11, 2020
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ jobs:
REDIS_URL: 'redis://localhost'
DATABASE_URL: 'postgres://postgres:postgres@localhost:${{ job.services.postgres.ports[5432] }}/postgres'
DISABLE_SECURE_SSL_REDIRECT: 1
SECURE_COOKIES: 0
OPT_OUT_CAPTURE: 1
run: |
python manage.py collectstatic --noinput
Expand Down
2 changes: 1 addition & 1 deletion bin/start-https
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ set -e
trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT

export IS_BEHIND_PROXY=1
export LOCAL_HTTPS=1
export DISABLE_SECURE_SSL_REDIRECT=1
./bin/start-worker &
./bin/start-backend &
./bin/start-frontend-https &
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
"kea-router": "^0.4.0",
"kea-window-values": "^0.0.1",
"moment": "^2.24.0",
"posthog-js": "1.3.8",
"posthog-js-lite": "^0.0.1",
"posthog-js": "1.4.1",
"posthog-js-lite": "^0.0.3",
"prop-types": "^15.7.2",
"react": ">= 16.8",
"react-datepicker": "^2.13.0",
Expand Down
5 changes: 5 additions & 0 deletions posthog/api/decide.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ def get_decide(request: HttpRequest):
"supportedCompression": ["gzip", "lz64"],
}

if request.COOKIES.get(settings.TOOLBAR_COOKIE_NAME):
response["isAuthenticated"] = True
if settings.JS_URL:
response["editorParams"] = {"jsURL": settings.JS_URL, "toolbarVersion": "toolbar"}

if request.user.is_authenticated:
team = request.user.team_set.get()
permitted_domains = ["127.0.0.1", "localhost"]
Expand Down
3 changes: 1 addition & 2 deletions posthog/api/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,10 @@ def redirect_to_site(request):
request.user.temporary_token = secrets.token_urlsafe(32)
request.user.save()
params = {
"action": "mpeditor",
"action": "ph_authorize",
"token": team.api_token,
"temporaryToken": request.user.temporary_token,
"actionId": request.GET.get("actionId"),
"apiURL": request.build_absolute_uri("/"),
"userIntent": request.GET.get("userIntent"),
}

Expand Down
33 changes: 33 additions & 0 deletions posthog/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,36 @@ def __call__(self, request: HttpRequest):
return HttpResponse(
"Your IP is not allowed. Check your ALLOWED_IP_BLOCKS settings. If you are behind a proxy, you need to set TRUSTED_PROXIES. See https://posthog.com/docs/deployment/running-behind-proxy"
)


class ToolbarCookieMiddleware(SessionMiddleware):
mariusandra marked this conversation as resolved.
Show resolved Hide resolved
def process_response(self, request, response):
response = super(ToolbarCookieMiddleware, self).process_response(request, response)

# skip adding the toolbar 3rd party cookie on API requests
if request.path.startswith("/api/") or request.path.startswith("/e/") or request.path.startswith("/decide/"):
return response

toolbar_cookie_name = settings.TOOLBAR_COOKIE_NAME # type: str
toolbar_cookie_secure = settings.TOOLBAR_COOKIE_SECURE # type: bool

if (
toolbar_cookie_name not in response.cookies
and request.user
and request.user.is_authenticated
and request.user.toolbar_mode == "toolbar"
):
response.set_cookie(
toolbar_cookie_name, # key
"yes", # value
365 * 24 * 60 * 60, # max_age = one year
None, # expires
"/", # path
None, # domain
toolbar_cookie_secure, # secure
True, # httponly
"Lax", # samesite, can't be set to "None" here :(
)
response.cookies[toolbar_cookie_name]["samesite"] = "None" # must set explicitly

return response
34 changes: 26 additions & 8 deletions posthog/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,23 +66,31 @@ def print_warning(warning_lines: Sequence[str]):
else:
JS_URL = os.environ.get("JS_URL", "")

SECURE_SSL_REDIRECT = False
# This is set as a cross-domain cookie with a random value.
# Its existence is used by the toolbar to see that we are logged in.
TOOLBAR_COOKIE_NAME = "phtoolbar"

# SSL & cookie defaults
if os.environ.get("SECURE_COOKIES", None) is None:
# Default to True if in production
secure_cookies = not DEBUG and not TEST
else:
secure_cookies = get_bool_from_env("SECURE_COOKIES", True)

TOOLBAR_COOKIE_SECURE = secure_cookies
SESSION_COOKIE_SECURE = secure_cookies
CSRF_COOKIE_SECURE = secure_cookies
SECURE_SSL_REDIRECT = secure_cookies

# production mode
if not DEBUG and not TEST:
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
if os.environ.get("SENTRY_DSN"):
sentry_sdk.init(
dsn=os.environ["SENTRY_DSN"], integrations=[DjangoIntegration()], request_bodies="always",
)

if get_bool_from_env("LOCAL_HTTPS", False):
SECURE_SSL_REDIRECT = False
SESSION_COOKIE_SECURE = True

if get_bool_from_env("DISABLE_SECURE_SSL_REDIRECT", False):
SECURE_SSL_REDIRECT = False
SESSION_COOKIE_SECURE = False
mariusandra marked this conversation as resolved.
Show resolved Hide resolved

if get_bool_from_env("IS_BEHIND_PROXY", False):
USE_X_FORWARDED_HOST = True
Expand Down Expand Up @@ -133,6 +141,7 @@ def print_warning(warning_lines: Sequence[str]):
"django.middleware.security.SecurityMiddleware",
"posthog.middleware.AllowIP",
"django.contrib.sessions.middleware.SessionMiddleware",
"posthog.middleware.ToolbarCookieMiddleware",
"corsheaders.middleware.CorsMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
Expand Down Expand Up @@ -351,3 +360,12 @@ def print_warning(warning_lines: Sequence[str]):
"Be sure to unset DEBUG if this is supposed to be a PRODUCTION environment!",
)
)


def show_toolbar(request):
return request.path.startswith("/api/") or request.path.startswith("/decide/") or request.path.startswith("/e/")


DEBUG_TOOLBAR_CONFIG = {
"SHOW_TOOLBAR_CALLBACK": "posthog.settings.show_toolbar",
}
6 changes: 2 additions & 4 deletions posthog/templates/demo.html
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
<html>
<head>
<title>HogFlix</title>

<script src="{{request.scheme}}://{{request.get_host}}/static/array.js"></script>
<script src="/static/array.js"></script>
<script>
posthog.init('{{api_token}}', {
api_host: '{{request.scheme}}://{{request.get_host}}',
app_host: '{{request.scheme}}://{{request.get_host}}',
api_host: window.location.protocol + '//' + window.location.hostname,
});
</script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous" />
Expand Down
5 changes: 4 additions & 1 deletion posthog/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,10 @@ def logout(request):
request.user.temporary_token = None
request.user.save()

return auth_views.logout_then_login(request)
response = auth_views.logout_then_login(request)
response.delete_cookie(settings.TOOLBAR_COOKIE_NAME, "/")

return response


def authorize_and_redirect(request):
Expand Down
22 changes: 11 additions & 11 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6121,9 +6121,9 @@ kea-window-values@^0.0.1:
integrity sha512-60SfOqHrmnCC8hSD2LALMJemYcohQ8tGcTHlA5u4rQy0l0wFFE4gqH1WbKd+73j9m4f6zdoOk07rwJf+P8maiQ==

kea@^2.2.0-beta.5:
version "2.2.0-beta.5"
resolved "https://registry.yarnpkg.com/kea/-/kea-2.2.0-beta.5.tgz#eafcb561cc8fcd70f0958dc691068cbee8ca6312"
integrity sha512-Y/djOgBMdKhcSKE9GG75LfrAi5cYRnzh/6OBi4C8RKeAnsgpWY7q57A+M6Gwqwz3BrhNy0xDr9ESz8Ij0W0oaQ==
version "2.2.0-rc.2"
resolved "https://registry.yarnpkg.com/kea/-/kea-2.2.0-rc.2.tgz#1c04110dca4b4c475fb0b0f40a5bfbe609058d40"
integrity sha512-N1ytphLYPeUmrqpal78mdZextJkO2Gzj8LQI3bahM/NagYSX8biAYS6FhJeGJfaySChkBf2zbL2hvfrScKap3A==

keyv@^3.0.0:
version "3.1.0"
Expand Down Expand Up @@ -7806,15 +7806,15 @@ postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.23, postcss@^7.0.26, postcss@^7.0
source-map "^0.6.1"
supports-color "^6.1.0"

posthog-js-lite@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/posthog-js-lite/-/posthog-js-lite-0.0.1.tgz#e32eebc8e5203947bc90bc794615627d7ffe7d28"
integrity sha512-CUfSRT/kjKLhGz23iS1YznFNYG/hkwESGzqAae6oFY2ncIXUppTeYvsQ/SM7QTajQEIHP6uUzjgDeaTQum7VWw==
posthog-js-lite@^0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/posthog-js-lite/-/posthog-js-lite-0.0.3.tgz#87e373706227a849c4e7c6b0cb2066a64ad5b6ed"
integrity sha512-wEOs8DEjlFBwgd7l19grosaF7mTlliZ9G9pL0Qji189FDg2ukY5IegUxTyTs7gsTGt6WK9W47BF5yXA5+bwvZg==

posthog-js@1.3.8:
version "1.3.8"
resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.3.8.tgz#796c8b3c488ebabd5a0325b283e3bf7e2a56d286"
integrity sha512-XmdSKnHX7RvpUE5h71gkdiLbe5MHhOwXu9NgpnkaNLmF/JZn+jq2pEGPiTMJsGsTNHYTKPRa4F0dztZYjS4oEQ==
posthog-js@1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.4.1.tgz#c1bfa740720503c36a0666a04d433315d7f34bb3"
integrity sha512-8awo5wsBw4cPBCHc5klXo0z09ZQj0bpwAmKsYtr7c4irVC8lF/hPvLX65oSvTXLicB+ULZlmiJtXUau5pLD2fA==

prelude-ls@^1.2.1:
version "1.2.1"
Expand Down