Securing a go REST API - Part 1: Sessions

This is part 1 of a multipart series on how to secure your API in golang. This series is inspired by this blogpost where they use a token to implement stateless session management. In this part I want to talk about session management in general.

More and more people recommend JWTs (JSON Web Tokens) for session management in web apps. People see different benefits for using them in session management. I’m not going into all the details of why this isn’t a good idea (read here for a good article). I want to focus on two reasons

1. Stateless session management is bad

I’ll admit that stateless session management isn’t always bad, but in 99% of the cases, stateful session management will make your life easier. Unless you are the admin of Google or Facebook, stateless session management will not bring you any scalability benefits. A single database with a nice cache can serve much more users than you expect.

Stateless sessions are nice to use because they feel easy. You store some user information in the session and you’re done. Since it’s all stored in the client, your server just needs to decrypt the session on each request no call to the database is needed.

I see people argue that stateless tokens can be superior because decrypting a token is faster than connecting to Redis. The thing is: A call to a database or to Redis is dirt cheap. If you have a huge distributed application, you can use read-only replication and you’re done. Don’t start optimizing prematurely at the wrong end. Encoding all the information clientside also means the client needs to send the information with every request. On slow connections, this can easily be more noticeable than a call to Redis from your application (hopefully, both are in the same datacenter).

But the most notable reason against stateless session management is that it’s too easy to shoot yourself in the foot. What about invalidating sessions early? Suddenly you have to maintain a token blacklist (one could argue that this is state as well) and if you aren’t careful you don’t catch all the tokens you wanted to invalidate. What about session information stored clientside diverging between two clients? Suddenly you have to think about consistency.

2. JSON Web Tokens is a bad standard (for sessions)

This has been talked about a lot before. If you really need to use stateless session management (you don’t), don’t use JWTs. It’s a cryptographic mess. The details can be found here. If you want to store sessions clientside, use cookies and just encrypt them with AES-GCM or XChaCha20-Poly1305 or use old style HMAC-SHA256 + AES-CBC with PKCS#5. You’re done, it’s easy.

If you really, really need tokens (for other things than sessions), you can use PASETO.

Continue with Part 2: Timeouts.