From 929b805faea012d6fe01e0d81eedd657cad6a96b Mon Sep 17 00:00:00 2001 From: Leo Gallucci Date: Wed, 21 Oct 2020 17:57:14 +0200 Subject: [PATCH 1/3] Fix #2284 must be sent from authorization page Fix #2284 Authorization form must be sent from authorization page --- jupyterhub/apihandlers/auth.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/jupyterhub/apihandlers/auth.py b/jupyterhub/apihandlers/auth.py index b7c4df0e..5023d611 100644 --- a/jupyterhub/apihandlers/auth.py +++ b/jupyterhub/apihandlers/auth.py @@ -274,9 +274,12 @@ class OAuthAuthorizeHandler(OAuthHandler, BaseHandler): uri, http_method, body, headers = self.extract_oauth_params() referer = self.request.headers.get('Referer', 'no referer') full_url = self.request.full_url() - if referer != full_url: + stripped_referer = referer.strip('https:').strip('http:').strip('\n') + stripped_full_url = full_url.strip('https:').strip('http:').strip('\n') + if stripped_referer != stripped_full_url: # OAuth post must be made to the URL it came from - self.log.error("OAuth POST from %s != %s", referer, full_url) + self.log.error("Original OAuth POST from %s != %s", referer, full_url) + self.log.error("Stripped OAuth POST from %s != %s", stripped_referer, stripped_full_url) raise web.HTTPError( 403, "Authorization form must be sent from authorization page" ) From b9a3b0a66a7c4a5404146e4f9604a2a8eeeaf9fb Mon Sep 17 00:00:00 2001 From: Leo Gallucci Date: Thu, 22 Oct 2020 11:36:15 +0200 Subject: [PATCH 2/3] Fix #2284 must be sent from authorization pageUpdate jupyterhub/apihandlers/auth.py Co-authored-by: Min RK --- jupyterhub/apihandlers/auth.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/jupyterhub/apihandlers/auth.py b/jupyterhub/apihandlers/auth.py index 5023d611..42fb4529 100644 --- a/jupyterhub/apihandlers/auth.py +++ b/jupyterhub/apihandlers/auth.py @@ -274,8 +274,18 @@ class OAuthAuthorizeHandler(OAuthHandler, BaseHandler): uri, http_method, body, headers = self.extract_oauth_params() referer = self.request.headers.get('Referer', 'no referer') full_url = self.request.full_url() - stripped_referer = referer.strip('https:').strip('http:').strip('\n') - stripped_full_url = full_url.strip('https:').strip('http:').strip('\n') + # trim protocol, which cannot be trusted with multiple layers of proxies anyway + # Referer is set by browser, but full_url can be modified by proxy layers to appear as http + # when it is actually https + referer_proto, _, stripped_referer = referer.partition("://")[2] + referer_proto = referer_proto.lower() + req_proto, _, stripped_full_url = full_url.partition("://")[2] + req_proto = req_proto.lower() + if referer_proto != req_proto: + self.log.warning("Protocol mismatch: %s != %s", referer, full_url) + if req_proto == "https": + # insecure origin to secure target is not allowed + raise web.HTTPError(403, "Not allowing authorization form submitted from insecure page") if stripped_referer != stripped_full_url: # OAuth post must be made to the URL it came from self.log.error("Original OAuth POST from %s != %s", referer, full_url) From eaa1353dcdd17a0ebd43530e108baf197c917ae9 Mon Sep 17 00:00:00 2001 From: Min RK Date: Thu, 22 Oct 2020 11:43:24 +0200 Subject: [PATCH 3/3] typos in use of partition --- jupyterhub/apihandlers/auth.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/jupyterhub/apihandlers/auth.py b/jupyterhub/apihandlers/auth.py index 42fb4529..97c8a65c 100644 --- a/jupyterhub/apihandlers/auth.py +++ b/jupyterhub/apihandlers/auth.py @@ -277,19 +277,23 @@ class OAuthAuthorizeHandler(OAuthHandler, BaseHandler): # trim protocol, which cannot be trusted with multiple layers of proxies anyway # Referer is set by browser, but full_url can be modified by proxy layers to appear as http # when it is actually https - referer_proto, _, stripped_referer = referer.partition("://")[2] + referer_proto, _, stripped_referer = referer.partition("://") referer_proto = referer_proto.lower() - req_proto, _, stripped_full_url = full_url.partition("://")[2] + req_proto, _, stripped_full_url = full_url.partition("://") req_proto = req_proto.lower() if referer_proto != req_proto: self.log.warning("Protocol mismatch: %s != %s", referer, full_url) if req_proto == "https": # insecure origin to secure target is not allowed - raise web.HTTPError(403, "Not allowing authorization form submitted from insecure page") + raise web.HTTPError( + 403, "Not allowing authorization form submitted from insecure page" + ) if stripped_referer != stripped_full_url: # OAuth post must be made to the URL it came from self.log.error("Original OAuth POST from %s != %s", referer, full_url) - self.log.error("Stripped OAuth POST from %s != %s", stripped_referer, stripped_full_url) + self.log.error( + "Stripped OAuth POST from %s != %s", stripped_referer, stripped_full_url + ) raise web.HTTPError( 403, "Authorization form must be sent from authorization page" )