6

I am developing an app using microservices in NodeJS. I have built an auth api which handles the usual registration login etc and it issues JWT's

How do I use these to protect routes in a separate API microservice written with Express?

Do I need to use JWT with the secret to decrypt the token in the API app?

1
  • This way's too complicated and also contradicts the principle of single responsibility. Basic reverse proxy solves the problem Commented Mar 14, 2021 at 9:05

4 Answers 4

29

You could write a library that you import into your other microservices that requires all routes by default to require authentication. This library could have a mechanism to validate JWT's at the microservice level, so you never need to talk to your auth api to see if a JWT is valid or not. See the description and diagram below:

Your auth server will will need to be the single issuer of JWTs to your microservices. So, when a user logs in and successfully authenticates, your auth server will issue a JWT signed with a private key (signing MUST be asymmetric - RS256 is one example) you keep on the auth server only; do not give this private key to other microservices that you wish to validate JWTs inside of. What you can do is derive a public key based on the private key you sign your tokens with and publish that to an endpoint on your auth server that requires no authentication - the public key will be represented in the form of a JWK (see link to spec). Google does something similar here. Then, in each of your microservices, your library will need to devise a way to make a GET request to the public key endpoint on your auth server every X minutes to see if there are any changes and cache the public key in each microservice. By having the public key cached in your microservice, you will be able to validate the requesting JWT inside the service that is being requested.

Then whenever a request comes into one of your microservices, the library you import will examine the requesting JWT, check its validity, and grant access/authorization if the token is valid. The beauty of using a private/public key pair and asymmetric key signing is that you can validate a token based on the public key alone, but not sign it. So as long as each service has the public key from your /cert endpoint, they can validate a token without ever needing to talk to the auth server or knowing the private key.

This will require a little more work up front, but will yield you massive amount of ease, flexibility, and peace of mind in the future knowing only one source knows your private key.

enter image description here

Sign up to request clarification or add additional context in comments.

3 Comments

Disadvantage of this sort of common library, is that any changes to the library cause all microservices needing to pull the upgrades + redeployed. This is not needed when you just call an auth micro-service.
@Chappie Johnson can you please provide some link or demo project which describe same flow well manner?
Easy if all your microservices use the same backend language, but a lot of work if they don't. Usually it's desirable to leverage the best language for each service, that's one of the nice things about microservices
12

One common pattern here would be to use an API gateway as the entry point to your entire microservice architecture. Incoming requests for authentication would be routed to the appropriate microservice. If the credentials provided be correct, a new JWT would be returned to the gateway, which would then forward to the caller. For the actual microservice APIs which comprise your application, the gateway would check that the incoming JWT be valid before allowing the request to hit the microservice.

This answer leaves out a few things, for simplicity. For instance, often you would want to have an authorization microservice, which decides what a user is allowed to do. Also, implementing JWT can be involved. You might need a cache layer to keep track of whitelisted and/or blacklisted JWT.

1 Comment

Wouldn't it cause a bottleneck in a single API gateway?
0

Here is the solution I came up with, to handle user data we can implement an Identity Provider Service (IDP) which is responsible for signing JWTs with symmetrical keys (rs256) and storing user information. The Identity Provider also has an open endpoint which will expose the public key in the form of a JWK (JSON Web Key) which is used to sign the JWT, This endpoint can be used to validate issued keys by any other service (ideally the external service would cache the JWK to reduce traffic to the IDP).

But This also poses another issue, that is we will have to implement more code to validate the tokens with the JWK endpoint. This is where an API Gateway comes in, The API gateway sits between the frontend client and the API server acting as a checkpoint. The API Gateway caches the JWK using the IDP endpoint and validates all the incoming requests. This means we would only have to implement features like JWK validation, rate-limiting, and SSL only to the API Gateway and we will not have to rely on the internal services for implementing these. Plus another improvement to the API Gateway would be to write the decoded JWT data onto the headers so the API Gateway can pass the decoded data for example: x-jwt-email: [email protected] directly to the internal services.

I found inspiration for this implementation from various sources and this was one of the first system designs that have completed building so let me know if there are any loopholes or improvements that could be implemented.

The code for the above implementation can be found here:

Identity Provider

API Gateway

Comments

0

Backend service like Cart services should not know about the Auth Service to make it decouple and easy to switch to other authencation method like from 3rd.

So, here is the flows:

1/ User ---(user/pass)---> API Gateway ---(user/pass)----> Auth services 2/ User <-----(JWT)------- API Gateway <----(JWT)--------- Auth services 3/ User ------(JWT)------> API Gateway --(Gateway sign)--> Cart services 3/ User <----(resources)-- API Gateway <----(resources)--- Cart services 

At step 3, service just need to validate to make sure the call is coming from API Gateway. We can use any method like give another JWT to the Gateway signed with private key then Cart Service can validate using public key. (We can establish SSH tunel/VPN, whatever internal authencation method,... just make sure Cart service only accept the call from API Gateway or insiders).

By this way, we can easily to refresh the internal authencation (example Gateway JWT) to new one (generate new JWT when deploying) to enhance security. Also able to setup the another internal authencation to grant access to developer when doing development.

For the concern about how we can validate the request is come from resource owner, like Alice trying to get cart from Bob. From gateway, after validate the JWT is correct we can extract the user_id from user JWT to put to the request before forward it to Cart service.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.