use one-time token for opening browser

first connection consumes the token, so command-line snoops can’t re-use it.
This commit is contained in:
Min RK 2016-10-17 14:26:43 +02:00
parent 3ba68d8cb7
commit cd3c6c1b8a
2 changed files with 26 additions and 5 deletions

View File

@ -98,7 +98,8 @@ class LoginHandler(IPythonHandler):
"""
# Can't call this get_current_user because it will collide when
# called on LoginHandler itself.
if getattr(handler, '_user_id', None):
return handler._user_id
user_id = handler.get_secure_cookie(handler.cookie_name)
if not user_id:
# prevent extra Invalid cookie sig warnings:
@ -111,11 +112,20 @@ class LoginHandler(IPythonHandler):
if login_token:
# check login token
user_token = handler.get_argument('token', '')
one_time_token = handler.settings.get('one_time_token', None)
if user_token == login_token:
# token-authenticated, set the login cookie
user_id = uuid.uuid4().hex
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
handler.settings.pop('one_time_token', None)
handler.log.info("Accepting one-time-token-authenticated connection from %s", handler.request.remote_ip)
user_id = uuid.uuid4().hex
cls.set_login_cookie(handler, user_id)
# cache value for future retrievals on the same request
handler._user_id = user_id
return user_id

View File

@ -585,6 +585,13 @@ class NotebookApp(JupyterApp):
"""
).tag(config=True)
one_time_token = Unicode(
help="""One-time token used for opening a browser.
Once used, this token cannot be used again.
"""
)
@default('login_token')
def _login_token_default(self):
if self.password:
@ -1015,6 +1022,10 @@ class NotebookApp(JupyterApp):
self.tornado_settings['allow_credentials'] = self.allow_credentials
self.tornado_settings['cookie_options'] = self.cookie_options
self.tornado_settings['login_token'] = self.login_token
if (self.open_browser or self.file_to_run) and not self.password:
self.one_time_token = binascii.hexlify(os.urandom(24)).decode('ascii')
self.tornado_settings['one_time_token'] = self.one_time_token
# ensure default_url starts with base_url
if not self.default_url.startswith(self.base_url):
self.default_url = url_path_join(self.base_url, self.default_url)
@ -1302,8 +1313,8 @@ class NotebookApp(JupyterApp):
else:
# default_url contains base_url, but so does connection_url
uri = self.default_url[len(self.base_url):]
if self.login_token:
uri = url_concat(uri, {'token': self.login_token})
if self.one_time_token:
uri = url_concat(uri, {'token': self.one_time_token})
if browser:
b = lambda : browser.open(url_path_join(self.connection_url, uri),
new=2)
@ -1322,7 +1333,7 @@ class NotebookApp(JupyterApp):
finally:
self.remove_server_info_file()
self.cleanup_kernels()
def stop(self):
def _stop():
self.http_server.stop()