1
votes

I can not access the "Authorization" header in each HTTP request on my Apollo-Server, implemented with express. Here is my setup of express, Apollo-Server, CORS, etc.

const corsConfig = {
  credentials: true,
  allowedHeaders: ['Authorization'],
  exposedHeaders: ['Authorization']
};

const app = express()

const server = new ApolloServer({
    schema,
    context: ({ req }) => {
      return {
        req
      };
    }
  });

server.applyMiddleware({
  app,
  path,
  cors: corsConfig
});

http.createServer(app).listen(port, () => logger.info(`Service started on port ${port}`));

And inside my resolvers, I bring in the context, particularly the req object (this is an example graphQL endpoint resolver):

const exampleQuery = async (parent, input , { req }) => {
    console.log(req.headers); 
    /*
    The output of this log:
      {
        'content-type': 'application/json',
         accept: '*/*',
        'content-length': '59',
        'user-agent': 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)',
        'accept-encoding': 'gzip,deflate',
         connection: 'close',
         host: 'localhost:3301',
        'Access-Control-Allow-Headers': 'Authorization',
        'Access-Control-Expose-Headers': 'Authorization'
    }

    */
}

I have sent requests to this endpoint, with an "Authorization" header, containing a token as the value. However, the Authorization header is not in the req.headers object (in fact, it's not in the entire req object either). I am certain that my Postman/Insomnia HTTP requests to this endpoint are sending out the Authorization header, however it seems to be not getting through my Apollo-Server. Anyone have any insight as to why the Authorization header is not going through?

SOLUTION:

The problem was actually that I am using an Apollo federated microservices architecture, which requires additional configuration on the gateway to pass the Authorization header onto the individual microservices, where the resolvers are. You have to add the buildService function inside the ApolloGateway constructor, where you specify that a RemoteGraphQLDataSource willSendRequest of context.req.headers.authentication to the underlying microservices

1
In your frontend JavaScript code, how are you setting the credentials mode? For example, with XHR, you need to set 'xhr.withCredentials = true' developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/…. And with the Fetch API you need to set "credentials: 'include'" developer.mozilla.org/en-US/docs/Web/API/Fetch_API/….sideshowbarker
@sideshowbarker right now I am not involving any front end code. I simply am sending a graphQL post request to that "exampleQuery" endpoint with Postman/Insomnia, with an "Authorization" header. My goal is to have access to that header in req.headers["Authorization"] inside exampleQuery.John Smith

1 Answers

0
votes

It works as expected, E.g.

server.ts:

import { ApolloServer, gql, makeExecutableSchema } from 'apollo-server-express';
import express from 'express';
import http from 'http';

const corsConfig = {
  credentials: true,
  allowedHeaders: ['Authorization'],
  exposedHeaders: ['Authorization'],
};

const typeDefs = gql`
  type Query {
    hello: String
  }
`;
const resolvers = {
  Query: {
    hello: (_, __, { req }) => {
      console.log(req.headers);
      return 'world';
    },
  },
};
const schema = makeExecutableSchema({ typeDefs, resolvers });

const app = express();
const path = '/graphql';
const port = 3000;
const server = new ApolloServer({
  schema,
  context: ({ req }) => {
    return {
      req,
    };
  },
});
server.applyMiddleware({ app, path, cors: corsConfig });

http.createServer(app).listen(port, () => console.info(`Service started on port ${port}`));

Send a GraphQL query HTTP request via curl:

curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer abc123" --data '{ "query": "{ hello }" }' http://localhost:3000/graphql
{"data":{"hello":"world"}}

Server-side logs:

Service started on port 3000
{ host: 'localhost:3000',
  'user-agent': 'curl/7.54.0',
  accept: '*/*',
  'content-type': 'application/json',
  authorization: 'Bearer abc123',
  'content-length': '24' }