6

I just read this article about why JWT's suck. I'm now uncertain what I should use for authentication.

For context: The API I wrote is mainly used by mobile Apps (iOS and Android). In the future it will also be accessed via a React Frontend.

In the past I just used DRF's build in Token authentication. The phone would then just store this token in the storage of the respective app.

Now I've recently been told, that this is not safe and that I should use JWT's. While researching JWT's I found the article above, which elaborates on why JWT's suck and basic session authentication is better. But as far as I know, when used as an API I can't use session authentication with DRF, can I?

So my question is? What tools of DRF should I use for authentication, so that it's safe?

Anders
  • 64,406
  • 24
  • 178
  • 215
J. Hesters
  • 163
  • 1
  • 5

2 Answers2

6

I'm the author of that article, as well as the somewhat popular tech talk I give about why JWTs suck and are stupid (all of which @joepie91 has eloquently written about much better than I ever could: http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/).

Given your application requirements (mobile app + JS front-end only app that both talk to a backend API), I'd suggest you use the OpenID Connect Authorization Code flow (w/ PKCE for your mobile app).

For your mobile app, specifically, I'd recommend using the fabulous AppAuth library: https://appauth.io/ (it has great libraries for both iOS + Android).

Now, you might be wondering why I'd recommend using OpenID Connect (and thus, JWTs) for something when I so publicly rally people against using JWTs: I'll tell you -- for most stuff it just does not matter.

Here's the thing: yes, JWTs are pretty awful to use when building secure apps. They're complicated, most libraries currently aren't spec complete, and using more advanced features like JWT encryption are almost sure to cause you massive headaches and compatibility issues between your services.

Furthermore, the entire reason JWTs have become popular for authentication is that they are frequently used to CACHE authentication and authorization data -- this entire practice is a big NO NO in the security world.

Caching sensitive data (like authentication and authorization data) is the worst possible thing you can ever do for security: you're trusting outdated information. ALL current auth systems built on top of JWTs suffer from this naïvety.

Once you've gone down the rabbit hole of trying to "speed up" your site/API by using JWTs, you've already committed a security sin and are now at risk.

Moreover, once people start using JWTs and realize they're at risk, they try to re-centralize everything (as one other commenter has suggested) and begin using revocation lists so that they can revoke tokens when bad things happen. This results in the same speed penalties as traditional session management, but with greater speed penalties due to JWTs being "heavier" than session cookies, and more fragile.

Sorry for the rant, but here's my advice:

  • If you want real security, you have to use server-side sessions. In your case, this would entail supporting session cookies from your API backend so that when your react app authenticates to your API, the API sets a secure cookie that the react app uses automatically each time it talks back to the API service to authenticate. You'd also need to use a cookie-based API from your mobile app (I'm not familiar with building native mobile apps, so can't comment on this component).
  • If you want simplicity and the same amount of security as just about every other major web app, using OIDC and go with out of the box open source solutions. This is the simplest way go currently and while it's not perfect, if it solves your problem then it likely isn't a big deal.

If you're building something sensitive, try to use server-side session cookies when possible. Otherwise? Don't sweat the details and go with the flow.

rdegges
  • 333
  • 1
  • 5
  • Little follow up question: Is it possible to have Django and React on the same server working with Django's default session cookies? My idea was the following: You use two regular views and a couple of api endpoints with DRF. The 1st view handles the authentication. The 2nd has a "catch-all" regex and login required mixin and loads the react frontend. React then uses the DRF API views(, which are also set to use session auth,) to communicate with the database. Since the React app is on the same server as the rest CSRF shouldn't be a problem. Would this be a safe way to use session cookies? – J. Hesters May 01 '18 at 10:53
  • You forgot that jwt is way easier to handle a ddos attacks, which is why it's favored in high security applications, like financial (AFAIK). If every request from every user is to be routed to the database, you can kiss your database goodbye or spend lots of money on unnecessary scaling (sharding ,etc). It's much easier to add computational power to handle jwt compared to the computational power to handle a database request. That former is distributable and can be handled at the API level. – The Quantum Physicist Jan 10 '19 at 09:24
1

You have two good options IMO:

  1. Use a random string, that will correspond with a session stored in database. This is the best option if possible. Though these sessions should not be long term. Use a re-authentication using JWT token if you need long term login.
  2. Use a JWT signed with symmetric key (HMAC). This is faster while still secure. This option however is still much more demanding on bandwidth and generally slower then random string.
Peter Harmann
  • 7,728
  • 5
  • 20
  • 28
  • Thank you for your answer! So random String would basically mean like Django Rest Framework's [Token Authentication](http://www.django-rest-framework.org/api-guide/authentication/#tokenauthentication)? And you suggested JWTs even though I think (according to the article I posted and according to [this video](https://youtu.be/pYeekwv3vC4) that JWTs are insecure. And yeah the seconds option sounds good, but I want to decrease bandwidth if possible. – J. Hesters Apr 29 '18 at 21:16
  • @J.Hesters No, JWTs are very secure. The problem is, they are slow to verify, which can lead to your server being slow, or even get DoS-ed. The trick is verifying the JWT rarely, like once a day when the session expires and put rate limit on it, so it can't be flooded. Also, I don't know what Django uses, but it is extremely important the random function to generate it is good. PHP had issues with small randomness and the secret being guessable. – Peter Harmann Apr 29 '18 at 21:26
  • Also, make sure you have a way to revoke your JWT tokens. – Peter Harmann Apr 29 '18 at 21:30
  • Did you watch the video? Apparently JWT's are very insecure. They are very vulnerable to XSS for example. And concering the DRF function to generate random tokes, I assume it is good. So I think I will use Django's own token authentication, or OAuth since that what many people have suggested. – J. Hesters Apr 30 '18 at 11:09
  • @J.Hesters JWT is only as vulnerable to XSS as the storage method you use for it, which is true for any authentication method. It is not unique to JWT... And what video? – Peter Harmann Apr 30 '18 at 11:58
  • This video: https://www.youtube.com/watch?v=pYeekwv3vC4&feature=youtu.be :) – J. Hesters Apr 30 '18 at 13:15