简体   繁体   中英

302 redirect after CORS preflight request to nodejs server

I try to build a platform, which consists of 2 separated parts, the backend and the frontend. The backend is powered by Express.js and Passport.js. It's available via localhost:3000. The frontend uses Googles polymer-1.0 and is running on localhost:8001.

I want to do all API stuff on my backend. The Ui calls and get data from the backend.

When try to do an iron-ajax request for authorization to my backend route, I'm getting a CORS error:

XMLHttpRequest cannot load http://localhost:3000/auth/facebook.
The request was redirected to 'https://www.facebook.com/v2.2/dialog/oauth?response_type=code&redirect_uri=…%3A3000%2Fauth%2Ffacebook%2Fcallback&scope=email&client_id=0815', 
which is disallowed for cross-origin requests that require preflight.

UI snippet:

iron-ajax
   id="login"
   url=""
   method="GET"
   headers='{"X-Requested-With": "XMLHttpRequest"}'
   handle-as="json"
   on-response="hresponse"
   debounce-duration="300">
/iron-ajax>


_handleTap: function () {
   var url = 'http://localhost:3000/auth/' + this.service;
   this.$.login.url = url;
   this.$.login.generateRequest();      
},

Backend snippet:

app.get('/auth/facebook', passport.authenticate('facebook', { scope: 'email' }));

app.get('/auth/facebook/callback', passport.authenticate('facebook'), function(req, res) {
        res.status(200).json({
            success: true,
            message: 'Enjoy!',
            redirect: '/route/to/nowhere',
        }).end();
    });

As you can see, I'm just using the simple Facebook auth snippet from passport.js documenation .

There were 2 request proceeded: PREFLIGHT:

RESPONSE
HTTP/1.1 200 OK
X-Powered-By: Express
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
Allow: GET,HEAD
Content-Type: text/html; charset=utf-8
Content-Length: 8
ETag: W/"8-8ww6QOmj5lyGjHVKXelZGQ"
Date: Tue, 26 Jan 2016 12:59:20 GMT
Connection: keep-alive

REQUEST
OPTIONS /auth/facebook HTTP/1.1
Host: localhost:3000
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: http://localhost:8001
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36
Access-Control-Request-Headers: accept, x-requested-with
Accept: */*
DNT: 1
Referer: http://localhost:8001/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4

GET:

RESPONSE
HTTP/1.1 302 Found
X-Powered-By: Express
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
Location: https://www.facebook.com/v2.2/dialog/oauth?response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauth%2Ffacebook%2Fcallback&scope=email&client_id=0815
Content-Length: 0
Date: Tue, 26 Jan 2016 12:59:20 GMT
Connection: keep-alive

REQUEST
GET /auth/facebook HTTP/1.1
Host: localhost:3000
Connection: keep-alive
accept: application/json
Origin: http://localhost:8001
x-requested-with: XMLHttpRequest
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36
DNT: 1
Referer: http://localhost:8001/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4

My node.js server also accepts CORS requests

app.use(function(req, res, next) {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
    next();
});

When using localhost:3000/auth/facebook as a link, I get my json response from the backend and on port 3000, but that is not what I want.

Is there a possibility to handle such API requests via an own API interface, like mine? Currently I see here a big show stopper.

Thanks & BR; andre

I think the issue has to do with redirection and CORS. Redirections with the status codes of 301, 302, 303, 307, or 308, will get you an error. This is being changed, but for now you need a workaround such as sending back the redirect URL in the response header or body, without using a redirect.

This is well explained in this reply

The only way for a user to authenticate with Facebook is if you actually send the user to Facebook. Doing an XMLHttpRequest won't work because there is no way for the user to login to their Facebook account, approve your application, etc. You must actually redirect the user's browser.

Change your _handleTap function to this:

_handleTap: function () {
  var url = 'http://localhost:3000/auth/' + this.service;
  window.location = url     
}

You need to add this middleware to all your request this way

 app.all('/*', function(req, res, next) { res.header('Access-Control-Allow-Origin', req.headers.origin || '*'); res.header('Access-Control-Allow-Methods', 'GET,POST,PUT,HEAD,DELETE,OPTIONS'); res.header('Access-Control-Allow-Headers', 'content-Type,x-requested-with'); next(); }); 

like explained here How to allow CORS in Express/Node.js?

This error basically means, the server is not accepting Cross Origin Requests (Requests from other domains). In express.js you can use a middleware to enable your server to do this.

var cors = require('cors');
app.use(cors());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM