node.jsapiexpressmicroservicesexpress-gateway

Express-gateway create new plugin / policy for express microservices application


I'm creating an express JS microservices architecture and I'm using express-gateway as an API gateway.

I can expose my services and endpoints through the express gateway , one of the services (Books) has 2 roles (admin, user) with 2 different login startegies (the admin uses JWT and the user uses Firebase auth).

I succeeded in security the admin endpoint /v1/admin with the JWT provided with express-gateway, now I want to create a policy / plugin (I didn't understand the difference) to involve my CheckIfAuthenticatedFirebase Middleware to secure my user endpoint /v1/user.

So I need some help to understand if I must create a plugin or a policy and the steps to do it.

Here is my gateway.config.yml :

http:
  port: 8080
admin:
  port: 9876
  host: localhost
apiEndpoints:
  bookAdmin:
    path: '/v1/admin*'
  bookUser:
    path: '/v1/user*'
serviceEndpoints:
  book:
    url: 'http://localhost:5000'
policies:
  - cors
  - log
  - proxy
  - jwt
  - request-transformer
pipelines:
  bookAdminPipeline:
    apiEndpoints:
      - bookAdmin
    policies:

      -
        cors:
          action:
            origin: '*'
            methods: 'GET,HEAD,PUT,PATCH,POST,DELETE'   
      -
        jwt:
          action:
            secretOrPublicKey: 'JWTKey'
            checkCredentialExistence: false

      -
        proxy:
          action:
            serviceEndpoint: book
  bookUserPipeline:
    apiEndpoints:
      - bookUser
    policies:

      -
        cors:
          action:
            origin: '*'
            methods: 'GET,HEAD,PUT,PATCH,POST,DELETE'   
      -
        proxy:
          action:
            serviceEndpoint: book

Here is my firebase-middleware.js :

var admin = require('../authentication/firebase');

 getAuthToken = (req, res, next) => {
    if (
      req.headers.authorization &&
      req.headers.authorization.split(' ')[0] === 'Bearer'
    ) {
      req.authToken = req.headers.authorization.split(' ')[1];
    } else {
      req.authToken = null;
    }
    next();
  };


checkIfAuthenticated = (req, res, next) => {
   getAuthToken(req, res, async () => {
      try {
        const { authToken } = req;
        const userInfo = await admin
          .auth()
          .verifyIdToken(authToken);
        req.authId = userInfo.uid;
        return next();
      } catch (e) {
        return res
          .status(401)
          .send({ error: 'You are not authorized to make this request' });
      }
    });
  };

  module.exports = checkIfAuthenticated

Thanks a lot


Solution

  • You have to create a policy and invoke it via plugin.

    1. Make a folder in your plugins directory, let's say folder name is auth.
    2. inside that auth folder, create a folder policies and a file manifest.js
    3. create a file auth.js inside policies folder.
    4. inside manifest.js write this piece of code
    module.exports = {
            version: '1.2.0',
            init: function (pluginContext) {
               let policy = require('./policies/auth')
               pluginContext.registerPolicy(policy)
            },
            policies:['auth'], // this is for CLI to automatically add to "policies" whitelist in gateway.config
            schema: {  // This is for CLI to ask about params 'eg plugin configure customer-auth'
                "$id":"https://express-gateway.io/schemas/plugins/blacklist.json"
            }
        }
    
    1. Your auth.js file should look like this
    module.exports = {
      name: 'auth',
      schema: {
        $id: 'http://express-gateway.io/schemas/policies/example-policy.json',
        type: 'object',
        properties: {
          baseUrl: {
            type: 'string',
            format: 'url',
            default: ''
          }
        }
      },
      policy: (actionParams) => {
        const that = this;
        return (req, res, next) => {
          // your custom logic
    
        };
      }
    };
    

    Now you just have to put the manifest path in the system.config.yml

    plugins:      
      auth:
        package: "../../../plugins/auth/manifest.js"
    

    And last step will be declaring this policy in the gateway.config.yml file in the policies section

    policies:
      - basic-auth
      - cors
      - expression
      - request-transformer
      - key-auth
      - log
      - oauth2
      - proxy
      - rate-limit
      - auth
    

    Now you can easily use it like any other policy. :)