Merge pull request #1938 from minrk/no-check-origin-token

don't check origin on token-authenticated requests
Kyle Kelley 9 years ago committed by GitHub
commit af3bdb333c

@ -114,6 +114,18 @@ class LoginHandler(IPythonHandler):
user_token = m.group(1)
return user_token
@classmethod
def should_check_origin(cls, handler):
"""Should the Handler check for CORS origin validation?
Origin check should be skipped for token-authenticated requests.
"""
if getattr(handler, '_user_id', None) is None:
# ensure get_user has been called, so we know if we're token-authenticated
handler.get_current_user()
token_authenticated = getattr(handler, '_token_authenticated', False)
return not token_authenticated
@classmethod
def get_user(cls, handler):
"""Called by handlers.get_current_user for identifying the current user.
@ -137,17 +149,23 @@ class LoginHandler(IPythonHandler):
# check login token from URL argument or Authorization header
user_token = cls.get_user_token(handler)
one_time_token = handler.one_time_token
authenticated = False
if user_token == token:
# token-authenticated, set the login cookie
handler.log.info("Accepting token-authenticated connection from %s", handler.request.remote_ip)
user_id = uuid.uuid4().hex
cls.set_login_cookie(handler, user_id)
if one_time_token and user_token == one_time_token:
# one-time token-authenticated, only allow this token once
authenticated = True
elif one_time_token and user_token == one_time_token:
# one-time-token-authenticated, only allow this token once
handler.settings.pop('one_time_token', None)
handler.log.info("Accepting one-time-token-authenticated connection from %s", handler.request.remote_ip)
authenticated = True
if authenticated:
user_id = uuid.uuid4().hex
cls.set_login_cookie(handler, user_id)
# Record that we've been authenticated with a token.
# Used in should_check_origin above.
handler._token_authenticated = True
# cache value for future retrievals on the same request
handler._user_id = user_id
return user_id

@ -79,6 +79,16 @@ class AuthenticatedHandler(web.RequestHandler):
return 'anonymous'
return self.login_handler.get_user(self)
def skip_check_origin(self):
"""Ask my login_handler if I should skip the origin_check
For example: in the default LoginHandler, if a request is token-authenticated,
origin checking should be skipped.
"""
if self.login_handler is None or not hasattr(self.login_handler, 'should_check_origin'):
return False
return not self.login_handler.should_check_origin(self)
@property
def cookie_name(self):
default_cookie_name = non_alphanum.sub('-', 'username-{}'.format(
@ -267,8 +277,9 @@ class IPythonHandler(AuthenticatedHandler):
Copied from WebSocket with changes:
- allow unspecified host/origin (e.g. scripts)
- allow token-authenticated requests
"""
if self.allow_origin == '*':
if self.allow_origin == '*' or self.skip_check_origin():
return True
host = self.request.headers.get("Host")
@ -295,8 +306,8 @@ class IPythonHandler(AuthenticatedHandler):
# No CORS headers deny the request
allow = False
if not allow:
self.log.warning("Blocking Cross Origin API request. Origin: %s, Host: %s",
origin, host,
self.log.warning("Blocking Cross Origin API request for %s. Origin: %s, Host: %s",
self.request.path, origin, host,
)
return allow

@ -126,7 +126,9 @@ class WebSocketMixin(object):
Tornado >= 4 calls this method automatically, raising 403 if it returns False.
"""
if self.allow_origin == '*':
if self.allow_origin == '*' or (
hasattr(self, 'skip_check_origin') and self.skip_check_origin()):
return True
host = self.request.headers.get("Host")

@ -3,18 +3,22 @@
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
from tornado import gen, web
from tornado import web
from ...base.handlers import APIHandler, json_errors
from . import csp_report_uri
class CSPReportHandler(APIHandler):
'''Accepts a content security policy violation report'''
def skip_origin_check(self):
"""Don't check origin when reporting origin-check violations!"""
return True
@json_errors
@web.authenticated
def post(self):
'''Log a content security policy violation report'''
csp_report = self.get_json_body()
self.log.warning("Content security violation: %s",
self.request.body.decode('utf8', 'replace'))

Loading…
Cancel
Save