https://apibakery.com/blog/tech/no-jwt/ API Bakery Open menu Solutions Startups Move faster without sacrificing quality Frontend Developers Focus on the user, we'll handle the backend. SaaS No need to reinvent the wheel. Start with a proven tech stack. Backend Developers Hit the ground running, instead of reinventing the wheel. Agencies Write better code, faster. Mobile Developers Start using fully-functional backend API from day one. Full-Stack Developers Use your preferred backend, full-featured from day one. Technology Platforms Full support for Python/Django and NodeJS/Express platforms Features Scaffolding, database design, API generation, authentication, and more Integrations Cloud storage, mail services, logging, and other 3rd-party integrations REST API Guide Learn all about RESTful APIs in our comprehensive guide. Pricing Blog About About Us Who we are and why we're building API Bakery. Guides In-depth guides on building REST API backends. FAQ Miscellaneous questions about our product. Contact Got questions or feedback? We'd love to hear from you. Sign in Sign up Close menu Startups SaaS Agencies Frontend Developers Backend Developers Mobile Developers Full-Stack Developers Platforms About Us Features FAQs Integrations Contact Sign up Existing customer? Sign in Technology Why you should not use JWT October 26th, 2021 In this article: * -- Crash course on web auth * -- What are JSON Web Tokens * -- Problems with JWT * -- Who should use JWTs * -- Who should not use JWTs * -- How we do auth How do you handle user authentication in your web app or API? When it comes to implementing auth, JSON Web Tokens (JWTs for short) are often touted as an industry best practice. On some platforms, and for some frameworks they are the first thing that comes to mind: we've seen many discussions on developer forums (such as /r/node) where the only alternatives suggested were JWT if you're doing it yourself, or using a 3rd-party service such as Auth0. When we added Node support to API Bakery, we thought long and hard whether to include JWT, because of its popularity. We decided against it. Here's why, and why you should probably not use JWT either. Crash course on web auth Most of the client-server communication on the web nowadays is stateless request-response (WebSockets are super useful, but people are not replacing plain old requests with them). This means that after your user logs in (for example, by providing email and password to your server), you, as a web developer, need to think how the next time that user's request hits your server you'll know it's from the same user. The first popular mechanism was cookies - arbitrary key-value pairs the server sends to the client. Client sends the same cookie key-value pairs back on following requests. Server can then inspect the cookies received and figure out information about the client. Sessions were built on top of cookies. The server kept context about the user's "session" (details about the user, shopping cart if the site was a webshop, and so on) and indexed it with a random session ID. The session ID was sent as a cookie and for each subsequent request, server looked up the session state. For the most part, this worked well, especially if your web framework of choice kept you safe from problems like CSRF. Then came mobile apps and single-page JavaScript apps, and plain cookies and sessions started being inadequate. Developers started using tokens, where a token was an unguessable random string that behaved like an identity card. Possession of it proved your (client's) identity (bearer token). Unlike an identity card, the same user could have multiple tokens (for example, one for each device) and tokens could be deleted or changed as needed. What are JSON Web Tokens JSON Web Tokens (JWTs) are a type of token with a twist. Instead of a random unguessable string (a bearer token we just described), JWT contains all the information about the user directly in itself. The information is cryptographically signed so a malicious user can't just change a few bytes in the token and the server will immediately see the signature doesn't match the forged contents. The information itself is a JSON-encoded object, that's optionally encrypted, then encoded and signed in a specific way, all defined in RFC 7519, an open internet standard. Major advantage of JWT compared to bearer tokens (or indeed, session authentication) is that they don't require looking up the token. If you have a distributed system, each node in the system can verify JWT correctness for itself and immediately use the data - no need to look up the random string in the database to figure out who it is. That's great if you've got a true microservices architecture. Your auth service can check user credentials (email and password, or using a 3rd-party auth provider), issue a JWT and call it a day. Other microservices can independently verify the correctness of the token and have the user information immediately, without the need to check in with the auth service. This shaves precious time off of every request handling and lowers the load on your auth service. What's not to like? Unfortunately, a lot. Problems with JWT An old joke is that there are only two hard things in computer science: cache validation, and naming things. JWT is named pretty well, but fails miserably at the first problem: invalidation, or How do you log out the user? The answer is, you don't. You can't. You (the server) can tell the user's client software to forget their JWT and hope they'll do it, but you can never be sure. Well, you could keep a list of tokens that are no longer valid - that is, the user has logged out and the token should be ignored. However, on each request, you need to check the token against this list and you've just lost your only advantage over much simpler bearer tokens, so that's not gonna work. Another strategy, and what people usually do in practice, is to minimize the damage: keep the token lifetime short (a couple of minutes) and issue another token, a refresh token. When the user logs in, you issue a short-lived JWT and a long-lived refresh token. When JWT expires, the client must request a new JWT using the refresh token. Your auth service then checks that refresh token is still valid (which is less of a problem as it's not happening on every request) and if it is, issues a new JWT. Issue solved, right? Well, kind of, except you've just reintroduced a bearer token, because that's exactly what the refresh token is. Looking at JWTs from that perspective, you've introduced a client-side cache of user identity (the JWT) and added a bunch of complexity (involving the creation, verification, and token refresh) for the hope of optimizing part of the work you used to do on the server (checking user identity using a bearer token). Was it worth it? And that's just the biggest problem. We've ignored things like increased attack surface due to complexity of JSON parsing/ validation, misconfiguring JWT libraries to allow no signature, leaking data to users because you thought JWTs were encrypted (they're usually not by default), and poor implementation of API clients that don't properly re-run requests that failed due to expired JWTs. The list goes on, and on, and on ... Who should use JWTs There certainly exist cases where JWT might be a good fit. If you have a truly distributed microservices architecture where the services themselves are completely independent (no touching the central database, or even a concept of a central database), then look up JWT. Or even better, some of the new JWT look-a-likes that fix some of its glaring security problems, like PASETO. Who should not use JWTs Everyone else, and that means most of web developers out there, should avoid them. And that's not just our (well researched) position. To quote security experts Thomas Ptacek: But, don't use JWT and Randall Degges: JWTs suck, and are stupid What should you use instead? To quote Thomas again from the same article: I continue to believe that boring, trustworthy random tokens are underrated, and that people burn a lot of complexity chasing statelessness they can't achieve and won't need, because token databases for most systems outside of Facebook aren't hard to scale. How we do auth This brings us back to how we implement authentication in Node projects you generate with API Bakery. If you've read all of the above, no surprise here - we use bearer tokens. They're simple to implement and simple to understand. For many projects, they'll be just enough. And if you do need another mechanism, the auth code in the generated project is isolated enough that it won't be a problem to rip it out and replace it with something else. But, don't use JWT. About API Bakery Build your next API backend in seconds. We create production-ready code for your backend service, customized just for you. Live demo Related articles * Understanding async/await in JavaScript We explain what `async` and `await` do in JavaScript and how they work, in simple terms, while not treating them as black magic. View all Footer Solutions * Startups * SaaS * Agencies Developers * Frontend * Backend * Full-stack * Mobile Platforms * Django / Python * Express / Node.js * Laravel / PHP Technology * Features * Integrations * Open-Source About * Why API Bakery * Pricing * Blog * Contact Legal * Privacy * Terms Facebook Twitter GitHub YouTube (c) 2019-2022 API Bakery