33from urllib .parse import urlparse
44
55from jupyterhub import __version__ as __jh_version__
6- from jupyterhub .services .auth import HubOAuthCallbackHandler
6+ from jupyterhub .services .auth import HubOAuthCallbackHandler , HubOAuthenticated
77from jupyterhub .utils import make_ssl_context
88from tornado import httpclient
9- from tornado .web import Application , RedirectHandler , RequestHandler
9+ from tornado .web import Application , RedirectHandler
1010from tornado .websocket import WebSocketHandler
1111
12- from ..handlers import SuperviseAndProxyHandler
12+ from ..handlers import ProxyHandler , SuperviseAndProxyHandler
1313
1414
1515def configure_http_client ():
@@ -24,19 +24,18 @@ def configure_http_client():
2424 httpclient .AsyncHTTPClient .configure (None , defaults = {"ssl_options" : ssl_context })
2525
2626
27- class StandaloneHubProxyHandler (SuperviseAndProxyHandler ):
27+ class StandaloneProxyHandler (SuperviseAndProxyHandler ):
28+ """
29+ Base class for standalone proxies. Will not ensure any authentication!
30+ """
31+
2832 def __init__ (self , * args , ** kwargs ):
2933 super ().__init__ (* args , ** kwargs )
30- self .authtype = "oauth"
3134 self .environment = {}
3235 self .timeout = 60
3336
3437 def prepare (self , * args , ** kwargs ):
35- # ToDo: Automatically disable if not spawned by JupyterHub
36- if self .authtype == "oauth" :
37- return super ().prepare (* args , ** kwargs )
38- else :
39- pass
38+ pass
4039
4140 def check_origin (self , origin : str = None ):
4241 # Skip JupyterHandler.check_origin
@@ -49,38 +48,70 @@ def get_timeout(self):
4948 return self .timeout
5049
5150
52- def _make_native_proxy_handler (command , port , mappath , authtype , environment , timeout ):
51+ class StandaloneHubProxyHandler (StandaloneProxyHandler , HubOAuthenticated ):
52+ """
53+ Standalone Proxy used when spawned by a JupyterHub.
54+ Will restrict access to the application by authentication with the JupyterHub API.
55+ """
56+
57+ @property
58+ def hub_users (self ):
59+ return {self .settings ["user" ]}
60+
61+ @property
62+ def hub_groups (self ):
63+ if self .settings ["group" ]:
64+ return {self .settings ["group" ]}
65+ return set ()
66+
67+ @property
68+ def allow_all (self ):
69+ if "anyone" in self .settings :
70+ return self .settings ["anyone" ] == "1"
71+ return super ().allow_all
72+
73+ def prepare (self , * args , ** kwargs ):
74+ # Enable Authentication Check
75+ return ProxyHandler .prepare (self , * args , ** kwargs )
76+
77+ def set_default_headers (self ):
78+ self .set_header ("X-JupyterHub-Version" , __jh_version__ )
79+
80+
81+ def _make_native_proxy_handler (
82+ command , port , mappath , overwrite_authentication , environment , timeout
83+ ):
5384 """
5485 Create a StandaloneHubProxyHandler subclass with given parameters
5586 """
5687
57- class _Proxy (StandaloneHubProxyHandler ):
88+ # Try to determine if we are launched by a JupyterHub via environment variables.
89+ # See jupyterhub/spawner.py#L1035
90+ if overwrite_authentication is not None :
91+ base = (
92+ StandaloneHubProxyHandler
93+ if overwrite_authentication is True
94+ else StandaloneProxyHandler
95+ )
96+ elif "JUPYTERHUB_API_TOKEN" in os .environ and "JUPYTERHUB_API_URL" in os .environ :
97+ base = StandaloneHubProxyHandler
98+ else :
99+ base = StandaloneProxyHandler
100+
101+ class _Proxy (base ):
58102 def __init__ (self , * args , ** kwargs ):
59103 super ().__init__ (* args , ** kwargs )
60104 self .name = command [0 ]
61105 self .proxy_base = command [0 ]
62106 self .requested_port = port
63107 self .mappath = mappath
64108 self .command = command
65- self .authtype = authtype
66109 self .environment = environment
67110 self .timeout = timeout
68111
69112 return _Proxy
70113
71114
72- def patch_default_headers ():
73- if hasattr (RequestHandler , "_orig_set_default_headers" ):
74- return
75- RequestHandler ._orig_set_default_headers = RequestHandler .set_default_headers
76-
77- def set_jupyterhub_header (self ):
78- self ._orig_set_default_headers ()
79- self .set_header ("X-JupyterHub-Version" , __jh_version__ )
80-
81- RequestHandler .set_default_headers = set_jupyterhub_header
82-
83-
84115def make_app (
85116 destport ,
86117 prefix ,
@@ -92,8 +123,6 @@ def make_app(
92123 progressive ,
93124 websocket_max_message_size ,
94125):
95- patch_default_headers ()
96-
97126 # ToDo: Environment
98127 proxy_handler = _make_native_proxy_handler (
99128 command , destport , {}, authtype , {}, timeout
0 commit comments