Search code examples
node.jsexpressexpress-jwtjwt

How do I calling API to multi micro-services but only authenticate once time and calling independently?


I have 2 microservices, MicroserviceA is a core service including authentication and authorization services and other APIs services. MicroserviceB includes several other APIs (not including authentication and authorization) MicroserviceA include some API likes this:

localhost:3000/api/login (by JWT)
localhost:3000/api/postA
localhost:3000/api/getA
localhost:3000/api/deleteA
localhost:3000/api/pushA

MicroserviceB include some API like this:

localhost:3001/api/postB
localhost:3001/api/getB
localhost:3001/api/deleteB
localhost:3001/api/pushB

My front-end only calls only 1 based url is: http: // localhost: 3000, so I do like that, to communicate between 2 microservices, I am using axios to call from core MicroserviceA to MicroserviceB So in MicroserviceA, I have the following APIs:

localhost:3000/api/login (JWT)
localhost:3000/api/postA
localhost:3000/api/getA
localhost:3000/api/deleteA
localhost:3000/api/pushA
localhost:3000/api/postB (axios call)
localhost:3000/api/getB (axios call)
localhost:3000/api/deleteB (axios call)
localhost:3000/api/pushB (axios call)

But the problem is that when I want to call some APIs from MicroserviceB, I have to call it from MicroserviceA. Is there any way that frond-end dev only needs to authenticate once but can call APIs independently from MicroserviceA and MicroserviceB without having to call twice as my way?


Solution

  • MicroserviceB will also need to implement JWT authentication. It doesn't need to implement the login method, you have MicroserviceA responsible for that, it only needs to validate the token. As long as both MicroserviceA and MicroserviceB share the same secret the token can be validated on both.

    Your main protection is your application's secret used to sign the tokens. This is essentially your private key so ideally use some algorithm/password generator to generate it and make sure nobody else have access to it.

    Ideally your JWT token would include some way of linking to the user in its payload such as the user id or email etc. With careful planning it's even possible to not need to make a database request to fetch the user - your endpoints should be able to use the JWT payload to identify the user/role/permissions etc.

    Say for example microserviceA implements a /login endpoint that returns the token in a JSON response. So to login you'd do something like:

    fetch('/login', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        },
        body: 'email=' + email + '&password=' + password
    })
    .then(response => response.json())
    .then(result => {
        localStorage.setItem('jwt', result.token); // save token somewhere
    });
    

    Then to make a request to microserviceB you just need to add the authorization header:

    fetch('http://microserviceB.com/do/something', {
        headers: {
            'Authorization': localStorage.getItem('jwt')
        }
    })
    .then(processResponseFromMicroserviceB);
    

    You can validate the jwt token in microserviceB the same way you did in microserviceA but you don't need to implement the login part.