authenticationjwtgateway

Misunderstanding about microservices authentication and authorization


I have three graphql microservices

My thoughts for implementation.

When a client (react-native app) send a request to register a user, the api gateway allows it to hit user-service without authentication. Once at the user-service, the user is created and token is issued and send back to the client. (This phase is okay for me).

The second phase is when the client send a request to travel-service that need to be authenticated. The request arrives at the api gateway, THE API GATEWAY SHOULD VALIDATE THE TOKEN BEFORE DIRECTING THE REQUEST TO THE CORRESPONDING SERVICE.

My Problem

If the api gateway must validate the token, it means that it will use the same library that issued token in user-service (jsonwebtoken) and it will check if the user sending the request belong to the user database which is located at the user service.

If the api gateway uses the user-service database, the separation of concern of microservices features is broken because the api gateway will use the same library the user-service uses to issue the token and it will hit the user-service database everytime a request arrives. (That is my thought)

is it the best practise to implement this ? or there is another best way to do.


Solution

  • A JSON Web token (JWT) has a couple of key parts. Importantly, it's normally cryptographically signed, so you can usually trust its contents. Its main content is a set of claims, which include an issuer (iss) for a second check on who issued it, an expiration time (exp), and the subject (sub) of the token – for whom it is valid.

    A typical approach I've seen here is for only one part of the system to issue an sign tokens; maybe it's your user service here. This produces a signed token, with a relatively short expiration time, a known issuer value, and a subject that encodes the specific user identity.

    The gateway in turn needs to validate the signature, check the expiration time, and check that the issuer string matches. The trick here is that these are all very typical JWT operations. You cite the jsonwebtoken Node library; these are essentially the options to jwt.verify(). A typical way to retrieve the public key is using the JSON Web Key Set (JWKS) format, and the jsonwebtoken includes a short example of using jwks-rsa to retrieve that. Copying their example exactly:

    // Verify using getKey callback
    // Example uses https://github.com/auth0/node-jwks-rsa as a way to fetch the keys.
    var jwksClient = require('jwks-rsa');
    var client = jwksClient({
      jwksUri: 'https://sandrino.auth0.com/.well-known/jwks.json'
    });
    function getKey(header, callback){
      client.getSigningKey(header.kid, function(err, key) {
        var signingKey = key.publicKey || key.rsaPublicKey;
        callback(null, signingKey);
      });
    }
    
    jwt.verify(token, getKey, options, function(err, decoded) {
      console.log(decoded.foo) // bar
    });
    

    The gateway does not need to separately validate the sub claim. It knows the user service has produced the token (with a valid signature) fairly recently, so the user ID is probably valid, unless the user has been deactivated in between them last logging in and the token expiring.