eduaravila / momo

1 stars 0 forks source link

how to manage sessions #5

Open eduaravila opened 1 year ago

eduaravila commented 1 year ago

I'm not familiar with Django, but if you have a JWT it should be using a public/private key pair (to sign or to encrypt, your choice, but you shouldn't be relying on symmetric encryption of JWTs to pass data around your systems; that sounds like a world of hurt of unnecessary complexity).

What this means is that the signing service has signed the key using the private key. That key can and should be kept controlled. Where to keep that secret is a topic unto itself, but it only needs to be accessible to the signing service (be that Django or something else).

For every other service, all you need is the PUBLIC key to decrypt the token, and validate that it was signed with the corresponding private key.

You can either do that locally to the service (where they are given the corresponding public key), or you can make it so there is a dedicated endpoint on the signing service for validating tokens.

The benefit to having a dedicating service that both signs, and validates, is that you can update tokens atomically (ish; if you have to scale that service out you may need to support multiple keys at once, or suffer some downtime; either way you should think about what happens to existing tokens if you have to rotate the key; how do clients know to sign users in again), and in general control the logic. The downside is the latency and additional traffic (since every incoming request will then have to call out to this service to validate the token).

Both Python and Golang should have well documented libraries and examples for this, though finding the corresponding equivalents may take a little trial and error.

This assumes you're using your own signup/login flow, rather than OAuth (which I'm assuming from your questions; if you're using something like a "Sign in with Google" flow, this all changes only in that the validation endpoint is owned by the signer rather than by you). If you are, the way passwords relate is this - when a user signs up (using HTTPS), you hash their password (using something like Bcrypt or another cryptographically strong hashing algorithm) and store that hash. When they log in, you take the salt from what is stored in the database, use that to hash the password that was sent in to confirm that the hashes match (meaning the passwords match), and then once you've confirmed they do, you create a JWT using the secret key, and return it. That JWT is sent with every request and can be confirmed either by decrypting it using the public key, or by calling the validation URL, as detailed above. When the password is changed, it has ZERO effect on the JWT. JWTs have their own life cycle, and should NOT store any secrets in them (because anyone with the public key can decrypt them, and public keys are meant to be, well, public, even if they aren't in practice).

There's a bit more with JWT best practices, having a refresh token separately from the auth token, etc etc, but that's the gist.

13

Reply