Search code examples
corsaws-api-gatewayfetch-apipreflightlambda-authorizer

CORS custom header stripped from request


I'm using a token based lambda authorizer as described here: https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html

Right now I'm still using the toy example where the header prop is tokenHeader

My fetch is as follows:

export function logout() {
    return (dispatch, getState) => {
      return fetch('https://account-api.example.com/v1/logout', {
        method: 'GET',
        headers: {
          'Access-Control-Request-Method': 'GET',
          'Access-Control-Request-Headers': 'Content-Type, Authorization',
          'Content-Type': 'application/json',
          'tokenHeader':'allow',
        },
        credentials: 'include'
      })
        .then((response) => {
          return response.json().then((body) => {
            return {
              status: body.statusCode,
              payload:body.payload,
            };
          },
          );
        })
        .then((response) => {
          console.log("response", response)
          if (response.status !== 200) {
            dispatch({ type: 'LOGOUT_ERROR', payload: response.payload.error});
          }
          if (response.status === 200) {
            dispatch({ type: 'LOGOUT_SUCCESSFUL', payload: response.payload });
          }
        })
        .catch(error => {
          dispatch({ type: 'LOGOUT_FAILED', payload: String(error)});
        })
    };
  }

When I look at the network tab the 'tokenHeader':'allow' header is missing from my request, resulting in a 401 from the authorizer - what do I need to do to prevent this header from being stripped?

request is missing tokenHeader header

Side Note: This request works in postman

API Gateway Configurations (Not sure if this is relevant):

OPTIONS
Request OPTIONS Method Request Response OPTIONS Integration Response

GET
Request GET Method Request Response GET Integration Response

I don't want to ignore CORS and am sending data between account-api.example.com and dev.example.com so please no answers indicating to remove/ignore cors -- my goal is to properly implement cors.


Solution

  • The details in the question show that the custom header isn’t being sent in the CORS preflight OPTIONS request. That’s expected — any custom headers you set in your frontend code won’t be included in the CORS preflight OPTIONS request. There’s no way you can prevent that behavior.

    So the bottom line is: if you use an authentication mechanism that relies on a particular header being added to requests, you need to configure the server to not require that custom header for OPTIONS requests — because the CORS protocol requires servers to allow OPTIONS requests without any authentication.

    In more detail, what’s happening is this:

    1. Your code’s telling your browser it wants to send a request with a custom tokenHeader header.
    2. Your browser says, OK, requests with a tokenHeader header require me to do a CORS preflight OPTIONS to make sure the server allows requests with the tokenHeader header.
    3. Your browser sends the OPTIONS request to the server without the tokenHeader header, because the whole purpose of the OPTIONS check is to see if it’s OK to include that header.
    4. Your server sees the OPTIONS request but instead of responding to it in a way that indicates it allows the tokenHeader header in requests, it rejects it with a 401 since it lacks the header.
    5. Your browser expects a 200 or 204 response for the CORS preflight but instead gets that 401 response. So your browser stops right there and never tries the GET request from your code.