bug with logout?

33 views
Skip to first unread message

Tim Harsch

unread,
Jan 18, 2018, 7:05:24 PM1/18/18
to Project Jupyter
I'm trying to understand the logout chain in jupyterhub/notebooks.   version 0.8.1 and 5.1.0 respectively.   I'm using dockerspawner and jwtauthenticator.

I would like to effect a logout from outside the UI, so I tried using the API token and that doesn't seem to work as I get a 403.   So I started experimenting and performed this simple test:

login to jupyterhub with chrome developer tools.   in network tab right-click copy /user/{name}/api/contents call as curl command.    execute the command at the terminal (which includes Cookie header).  Notice success with JSON.
go to UI and choose logout in UI.   
repeat curl command and notice same result.  I'm allowed in to a logged out session with the Cookie token.  Does this seem like a bug? or I wonder if it has to do with my fairly specific environment?

Thanks,
Tim

Thomas Kluyver

unread,
Jan 19, 2018, 5:29:46 AM1/19/18
to Project Jupyter
Logging out should clear the cookie in the browser, but if you've taken a copy of the cookie before that, it's still valid.

--
You received this message because you are subscribed to the Google Groups "Project Jupyter" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jupyter+unsubscribe@googlegroups.com.
To post to this group, send email to jup...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jupyter/fbb689b6-ca3d-4c7c-abfe-e7ee5fee7cee%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Tim Harsch

unread,
Jan 19, 2018, 10:59:06 AM1/19/18
to Project Jupyter
I see your point.   But the issue is compounded by the fact that since the logout is occurring through the REST API, the browser still maintains the cookie.  So, after performing logout on command line I can go back to the browser and continue to have access.

We recently underwent a security evaluation of our app, which uses JWT and we were told that we have the same problem in that we need to configure our app to have a persistent store of invalidated tokens to ensure they can't be re-used after logout.   It seems that would be the best security practice.  Since in my use case I'm using jwtauthenticator, I was planning to submit a PR to make that option available in the authenticator.   That wouldn't make sense unless the protection were there for the jupyter token as well.


On Friday, January 19, 2018 at 2:29:46 AM UTC-8, takowl wrote:
Logging out should clear the cookie in the browser, but if you've taken a copy of the cookie before that, it's still valid.
On 19 January 2018 at 00:05, Tim Harsch <harsc...@gmail.com> wrote:
I'm trying to understand the logout chain in jupyterhub/notebooks.   version 0.8.1 and 5.1.0 respectively.   I'm using dockerspawner and jwtauthenticator.

I would like to effect a logout from outside the UI, so I tried using the API token and that doesn't seem to work as I get a 403.   So I started experimenting and performed this simple test:

login to jupyterhub with chrome developer tools.   in network tab right-click copy /user/{name}/api/contents call as curl command.    execute the command at the terminal (which includes Cookie header).  Notice success with JSON.
go to UI and choose logout in UI.   
repeat curl command and notice same result.  I'm allowed in to a logged out session with the Cookie token.  Does this seem like a bug? or I wonder if it has to do with my fairly specific environment?

Thanks,
Tim

--
You received this message because you are subscribed to the Google Groups "Project Jupyter" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jupyter+u...@googlegroups.com.

Lawrence D’Oliveiro

unread,
Jan 19, 2018, 6:08:16 PM1/19/18
to Project Jupyter
On Saturday, January 20, 2018 at 4:59:06 AM UTC+13, Tim Harsch wrote:

... we need to configure our app to have a persistent store of invalidated tokens to ensure they can't be re-used after logout.

Surely it’s the other way round, the usual practice being to maintain a store of valid tokens, with a finite lifetime attached to each (perhaps reset when they get presented again). The tokens get deleted either on explicit logout or implicitly on lifetime expiry. Anything that isn’t currently recognized from the store entries is invalid.

Roland Weber

unread,
Jan 22, 2018, 3:07:20 AM1/22/18
to Project Jupyter
On Saturday, January 20, 2018 at 12:08:16 AM UTC+1, Lawrence D’Oliveiro wrote:
Surely it’s the other way round, the usual practice being to maintain a store of valid tokens, with a finite lifetime attached to each (perhaps reset when they get presented again). The tokens get deleted either on explicit logout or implicitly on lifetime expiry. Anything that isn’t currently recognized from the store entries is invalid.

Nope, that would require a central store of tokens. In single sign-on environments, or with more complex authentication schemes like OAuth, web servers have to accept tokens that were issued elsewhere. They don't know about a token until it is presented to them.

Matthias Bussonnier

unread,
Jan 22, 2018, 11:04:18 AM1/22/18
to jup...@googlegroups.com
I believe the use case and patterns for JupyterHub vs notebook could be sufficiently different that we may want to look more into details. 
IMHO having a set cookie  to login to a notebook seem reasonable, as users often only use it on localhost, and once you are logged-in you want your login status to persist during notebook restart (which can be quite often). 
For Hub, as Hub is an intermediary that is likely up for long period of time, having 1 cookie/client that are revokable does make more sens from the security point of view.

I would bring this discussion to the Hub tracker (and it may be that the hub does that already).
-- 
M

--
You received this message because you are subscribed to the Google Groups "Project Jupyter" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jupyter+unsubscribe@googlegroups.com.

To post to this group, send email to jup...@googlegroups.com.

Tim Harsch

unread,
Jan 22, 2018, 11:36:51 AM1/22/18
to Project Jupyter
I spent some time digging into Spring to see how it is handled.  They have a PersistentTokenBasedRememberMeServices class.  It generally follows this standard approach http://jaspan.com/improved_persistent_login_cookie_best_practice.  The article was a very interesting read and I think it may be applicable to this issue.

On Monday, January 22, 2018 at 8:04:18 AM UTC-8, Matthias Bussonnier wrote:
I believe the use case and patterns for JupyterHub vs notebook could be sufficiently different that we may want to look more into details. 
IMHO having a set cookie  to login to a notebook seem reasonable, as users often only use it on localhost, and once you are logged-in you want your login status to persist during notebook restart (which can be quite often). 
For Hub, as Hub is an intermediary that is likely up for long period of time, having 1 cookie/client that are revokable does make more sens from the security point of view.

I would bring this discussion to the Hub tracker (and it may be that the hub does that already).
-- 
M
On 22 January 2018 at 00:07, Roland Weber <rolw...@de.ibm.com> wrote:
On Saturday, January 20, 2018 at 12:08:16 AM UTC+1, Lawrence D’Oliveiro wrote:
Surely it’s the other way round, the usual practice being to maintain a store of valid tokens, with a finite lifetime attached to each (perhaps reset when they get presented again). The tokens get deleted either on explicit logout or implicitly on lifetime expiry. Anything that isn’t currently recognized from the store entries is invalid.

Nope, that would require a central store of tokens. In single sign-on environments, or with more complex authentication schemes like OAuth, web servers have to accept tokens that were issued elsewhere. They don't know about a token until it is presented to them.

--
You received this message because you are subscribed to the Google Groups "Project Jupyter" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jupyter+u...@googlegroups.com.

To post to this group, send email to jup...@googlegroups.com.

Lawrence D’Oliveiro

unread,
Jan 22, 2018, 3:04:20 PM1/22/18
to Project Jupyter
On Monday, January 22, 2018 at 9:07:20 PM UTC+13, Roland Weber wrote:

On Saturday, January 20, 2018 at 12:08:16 AM UTC+1, Lawrence D’Oliveiro wrote:
 
Surely it’s the other way round, the usual practice being to maintain a store of valid tokens, with a finite lifetime attached to each (perhaps reset when they get presented again). The tokens get deleted either on explicit logout or implicitly on lifetime expiry. Anything that isn’t currently recognized from the store entries is invalid.

Nope, that would require a central store of tokens.

Which you have to have somewhere anyway.
 
In single sign-on environments, or with more complex authentication schemes like OAuth, web servers have to accept tokens that were issued elsewhere. They don't know about a token until it is presented to them.

Don’t they have to check back with the issuing server(s) to validate those tokens anyway? Then if they pass, keep them in a local cache for some reasonable time, either until their expiry (if that’s not too long) or until they need to be rechecked for validity. Either way, you do not want to maintain an ever-growing store of invalid tokens, only a limited and regularly-pruned store of valid ones.

This is all just basic security stuff.

Thomas Kluyver

unread,
Jan 22, 2018, 3:23:26 PM1/22/18
to Project Jupyter
There's two ways to approach it. One is, as you're describing, to have a central store of currently valid tokens, and check against that.

The other is to have tokens that contain information on what permissions they grant and when they expire, with a cryptographic signature to prevent tampering. Then you don't need a central store; the server receives a token, checks that it is in date and gives the necessary permission, and checks that it was correctly signed. However, you do need a central store if you want to invalidate tokens before they expire. It's not ever-growing, though, because once an invalidated token has expired, you can discard it from the list.

Thomas

--
You received this message because you are subscribed to the Google Groups "Project Jupyter" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jupyter+unsubscribe@googlegroups.com.

To post to this group, send email to jup...@googlegroups.com.

Tim Harsch

unread,
Jan 22, 2018, 11:01:34 PM1/22/18
to Project Jupyter
That's my understanding as well.   Also stated in the javadocs of https://docs.spring.io/spring-security/site/docs/4.0.3.RELEASE/apidocs/org/springframework/security/web/authentication/rememberme/PersistentTokenBasedRememberMeServices.html  "A suitable batch process should be run periodically to remove expired tokens from the database."

In the approach described at http://jaspan.com/improved_persistent_login_cookie_best_practice, a series ID is used to aid in the generation of a new token for each request.  With this approach it is impossible to get into the session by stealing and re-using the token, because it is only good for one request.  Coupled with the persistent store of not expired but invalidated tokens it is possible to prevent the hijacking of a token.   In the Jupyter case, would it be possible for the logout from the API, using the API token, to invalidate all tokens of the user in the persistent store? .. and thus even if the user tried to use an open window for another request, the current browser token would not be valid.  That would make possible a useful admin feature of logging out all logged in users.


On Monday, January 22, 2018 at 12:23:26 PM UTC-8, takowl wrote:
There's two ways to approach it. One is, as you're describing, to have a central store of currently valid tokens, and check against that.

The other is to have tokens that contain information on what permissions they grant and when they expire, with a cryptographic signature to prevent tampering. Then you don't need a central store; the server receives a token, checks that it is in date and gives the necessary permission, and checks that it was correctly signed. However, you do need a central store if you want to invalidate tokens before they expire. It's not ever-growing, though, because once an invalidated token has expired, you can discard it from the list.

Thomas
On 22 January 2018 at 20:04, Lawrence D’Oliveiro <lawren...@gmail.com> wrote:
On Monday, January 22, 2018 at 9:07:20 PM UTC+13, Roland Weber wrote:

On Saturday, January 20, 2018 at 12:08:16 AM UTC+1, Lawrence D’Oliveiro wrote:
 
Surely it’s the other way round, the usual practice being to maintain a store of valid tokens, with a finite lifetime attached to each (perhaps reset when they get presented again). The tokens get deleted either on explicit logout or implicitly on lifetime expiry. Anything that isn’t currently recognized from the store entries is invalid.

Nope, that would require a central store of tokens.

Which you have to have somewhere anyway.
 
In single sign-on environments, or with more complex authentication schemes like OAuth, web servers have to accept tokens that were issued elsewhere. They don't know about a token until it is presented to them.

Don’t they have to check back with the issuing server(s) to validate those tokens anyway? Then if they pass, keep them in a local cache for some reasonable time, either until their expiry (if that’s not too long) or until they need to be rechecked for validity. Either way, you do not want to maintain an ever-growing store of invalid tokens, only a limited and regularly-pruned store of valid ones.

This is all just basic security stuff.

--
You received this message because you are subscribed to the Google Groups "Project Jupyter" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jupyter+u...@googlegroups.com.

To post to this group, send email to jup...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages