wichert / pyramid_jwt

JWT authentication for Pyramid
BSD 2-Clause "Simplified" License
75 stars 31 forks source link

Support for sliding sessions #14

Open Cito opened 7 years ago

Cito commented 7 years ago

This is a nice little Pyramid extension that works very well to provide access to a Pyramid server for a fixed time.

However, contrary to the cookie-based "auth ticket" solution in Pyramid, it does not support "sliding sessions" out of the box, i.e. sessions that automatically extend their duration as long as the user is active. To achieve this goal with web tokens, you could either issue short-living access tokens that renew automatically on every request or use special "refresh tokens" to obtain the actual acess tokens. I think pyramid_jwt should provide special support for one of these mechanisms. Maybe also some support for explicitly invalidating web tokens on log out using a blacklist as a kind of replacement for the "forget" method for cookies.

wichert commented 7 years ago

I don't see how it can provide special support, since refreshing tokens is completely up to the consumer of the web service (i.e. something running in a browser or calling a REST API).

A blacklist might be interesting, but isn't something that most users will need and is likely to require a bit of extra infrastructure to manage the blacklist, so I'm not convinced it should be default behaviour. It could be an optional extension in the package though. Since it isn't something that I need I don't intend to work on that myself, but I'm certainly willing to look at a PR for it.

Cito commented 7 years ago

Thanks for the quick reply.

You're right, if you just let the client refresh the access token, then you just need to provide a refresh endpoint on the server that creates a new token if the user is authenticated (see below). But pyramid_jwt could provide support for the solution that uses two different kinds of tokens, "refresh tokens" and "access tokens". For instance, the create_jwt_token() method could have an additional token_type parameter that could be set to "refresh_token" to create a refresh token, and there could be an additional method to validate a refresh token passed in by the client, and return a newly created access token.

Regarding the blacklist, yes, the management of the list should be made pluggable (like whether you want to store it using redis or just in memory). But all the logic, like creating a "JWT id" to be stored in the list, checking against the blacklist when authenticating users, and automatically removing expired JWTs from the list could be handled by pyramid_jwt.

I think it would already help if you mention the problem in the README.md and provide a simple example recipe for solving it. Like getting the expiration time from the JWT on the client and automatically sending a refresh request shortly before the JWT expires, using an endpoint like this:

@view_config('refresh', permission=Authenticated,
    request_method='GET', renderer='json')
def refresh(request):
    return {'token': request.create_jwt_token(request.authenticated_userid)}

But I'm not sure if this is the best solution. Maybe you have better ideas.

umeboshi2 commented 7 years ago

The distinction between access and refresh tokens doesn't require anything that pyramid_jwt isn't already providing. A view that uses a refresh_token for auth can return the access_token. The client should be managing both tokens and handle expired access tokens. If "token_type" is necessary, it can be added as a claim to be parsed on the server.