From 31c0788bd964fff6178e4a88e7e1f955071a0407 Mon Sep 17 00:00:00 2001 From: "Bruno P. Kinoshita" Date: Wed, 19 Feb 2020 12:56:02 +1300 Subject: [PATCH 1/4] Move cookies to the end of the list (ssl, proxy, and then cookies) --- .../getting-started/security-basics.rst | 77 +++++++++---------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/docs/source/getting-started/security-basics.rst b/docs/source/getting-started/security-basics.rst index 80996555..7661cfd1 100644 --- a/docs/source/getting-started/security-basics.rst +++ b/docs/source/getting-started/security-basics.rst @@ -80,6 +80,44 @@ To achieve this, simply omit the configuration settings ``c.JupyterHub.ssl_key`` and ``c.JupyterHub.ssl_cert`` (setting them to ``None`` does not have the same effect, and is an error). +.. _authentication-token: + +Proxy authentication token +-------------------------- + +The Hub authenticates its requests to the Proxy using a secret token that +the Hub and Proxy agree upon. The value of this string should be a random +string (for example, generated by ``openssl rand -hex 32``). + +Generating and storing token in the configuration file +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Or you can set the value in the configuration file, ``jupyterhub_config.py``: + +.. code-block:: python + + c.JupyterHub.proxy_auth_token = '0bc02bede919e99a26de1e2a7a5aadfaf6228de836ec39a05a6c6942831d8fe5' + +Generating and storing as an environment variable +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can pass this value of the proxy authentication token to the Hub and Proxy +using the ``CONFIGPROXY_AUTH_TOKEN`` environment variable: + +.. code-block:: bash + + export CONFIGPROXY_AUTH_TOKEN=$(openssl rand -hex 32) + +This environment variable needs to be visible to the Hub and Proxy. + +Default if token is not set +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you don't set the Proxy authentication token, the Hub will generate a random +key itself, which means that any time you restart the Hub you **must also +restart the Proxy**. If the proxy is a subprocess of the Hub, this should happen +automatically (this is the default configuration). + .. _cookie-secret: Cookie secret @@ -145,42 +183,3 @@ itself, ``jupyterhub_config.py``, as a binary string: If the cookie secret value changes for the Hub, all single-user notebook servers must also be restarted. - - -.. _authentication-token: - -Proxy authentication token --------------------------- - -The Hub authenticates its requests to the Proxy using a secret token that -the Hub and Proxy agree upon. The value of this string should be a random -string (for example, generated by ``openssl rand -hex 32``). - -Generating and storing token in the configuration file -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Or you can set the value in the configuration file, ``jupyterhub_config.py``: - -.. code-block:: python - - c.JupyterHub.proxy_auth_token = '0bc02bede919e99a26de1e2a7a5aadfaf6228de836ec39a05a6c6942831d8fe5' - -Generating and storing as an environment variable -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can pass this value of the proxy authentication token to the Hub and Proxy -using the ``CONFIGPROXY_AUTH_TOKEN`` environment variable: - -.. code-block:: bash - - export CONFIGPROXY_AUTH_TOKEN=$(openssl rand -hex 32) - -This environment variable needs to be visible to the Hub and Proxy. - -Default if token is not set -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you don't set the Proxy authentication token, the Hub will generate a random -key itself, which means that any time you restart the Hub you **must also -restart the Proxy**. If the proxy is a subprocess of the Hub, this should happen -automatically (this is the default configuration). From 287b0302d9e6677a826727c973f39e66ea5bc6d5 Mon Sep 17 00:00:00 2001 From: "Bruno P. Kinoshita" Date: Wed, 19 Feb 2020 13:46:45 +1300 Subject: [PATCH 2/4] Add more docs about authentication and cookies, using text posted by MinRK on Discourse --- .../getting-started/security-basics.rst | 71 ++++++++++++++++++- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/docs/source/getting-started/security-basics.rst b/docs/source/getting-started/security-basics.rst index 7661cfd1..6704e7ce 100644 --- a/docs/source/getting-started/security-basics.rst +++ b/docs/source/getting-started/security-basics.rst @@ -86,7 +86,7 @@ Proxy authentication token -------------------------- The Hub authenticates its requests to the Proxy using a secret token that -the Hub and Proxy agree upon. The value of this string should be a random +the Hub and Proxy agree upon. The value of this token should be a random string (for example, generated by ``openssl rand -hex 32``). Generating and storing token in the configuration file @@ -96,7 +96,7 @@ Or you can set the value in the configuration file, ``jupyterhub_config.py``: .. code-block:: python - c.JupyterHub.proxy_auth_token = '0bc02bede919e99a26de1e2a7a5aadfaf6228de836ec39a05a6c6942831d8fe5' + c.ConfigurableHTTPProxy.api_token = 'abc123...' # any random string Generating and storing as an environment variable ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -183,3 +183,70 @@ itself, ``jupyterhub_config.py``, as a binary string: If the cookie secret value changes for the Hub, all single-user notebook servers must also be restarted. + +.. _cookies: + +Cookies used by JupyterHub authentication +----------------------------------------- + +The following cookies are used by the Hub for handling user authentication. + +jupyterhub-hub-login +~~~~~~~~~~~~~~~~~~~~ + +This is the login token used when visiting Hub-served pages encrypted such +as the main home, the spawn form, etc. If this cookie is set, then the +user is logged in. + +Resetting the Hub cookie secret effectively revokes this cookie. + +This cookie is restricted to the path ``/hub/``. + +jupyterhub-user- +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is the cookie used for authenticating with a single-user server +encrypted. It is set by the single-user server after OAuth with the Hub. + +Effectively the same as ``jupyterhub-hub-login``, but for the +single-user server instead of the Hub. It contains an OAuth access token, +which is checked with the Hub to authenticate the browser. + +Each OAuth access token is associated with a session id (see ``jupyterhub-session-id`` section +below). + +To avoid hitting the Hub on every request, the authentication response +is cached. And to avoid a stale cache the cache key is comprised of both +the token and session id. + +Resetting the Hub cookie secret effectively revokes this cookie. + +This cookie is restricted to the path ``/user/``, so that +only the user’s server receives it. + +jupyterhub-session-id +~~~~~~~~~~~~~~~~~~~~~ + +This is a random string, meaningless in itself, and the only cookie +shared by the Hub and single-user servers. + +Its sole purpose is to to coordinate logout of the multiple OAuth cookies. + +This cookie is set to ``/`` so all endpoints can receive it, or clear it, etc. + +jupyterhub-user--oauth-state +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A short-lived cookie, used solely to store and validate OAuth state. +It is only set while OAuth between the single-user server and the Hub +is processing. + +If you use your browser development tools, you should see this cookie +for a very brief moment before your are logged in, +with an expiration date shorter than ``jupyterhub-hub-login`` or +``jupyterhub-user-``. + +This cookie should not exist after you have successfully logged in. + +This cookie is restricted to the path ``/user/``, so that only +the user’s server receives it. From f5bd5b7751f87dd0ac229be8db909f199cd39a09 Mon Sep 17 00:00:00 2001 From: "Bruno P. Kinoshita" Date: Fri, 21 Feb 2020 10:32:11 +1300 Subject: [PATCH 3/4] Incorporate review feedback --- .../getting-started/security-basics.rst | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/docs/source/getting-started/security-basics.rst b/docs/source/getting-started/security-basics.rst index 6704e7ce..1a79f2e6 100644 --- a/docs/source/getting-started/security-basics.rst +++ b/docs/source/getting-started/security-basics.rst @@ -87,12 +87,13 @@ Proxy authentication token The Hub authenticates its requests to the Proxy using a secret token that the Hub and Proxy agree upon. The value of this token should be a random -string (for example, generated by ``openssl rand -hex 32``). +string (for example, generated by ``openssl rand -hex 32``). You can store +it in the configuration file or an environment variable Generating and storing token in the configuration file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Or you can set the value in the configuration file, ``jupyterhub_config.py``: +You can set the value in the configuration file, ``jupyterhub_config.py``: .. code-block:: python @@ -191,12 +192,16 @@ Cookies used by JupyterHub authentication The following cookies are used by the Hub for handling user authentication. +This section was created based on this post_ from Discourse. + +.. _post: https://discourse.jupyter.org/t/how-to-force-re-login-for-users/1998/6 + jupyterhub-hub-login ~~~~~~~~~~~~~~~~~~~~ -This is the login token used when visiting Hub-served pages encrypted such -as the main home, the spawn form, etc. If this cookie is set, then the -user is logged in. +This is the login token used when visiting Hub-served pages that are +protected by authentication such as the main home, the spawn form, etc. +If this cookie is set, then the user is logged in. Resetting the Hub cookie secret effectively revokes this cookie. @@ -205,8 +210,8 @@ This cookie is restricted to the path ``/hub/``. jupyterhub-user- ~~~~~~~~~~~~~~~~~~~~~~~~~~ -This is the cookie used for authenticating with a single-user server -encrypted. It is set by the single-user server after OAuth with the Hub. +This is the cookie used for authenticating with a single-user server. +It is set by the single-user server after OAuth with the Hub. Effectively the same as ``jupyterhub-hub-login``, but for the single-user server instead of the Hub. It contains an OAuth access token, From 239a4c63a2e644f44297c0f330f8985cd25716b0 Mon Sep 17 00:00:00 2001 From: "Bruno P. Kinoshita" Date: Fri, 21 Feb 2020 10:35:30 +1300 Subject: [PATCH 4/4] Add note that not all proxy implementations use an auth token --- docs/source/getting-started/security-basics.rst | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/source/getting-started/security-basics.rst b/docs/source/getting-started/security-basics.rst index 1a79f2e6..5da0a668 100644 --- a/docs/source/getting-started/security-basics.rst +++ b/docs/source/getting-started/security-basics.rst @@ -86,9 +86,13 @@ Proxy authentication token -------------------------- The Hub authenticates its requests to the Proxy using a secret token that -the Hub and Proxy agree upon. The value of this token should be a random -string (for example, generated by ``openssl rand -hex 32``). You can store -it in the configuration file or an environment variable +the Hub and Proxy agree upon. Note that this applies to the default +``ConfigurableHTTPProxy`` implementation. Not all proxy implementations +use an auth token. + +The value of this token should be a random string (for example, generated by +``openssl rand -hex 32``). You can store it in the configuration file or an +environment variable Generating and storing token in the configuration file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~