Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Error: Headers Authorization forbidden" in CORS #2408

Closed
jonathanadler opened this issue Oct 31, 2018 · 6 comments
Closed

"Error: Headers Authorization forbidden" in CORS #2408

jonathanadler opened this issue Oct 31, 2018 · 6 comments

Comments

@jonathanadler
Copy link

Hey,

I have a test running with jsdom, in which i'm sending a cross-origin request with an Authorization header (i'm using nock to mock the server).
As expected, an OPTIONS preflight request is sent.
However i'm receiving an exception, saying that the Authorization header is forbidden in the preflight request.
Since i'm not controlling which headers are being sent in the preflight request, I have a feeling that this might be a bug.

So I searched the code a bit, and tried to debug this, and I encountered this line of code:

const forbiddenHeaders = Object.keys(flag.requestHeaders).filter(header => {

It seems that in the validCORSPreflightHeaders function, the original request headers are being validated instead of the preflight headers.

Is this correct? Or am I missing something?

@domenic
Copy link
Member

domenic commented Oct 31, 2018

Can you provide a minimal example to reproduce this issue, per the issue template? Including important information like the versions in use, etc. We can't really debug based on this description.

@jonathanadler
Copy link
Author

jonathanadler commented Oct 31, 2018

@domenic Of course

I'm working with versions:

  • node v8.9.1
  • npm v5.5.1

This is a simple example, that's closest to what i'm working on:

I have a package.json file of:

{
  "name": "testing",
  "version": "1.0.0",
  "description": "",
  "main": "",
  "scripts": {
    "test": "jest test.js"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "axios": "^0.18.0",
    "jest": "^23.6.0",
    "nock": "^10.0.1"
  },
  "jest": {
    "testEnvironment": "jsdom"
  }
}

And a test.js file like this:

const nock = require('nock');
const axios = require('axios');

const HOST = 'http://localhost';
const PORT = '3333';
const somePath = '/some/path';

describe('jsdom cors', function () {
    const response = {foo: 'bar'};
    const headers = {
        'Authorization': 'Bearer someAccessToken',
    };

    beforeEach(() => {
        nock(`${HOST}:${PORT}`)
        .options(somePath)
        .reply(200, null, {'Access-Control-Allow-Origin': HOST})
        .get(somePath)
        .matchHeader('Authorization', headers['Authorization'])
        .reply(200, response, {'Access-Control-Allow-Origin': HOST});
    });

    afterEach(() => {
        nock.cleanAll();
    });

    it('should pass', done => {
        var request = {
            method: 'GET',
            url: `${HOST}:${PORT}${somePath}`,
            headers,
            timeout: 0
        };

        axios(request)
        .then(resp => {
            expect(resp.data).toBeEqual(response);
            done();
        }).catch();
    });
})

Running npm test gives me the error:

 FAIL  ./test.js
  jsdom cors
    ✕ should pass (37ms)

  ● jsdom cors › should pass

    Network Error

      at createError (node_modules/axios/lib/core/createError.js:16:15)
      at XMLHttpRequest.handleError (node_modules/axios/lib/adapters/xhr.js:87:14)
      at XMLHttpRequest.el.addEventListener.event (node_modules/jsdom/lib/jsdom/living/helpers/create-event-accessor.js:33:32)
      at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:193:27)
      at XMLHttpRequestEventTargetImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:119:9)
      at XMLHttpRequestEventTargetImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:82:17)
      at XMLHttpRequest.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:157:21)
      at requestErrorSteps (node_modules/jsdom/lib/jsdom/living/xhr-utils.js:132:7)
      at dispatchError (node_modules/jsdom/lib/jsdom/living/xhr-utils.js:62:3)
      at validCORSPreflightHeaders (node_modules/jsdom/lib/jsdom/living/xhr-utils.js:102:5)
      at Request.preflightClient.on.resp (node_modules/jsdom/lib/jsdom/living/xhr-utils.js:380:12)
      at Request.onRequestResponse (node_modules/request/request.js:1066:10)
      at _respond (node_modules/nock/lib/request_overrider.js:525:17)
      at respond (node_modules/nock/lib/request_overrider.js:508:11)

  console.error node_modules/jsdom/lib/jsdom/virtual-console.js:29
    Error: Headers Authorization forbidden
        at dispatchError (/Users/jonathana/Projects/testing/node_modules/jsdom/lib/jsdom/living/xhr-utils.js:65:19)
        at validCORSPreflightHeaders (/Users/jonathana/Projects/testing/node_modules/jsdom/lib/jsdom/living/xhr-utils.js:102:5)
        at Request.preflightClient.on.resp (/Users/jonathana/Projects/testing/node_modules/jsdom/lib/jsdom/living/xhr-utils.js:380:12)
        at emitOne (events.js:116:13)
        at Request.emit (events.js:211:7)
        at Request.onRequestResponse (/Users/jonathana/Projects/testing/node_modules/request/request.js:1066:10)
        at emitOne (events.js:116:13)
        at OverriddenClientRequest.emit (events.js:211:7)
        at _respond (/Users/jonathana/Projects/testing/node_modules/nock/lib/request_overrider.js:525:17)
        at respond (/Users/jonathana/Projects/testing/node_modules/nock/lib/request_overrider.js:508:11) undefined

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        1.589s, estimated 2s
Ran all test suites matching /test.js/i.
npm ERR! Test failed.  See above for more details.

I hope I didn't forget anything.
I'd be happy to give more information if missing.
I'm kind of a newbie here, sorry.

@Zirro
Copy link
Member

Zirro commented Oct 31, 2018

It would help if you could create a test case using the latest version of jsdom (the version currently used in Jest is older), preferably without the other dependencies (axios, jest and nock). That would make it easier to test how the same code behaves in a browser.

@jonathanadler
Copy link
Author

After trying to duplicate the error without axios and nock, i've resolved the issue.
I have forgotten to add the header: 'access-control-allow-headers': 'Authorization' in my response from the server.

Sorry for taking your time, and thanks for your help.

@worc
Copy link

worc commented Apr 8, 2019

this might also be related to a test server setup that has access-control-allow-headers: * with the wildcard. i'm not seeing that jsdom supports wildcards when trying to validate the CORS preflight headers.

@alexjball
Copy link

alexjball commented Dec 6, 2019

If you don't control the server endpoint you can swap out the fetch implementation to use node-fetch, which handles access-control-allow-headers: * correctly:

import nodeFetch from "node-fetch";
window.fetch = nodeFetch;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants