Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
581 views
in Technique[技术] by (71.8m points)

angularjs - Angular/Node/Express/Passport Cross Domain Problems - Enable CORS Passport Facebook Authentication

It's been two days and a million tries to enable CORS when trying to authenticate a user with Facebook using Passport in NodeJS/Express.

The error I get on Chrome is this:

XMLHttpRequest cannot load https://www.facebook.com/dialog/oauth?response_type=code&redirect_uri=http%…%3A8080%2Fauth%2Ffacebook%2Fcallback&scope=email&client_id=598171076960591. 
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'http://localhost:8080' is therefore not allowed access. 

The routes I use are as simple as that:

// =====================================
// FACEBOOK ROUTES =====================
// =====================================
// route for facebook authentication and login

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

// handle the callback after facebook has authenticated the user
app.get('/auth/facebook/callback',
    passport.authenticate('facebook', {
        successRedirect : '/home',
        failureRedirect : '/login'
    }));

This is how the route is called on my angularJS file (I've also tried setting withCredentials : true):

$http.get('/auth/facebook')
    .success(function(response) {

    }).error(function(response){

    });

I've tried a dozen solutions that I found here on StackOverflow and other forums.

  1. I tried adding this on the before my routes on the routes.js files:

    app.all('*', function(req, res, next) {
      res.header('Access-Control-Allow-Origin', '*');
      res.header("Access-Control-Allow-Headers", "Content-Type,X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5,  Date, X-Api-Version, X-File-Name");
      res.header('Access-Control-Allow-Methods', 'GET,POST,PUT,HEAD,DELETE,OPTIONS');
      res.header('Access-Control-Allow-Credentials', true);
    
      if ('OPTIONS' == req.method) {
          res.send(200);
      } else {
          next();
      }
    });
    
  2. I tried adding this on server.js file (note that I changed header to setHeader but I've tried both):

    app.use(function(req, res, next) {
      res.setHeader('Access-Control-Allow-Origin', '*');
      res.setHeader('Access-Control-Allow-Headers', 'Content-Type,X-Requested-With');
      res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,HEAD,DELETE,OPTIONS');
      res.setHeader('Access-Control-Allow-Credentials', true);
    
      if ('OPTIONS' == req.method) {
        res.send(200);
      } else {
        next();
      }
    
     });
    
     require('./app/routes.js')(app, passport);
    
  3. I tried adding this on my app.js file (angularJS configurations):

    $httpProvider.defaults.useXDomain = true;
    delete $httpProvider.defaults.headers.common['X-Requested-With'];
    $httpProvider.defaults.withCredentials = true;
    

Anyway, I don't know what else to do. Everything I found online didn't work. Is there a chance it has something to do with me using AngularJS Routing? I don't see any reason why this would matter, but I kinda ran out of guesses.

My situation is very similar to this one: Angular/Node/Express/Passport - Issues when connecting to facebook(CORS)

Thanks in advance!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I was having this issue and almost reached the point where I was convinced I could find no solution, but looking at a simple tutorial again (http://mherman.org/blog/2013/11/10/social-authentication-with-passport-dot-js/) solved it for me. I was trying to make an API call from Angular to Node.js, which is going to always bring you those XMLHttpRequest errors despite what you configure on the server, CORS or not! CORS is not the fixture - if you opened your Chrome network console, you'll find that your request to Google or Facebook or whatever 3rd party site is out of your control to change - it was triggered from a 302 redirect that was sent back to your frontend, something that Angular.js or any other framework has no power to control, thus you can't really add "Access Control Allow Origin" to that request anyway.

The solution is simply to make the button or text that says "Sign In with _____" a LINK. A literal <a href="/auth/facebook"></a> link. That's it.

Of course, I also met with a lot of other stumbling blocks and gotchas in the process. I tried to not use the default middleware for passport.authenticate('facebook'), but tried to wrap it in a function(req, res, next){ ... }, thinking that would do something, but it doesn't.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...