ExpressGateway / express-gateway

A microservices API Gateway built on top of Express.js
https://www.express-gateway.io
Apache License 2.0
2.97k stars 344 forks source link

Changing/Modifying header in custom policy #938

Closed josemf closed 5 years ago

josemf commented 5 years ago

I've a custom policy for JWT authorization and I'm trying to modify the Authorization header so headers send to proxy include said Authorization header.

Flow: App -> Sends request with JWT Authentication: Bearer xxxxx Gateway Custom Policy -> call web service for JWT token authorization, changes header Authorization: apiKey yyyyyy (provided by the web service) Gateway Proxy -> proxies to service endpoint that expects header Authorization: apiKey yyyyy schema Service Endpoint API -> reads header Authorization: apiKey yyyyy

Policy


const axios = require('axios');

module.exports = {
    name: 'swl-business-auth',
    schema: {
        $id: 'http://express-gateway.io/schemas/policies/swl-business-auth.json',
        type: 'object',
        properties: {
            baseUrl: {
                type: 'string',
                format: 'url',
                default: 'https://example.com'
            }
        }
    },
    policy: (actionParams) => {
        return async (req, res, next) => {

            axios.get('/proctor/auth', { headers: req.headers, baseURL: process.env.GW_BUSINESS_URL })
                .then(function (response) {

                    if(!response.data.tenant || !response.data.tenant.apiKey) {
                        res.status(401);
                        res.json({
                            status: "NOK",
                            message: "Unauthorized",
                            error: "unauthorized"
                        });
                        return;
                    }

                    // Changing doesn't work
                    req.headers["Authorization"] = "apiKey " + response.data.tenant.apiKey;

                    // Deleting doesn't work
                    delete req.headers["X-App-Authorization"];

                    // Adding DOES work
                    req.headers["X-Authorization"] = "apiKey " + response.data.tenant.apiKey;

                    next();
                })
                .catch(function (error) {

                    res.status(401);
                    res.json({
                        status: "NOK",
                        message: "Unauthorized",
                        error: "unauthorized"
                    }); 
                });
        };
    }
};

gateway.config.yml

http:
  port: ${GW_PORT}
admin:
  port: 9876
  host: localhost

apiEndpoints:
  getTestsAPI:
    host: ${GW_HOST}
    paths: '/test'

serviceEndpoints:  
  scantronServices:
    url: ${GW_SCANTRON_URL}

policies:
  - key-auth
  - proxy
  - swl-business-auth

pipelines:
  - name: getTests
    apiEndpoints:
      - getTestsAPI
    policies:
      - key-auth:
          -
            action:
              apiKeyHeader: ${GW_API_AUTH_HEADER}
              disableQueryParam: true

      - swl-business-auth:
      - proxy:
        - action:
            serviceEndpoint: scantronServices
            changeOrigin: true

I've based some of the code in the Request Transformer code https://github.com/ExpressGateway/express-gateway/tree/master/lib/policies/request-transformer. For some reason request header deletion is not working...

Also is there a way to modify an existing request header?

XVincentX commented 5 years ago

Hey,

  1. What do you mean by "does not work"? Do you still see the header In place?
  2. Instead of writing this whole custom policy — you could basically write a minimal policy saving the values in the req.egContext object and then use the Request Transformer to add the required values as headers and remove the one that are not necessary.

In this way you'll leverage EG's stuff and not reinvent the wheel.

josemf commented 5 years ago

Hey Vincent,

  1. Yes it didn't work, not sure why. I checked whatever headers where hitting the service endpoint.
  2. This is a fine suggestion.

Thank you!