GithubHelp home page GithubHelp logo

Comments (22)

orehush avatar orehush commented on August 9, 2024 14

@derek-adair I have created gist with logout view .
@ngocngoan access token will be expired in ACCESS_TOKEN_LIFETIME and you can not refresh it, because refresh token blacklisted.

from djangorestframework-simplejwt.

davesque avatar davesque commented on August 9, 2024 10

Currently, there is no way to logout. I had planned to add a revocation view for tokens but I just don't have the time to do it right now.

from djangorestframework-simplejwt.

MihaiVisu avatar MihaiVisu commented on August 9, 2024 4

In my case I instantiated a CustomAccessToken class inheriting the BlacklistMixin too and in my logout view I just blacklist the token. I know it is not very effective from a database perspective, but it was the quickest workaround in my case.

One solution might be to edit the access token and add some kind of flag in the jwt encoding highlighting whether the token has been deactivated by logging out. I am not sure if this is the most effective way.

from djangorestframework-simplejwt.

sergiowalls avatar sergiowalls commented on August 9, 2024

If refresh token were saved on database we can add a validation against it and perhaps invalidate compromised tokens.

from djangorestframework-simplejwt.

davesque avatar davesque commented on August 9, 2024

Actually, that's probably the best way to do it as long as you're flushing the blacklist fairly frequently. If a token is expired, it will be flushed from the blacklist. There's really no other way to log someone out with JWT's other than to have a blacklist or to change the signing keys (logging everyone out).

from djangorestframework-simplejwt.

marioyc avatar marioyc commented on August 9, 2024

jpadilla/django-rest-framework-jwt#385 mentions the possibility of having different signing keys per user which allows to logout only the intended user, would there be a simple way to implement this?

from djangorestframework-simplejwt.

davesque avatar davesque commented on August 9, 2024

Hmm...yeah, I suppose that is another way. I can't think of a really straight forward way to do it right now. A possible drawback to that approach is that it could be difficult to coordinate using the same signing key across multiple services.

from djangorestframework-simplejwt.

wakaryry avatar wakaryry commented on August 9, 2024

You could add a judge that a token before the logout is invalid.

If add tokens into db, why not to use sessions.

from djangorestframework-simplejwt.

ngocngoan avatar ngocngoan commented on August 9, 2024

Hi!

I wrote a logout function, and I added a successful token refresh to the blacklist. But then I realized that when I send requests with access token in HTTP Header, I still get the value of success (code 200) without the unauthorized error (code 401) as expected.

from djangorestframework-simplejwt.

derek-adair avatar derek-adair commented on August 9, 2024

Would someone mind posting a gist of this working? Seems like something beneficial to the docs.

from djangorestframework-simplejwt.

volartem avatar volartem commented on August 9, 2024

Is it possible to change expires_at in current access token on logout request?

from djangorestframework-simplejwt.

davesque avatar davesque commented on August 9, 2024

Yes, but there are still unexpired access tokens with valid signatures out in the wild at that point. So doing that wouldn't really log anyone out.

from djangorestframework-simplejwt.

greyhare avatar greyhare commented on August 9, 2024

The way things are supposed to work is that you have some other communication channel to JWT-using services, such as a publish-subscribe setup, that would broadcast revoked tokens. Those other services would need to add them to their blacklists.

This channel, IMHO, is outside the scope of this project, because we have no idea what it is (dbus, zeromq, smtp, who knows). The module user would be expected to add this support themselves, using the blacklist module (or equivalent) to track blacklisted tokens.

from djangorestframework-simplejwt.

davesque avatar davesque commented on August 9, 2024

@greyhare Yeah that seems correct. Although maybe we could add something like a signal that people could hook into if they want to build their own blacklisting channels.

from djangorestframework-simplejwt.

greyhare avatar greyhare commented on August 9, 2024

Right now, I guess the signal could be "blacklist object created"

from djangorestframework-simplejwt.

trase8 avatar trase8 commented on August 9, 2024

maybe it's better to use cache or redis for blacklist storage backend? Cache may be expired for instance in 24h. So this allows not to use cron tasks

from djangorestframework-simplejwt.

greyhare avatar greyhare commented on August 9, 2024

I haven't used Redis much myself. Can you tell it when to expire an object? If so, then you can just set object expiration time to token expiration time.

Also, can you search for an object via its SHA-256 hash? The blacklists I've seen elsewhere just store the SHA-256 hashes of expired tokens, not the tokens themselves.

from djangorestframework-simplejwt.

shahriaroo avatar shahriaroo commented on August 9, 2024

The problem with Redis is that it's an in-memory database and therefore when it restarts it would log everyone back in (unless you use a Redis cluster or something).

from djangorestframework-simplejwt.

sshishov avatar sshishov commented on August 9, 2024

Could you guys please explain to me why do you store blacklisted tokens instead of whitelisted?

In the beginning, I was thinking about the saved database call on token validation, but if we are validating against blacklisted tokens, it will be the same, even worse.

If you store only VALID tokens, then it is easy to revoke and you almost no need to clean anything, except of expired refresh tokens in the database based on created_at date for instance.

In our setup we did use REDIS to store valid tokens for users as DB call is quite expensive to do on every request (as we are validating tokens against misuse and we rotate refresh token every now and then). But a lot of people just do not have REDIS setup ready and depending on the users count, you can have OOM of REDIS unexpectedly if you are not running managed service on AWS for instance.

from djangorestframework-simplejwt.

Andrew-Chen-Wang avatar Andrew-Chen-Wang commented on August 9, 2024

@sshishov I like that idea of whitelist. There are definitely pros and cons to each, and I think the time consumption on whitelisting is much less than a full scan for the blacklist table. (even with a bunch of bots spamming, it wouldn't make a difference).

HOWEVER, I think the biggest problem with whitelisting is the data storage requirement. If we're only blacklisting a certain few tokens, data is limited. If we accept majority of users, then you've got a huge database table that needs a cron job clearing that table for expired.

Whitelisting with Redis is the same story. You don't want to fill up the data store too quickly if you're accepting the majority of incoming requests.

from djangorestframework-simplejwt.

sshishov avatar sshishov commented on August 9, 2024

Hello @Andrew-Chen-Wang .

If you are using database, then every access of protected API will do DB call which is not desired when we are using JWT tokens (as it is self contained).

Using REDIS, it is completely different story:

  • If we store only valid refresh tokens, we should not fill up quickly
  • Along with storing the token we can set TTL on the key (for instance tokens:<user_id>:<token_id>) the same value + 5 seconds of the token lifetime. The only issue with this approach if users will just start doing a lot of login requests where new refresh tokens will be generated every request. And we cannot easily restrict the number of tokens per user as lookup in redis with a lot of data is not VERY fast also like SCAN tokens:<user_id>:* and limit to 10, but it if we are okay with this small delay on every refresh/login, then it is way to go.
  • Another approach is to use REDIS lists on the key tokens:<user_id> with TTL of inserted token. and update TTL on every new push to the list using (LPUSH, RPOP) and here you can limit number of tokens per user, say 5. If the returned value of LPUSH more than 5, then we will do RPOP to remove the latest element from the list and update TTL of main key

It is just my assumptions and possible ways to solve the problem without degradation of the performance.


Update:

Points to consider:

  • Also using blacklist approach you will add to the database/redis every "old" refresh token after successful rotation, or not?
  • If I am user and my refresh token leaked, but then I did re-login and started using OLD token. The "bad" guy can still use old leaked token to access data. And to blacklist it, we have to know which token exactly to blacklist, how we are going to get it, only from logs?

from djangorestframework-simplejwt.

greyhare avatar greyhare commented on August 9, 2024

The reason you want a blacklist instead of a whitelist is because it's a much shorter list, and tokens can be removed from the blacklist when they expire. So authentication is just "is the JWT itself valid, and not in the blacklist?" Which is a hash operation plus a lookup on a small tree.

Which gets back to one of the main reasons to use JWT is that you don't need to maintain a database of valid tokens shared among the hosts trying to authenticate the token. If you're okay with keeping a database of active tokens to authenticate against, you may as well be using the non-JWT random session token model.

Some things regarding refresh tokens:

  • Maybe instead of generating a refresh token on login, you require the client to wait some time before requesting it? I.e. you can request a longer-lived refresh token, but only with a regular JWT that's at least n seconds old. Then folks who just need a one-and-done transaction don't have to deal with refresh tokens at all.
  • There should only be one refresh token for a session ever. Refresh tokens are basically session tokens, with all their problems. Maybe allow the client to optionally provide the old refresh token in the refresh request so you can expire it immediately?
  • Yes, you need to blacklist old refresh tokens. Maybe they need their own blacklist with its own rules?
  • Or maybe you only issue new refresh tokens within some time of the expiration of an old one, and set the new token to only become valid a few seconds before the old one expires?
  • "If I am user and my refresh token leaked, but then I did re-login and started using OLD token." Old which token, regular or refresh?

from djangorestframework-simplejwt.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.