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

Fetch Calls Removes Authorization Header #2020

Closed
matthias-b opened this issue May 15, 2019 · 8 comments
Closed

Fetch Calls Removes Authorization Header #2020

matthias-b opened this issue May 15, 2019 · 8 comments
Assignees
Milestone

Comments

@matthias-b
Copy link

This is a duplicate of #1822, and similar to the issue with xhr sandbox in #1016.

We use the Authorization header to pass our JWT token to our backend API. We use fetch, with mode: 'cors', and whitelist the Authorization header in the preflight response using access-control-allow-headers.

This works as expected under normal conditions, and chrome will issue a preflight and pass our Authorization header in the subsequent GET.

However, in hammerhead, the header is stripped out in transform.ts/transformAuthorizationHeader().

The server request then gets a 401, as it's unauthorized, and hammerhead gives a 222 response to the browser.

Curiously, there also doesn't appear to be a preflight, although both chrome and firefox issue one without the proxy in place. hammerhead should issue a preflight, as "the request includes any headers other than those which the Fetch spec defines as being a CORS-safelisted request-header"

The fix in #1016 was to prefix the header with AUTHORIZATION.valuePrefix, then strip it out during the header transforms. It looks like this would apply equally well to fetch as it does to xhr.

We also can't seem to find any combination of fetch params that will force hammerhead to issue a preflight.

@Farfurix
Copy link
Contributor

@matthias-b

We need some time to research the issue. We will get back to you as soon as we make progress.

@LavrovArtem
Copy link
Contributor

I cannot reproduce the behavior you described. Could you please modify my test server to show me the problem?

Server for reproducing:
const http = require('http');

http
    .createServer((req, res) => {
        if (req.url === '/') {
            res.writeHead(200, { 'content-type': 'text/html' });
            res.end(`
                <body>
                    <pre></pre>
                    <script>
                        fetch('http://localhost:2020/fetch', { method: 'GET', headers: { 'Authorization': '123' }, mode: 'cors' })
                            .then(r => r.json())
                            .then(j => document.body.firstElementChild.textContent = j.headers);
                    </script>
                </body>
            `);
        } else
            res.end();
    })
    .listen(2019, () => console.log('Please open http://localhost:2019'));

http
    .createServer((req, res) => {
        if (req.url === '/fetch') {
            if (req.method === 'OPTIONS') {
                res.writeHead(200, {
                    'access-control-allow-origin': 'http://localhost:2019',
                    'access-control-allow-methods': 'GET',
                    'access-control-allow-headers': 'Authorization'
                });
                res.end();
            } else {
                res.writeHead(200, {
                    'content-type': 'aplication/json',
                    'access-control-allow-origin': 'http://localhost:2019'
                });
                res.end(JSON.stringify({ headers: JSON.stringify(req.headers, null, '  ') }));
            }
        } else
            res.end();
    })
    .listen(2020);

@matthias-b
Copy link
Author

It seems to be a combination of using a new Request object, and setting the cache option. Replace line 11 with the following, and it will strip the authorization header.

fetch(new Request('http://localhost:2020/fetch', { method: 'GET', headers: { 'Authorization': '123' }, mode: 'cors' }), {cache: 'no-cache'})

@LavrovArtem
Copy link
Contributor

Thank you for the additional information. I've reproduced this issue.

@behlrattan
Copy link

Thanks @LavrovArtem for the fix. I see you made it part of Sprint which is due on 27th May so a new version will be available on 27th? Is that assumption correct? Cheers

@matthias-b
Copy link
Author

@LavrovArtem thanks for such a prompt fix! You are awesome.

After much trial and error, we implemented a simple workaround in the meantime, shifting our cache setting from the fetch to the request, like so:

fetch(new Request('http://localhost:2020/fetch', { method: 'GET', headers: { 'Authorization': '123' }, mode: 'cors', cache: 'no-cache' }))

@AndreyBelym
Copy link
Contributor

@behlrattan @matthias-b yes, we are going to release a new version.

@lock
Copy link

lock bot commented Jun 2, 2019

This thread has been automatically locked since it is closed and there has not been any recent activity. Please open a new issue for related bugs or feature requests. We recommend you ask TestCafe API, usage and configuration inquiries on StackOverflow.

@lock lock bot added the STATE: Auto-locked Issues that were automatically locked by the Lock bot label Jun 2, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Jun 2, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants