JWT key rotation - jwt

I have been thinking and searching many different approaches but I am not sure what is the best solution to solve this problem.
Imagine you have 50 microservices that communicate via symmetric JWT - shared key. At the moment the jwt is stored on each microservice (server or virtual host).
What i would like to do is to use aws secret manager to manager the JWT key and to eventually rotate the key.
Obviously i can rotate the key easily but i want to cache the JWT token (with the aws library for python) so that i do not make too many calls to the services (yes, each call to each web service requirs a JWT).
Obviously, if i cache the key for a certain amount of time, there will be cases where the key will be out of sync on some servers, so how would you move forward to be able to rotate secret in aws secret service (keeping in mind that i use caching to avoid slowdown in server interaction and cost)?
Any suggestions?

JWKS use asymmetric priv/pub keys kept in secret manager, expose pub key on the auth server (via url) for other services to use. Auth server either periodically checks for new keys or you ping it to refresh after rotating the keys.

Related

JWT architecture for multiple users?

Most examples always take into consideration only one users using the system in the JWT/Flask tutorials. I want to understand this at a multi-user level but cannot find the correct resources.
Lets say we have the following secret key:
app.config['SECRET_KEY'] = 'randomkey'
Two Questions:
Would this key be the same for every user? if so, wouldn't this provide a security risk because if the key was stolen, anyone would have access to do whatever they want?
If it is not the same, how is the key stored on the server-side so it could be authenticated when requesting information? Would it be stored within the user's table under current token or something?
In this case, that key is the JWT signing key It could also be different from flask's secret key setting (see flask docs). It's not used for encryption so it's not intended to be a shared secret between server and users. Its role is to provide the server with a proof that the JWT content was generated by the server itself: it's a proof of integrity.
Having knowledge of that key means having the right to issue JWTs on behalf of the application, attackers could impersonate servers or make requests with some modified claims, eg pretending to be other users. This means that these keys are quite sensible from security perspective
Turns out that 1 app : 1 key, with some remarks
This key should theorically never change: if at time T1 KEY=x, a user could login in and receive a JWT signed with KEY=x. at T2 KEY=y, the user will invoke some API using the previous JWT and the server will try to verify(signature(payload , x) , y). So every user will be logged out automatically
Despite 1. It would be good to rotate the key. In this case the authentication system should save a buffer of old keys and use them to validate oldest JWT. Since a JWT should be short-lived, it could be useful set a rotation time grater than JWT expire time and just keep the last used key along with the current
This key is a secret and should be managed exactly as other secrets. Aside from terrible approaches like leaving it plaintext in the code/config, there are secret managers from cloud providers, or kubernetes secrets if you use the latter, as well as secret managers from configuration management tools (salt, ansible) or Hashicorp's Vault that is a specialized storage engine for sensible data. Anyway, it's more infra/security team concern if you are in a structured organization

How to safely & properly storing JWT token in Electron App

I'm building an electron desktop app, and in the app it will call the remote API with JWT token. However, where should I persist this JWT token safely without the threats like XSS, CSRF, man in the middle attack etc... and cannot be accessible by other applications
I've tried using node-keytar package, which uses an encryption key derived from the user’s login.
But according to this issue(https://github.com/atom/node-keytar/issues/88), the credential(JWT in our scenario) can still be compromised if the user's environment got a malware installed.
The code of node-keytar is fairly easy, here's the add secret
keytar.addPassword('KeytarTest', 'AccountName', 'secret');
and here's the get secret
const secret = keytar.getPassword('KeytarTest', 'AccountName');
console.log(secret); // "supersecret"
I'm thinking about just storing JWT into the memory might be the safest way, but will require user to re-login and get JWT token everytime they reopen the electron desktop app.
Any suggestions or thoughts are welcomed. Thanks!
In many use cases involving JWT, you would not need to necessarily do any additional encryption/obfuscation of the JWT before you send it to the API, because:
When you send the JWT to the API, you would be doing so via SSL or HTTPS, which encrypts the entire payload. This in theory would eliminate most chances of man-in-the-middle attacks.
Even if someone managed to sniff your JWT token, they would lack the server's key which is required to unlock it. Also, even if they managed to unlock the JWT, it would be almost impossible to alter its contents without also altering the checksum, which is contained within the JWT itself. This eliminates the chance of injection attacks by inserting something into the JWT.
So in general, the JWT pattern is a way of pushing server side session state outside of the application. And it does it in such a way that this state is protected from tampering on the outside. If it were possible to easily tamper with a JWT on the outside, the entire pattern would fall apart.

MIcroservice: Best practise for Authentication

I am looking into using microservice for my application. However the application involves authentication. E.g. there is a service for user to upload their images if they are authenticated. There is also a service for them to write reviews if they are authenticated.
How should i design the microservice to ensure that the user just need to authenticate once to access different services. Should i have a API gateway layer that does the authentication and make this API gateway talk to the different services?
You can do authentication at the gateway layer, if authentication is all you need. If you are interested in authorization, you may have to pass the tokens forward for application to consider it. Also you can do that, if you have trust on other services behind the gateways. That is service 1 is free to call service 2 without authentication.
Also you loose bit of information about the principal, you can however write it back on the request in the gateway while forwarding.
Also another point to consider is JWT, they are lightweight and more importantly could be validated without calling auth server explicitly and it saves you some time specially in microservices. So even if you have to do auth at every service layer you are doing it at minimal cost, some nanoseconds. You can explore that as well.
However final call is based on how strong your security needs are compared to rest. based on that you can take a call. Auth stripping at api gateway saves you code duplication but is less secure as other services can do as they wish.
Same goes for token, you can authenticate without explicit call to auth server but then tokens are valid for some min time and bearer is free to do as they wish once they got the tokens, you cannon invalidate it.
While Anunay's answer is one the most famous solutions, there is another solution I would like to point out. You could use some distributed session management systems to persist sessions on RAM or DISK. As an example, we have authentication module that creates a token and persists it in Redis. While Redis itself can be distributed and it can persist less used data on disk, then it will be a good choice for all microservices to check client tokens with redis.
With this method, there is nothing to do with API gateway. The gateway just passes tokens to microservices. So even in case you are thinking about different authenitcation methods on different services, it will be a good solution. (Although I cant think of a reason for that need right now but I have heard of it)
Inside a session, you can store user Roles and Permissions. That's how you can strict users access to some API's. And for your private API's, you could generate a token with role ADMIN. Then each microservice can call other one with that token so your API's will be safe.
Also you could rapidly invalidate any sessions and store anything you want in those sessions. In our system, spring framework generates a X-AUTH-TOKEN that can be set in headers. The token is pointing to a session key in redis. This works with Cookies too. (and if I'm not wrong, you could even use this method with oAuth and JWT)
In a clean architecture you can create a security module that uses this validation method over API's and add it to every microservice that you want to protect.
There are other options when it comes to session persisting too. Database, LDAP, Redis, Hazelcast ... the choice depends on your need.

Best practice for syncing private keys between server instances

I'm working on a project that uses jwt (json web tokens) to check whether a user is authenticated with the system.
The services are completely stateless, so I can easily scale from one instance to a few dozens. There is only one issue. To be able to validate the jwt on every instance, I need to synchronize the symmetric secret key between the instances.
Of course I could build a system that uses some sort of service discovery and exchanges the symmetric key by encrypting it with an asymmetrical encryption. This just doesn't feel like a proper method.
I could set a fixed key on every instance but changing the key, which effectively invalidates all the previously created tokens, would be a pain.
I don't want to set a master instante every other instance is relying on.
My third idea was using an asymmetrical approach and letting each instance create their own key pair. By writing the issuer in the token, the instance that gets called could retrieve the public key from the instance that issued the token and validate the token this way.
It's not like I don't have any ideas. I just don't really like my ideas so far.
Do you have any best practices to solve such a problem?

REST Api authentication - exchange private key

I'm adding rest API for mobile application into my existing grails web app. Since I'm having hard time with integrating OAuth2 provider into my application, I'm going to implement my own HMAC mechanism.
HMAC uses secret key and what I want is, that each user of application has it's own secret key. Now the thing is how do I transfer secret in a safe manner between API and mobile device initially.
Of course all communication will be through t SSL. But is it safe to send client secret from server to mobile client when connecting for the first time over the wire?
Or I should use one secret and store it with mobile client, which could be easily reverse-engineered?
Or maybe there are other and better ways to do it?
You may want to look into shared key authentication schemes and implement custom mechanism.
Here is example how Amazon use it for REST request:
http://docs.aws.amazon.com/AWSECommerceService/latest/DG/Query_QueryAuth.html
and sample java code
http://docs.aws.amazon.com/AWSECommerceService/latest/DG/AuthJavaSampleSig2.html