MEAN stack error Authorization error: no "Access-Control-Allow-Origin" header?

I am trying to do facebook authorization in my MEAN stack application. I am using passport

and passport-facebook

. I am not using jade

or ejs

, I want to use pure angular. When I launch my application and click the Login button, I get the following error:

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

      

I did some research and found that the node module cors

can fix this, but it doesn't.

What did I do wrong and how can I fix it?

Here is my routes.js file (server side):

app.get('/auth/facebook', passport.authenticate('facebook'));

app.get('/auth/facebook/callback', passport.authenticate('facebook', {
    successRedirect: '/success',
    failureRedirect: '/error'
}));

app.post('/success', function(req, res, next) {
    User.findById(req.session.passport.user, function(err, user) {
        if(err){ 
            res.send({success:false}); 
        }else{ 
            res.send({success:true,user: user});
        }
    });
});

app.get('/logout', function(req, res){
    req.logout();
    res.redirect('/');
    res.end();
});

app.post('/error', function(req, res, next) {
    res.send({success:false});
});

      

Here is my file passport.js

(server side):
Note. clientID

, clientSectret

and callbackURL

are in another file ( config.js

). But they are valid.

passport.use(new FacebookStrategy({
    clientID: config.facebookAuth.clientID,
    clientSecret: config.facebookAuth.clientSecret,
    callbackURL: config.facebookAuth.callbackURL
    },
    function(accessToken, refreshToken, profile, done) {
        User.findOne({ oauthID: profile.id }, function(err, user) {
            if(err) { console.log(err); }
            if (!err && user != null) {
                done(null, user);
            } else {
                var user = new User({
                    oauthID: profile.id,
                    name: profile.displayName,
                    created: Date.now()
                });
                user.save(function(err) {

                    if(err) {
                        console.log(err);
                    } else {
                        console.log("saving user ...");
                        done(null, user);
                    }
                });
            }
        });
    }
));


// serialize and deserialize
passport.serializeUser(function(user, done) {
    console.log('serializeUser: ' + user._id)
    done(null, user._id);
});
passport.deserializeUser(function(id, done) {
    User.findById(id, function(err, user){
        console.log(user)
        if(!err) {done(null, user);}
        else {done(err, null)}
    });
});

      

And here is my express config file: express.js

(server side):

var express = require('express'),
    passport = require('passport'),
    cookieParser = require('cookie-parser'),
    bodyParser = require('body-parser'),
    session = require('express-session'),
    cors = require('cors');

var whitelist = ['https://www.facebook.com'];
var corsOptions = {
  origin: function(origin, callback){
    var originIsWhitelisted = whitelist.indexOf(origin) !== -1;
    callback(null, originIsWhitelisted);
  }
};

module.exports = function (app, config) {
    app.set('view engine', 'ejs');
    app.use(cookieParser());
    app.use(bodyParser());
    app.use(cors(corsOptions));
    app.use(session({secret:"car advisor secret"}));
    app.use(passport.initialize());
    app.use(passport.session());
    app.use(express.static(config.rootPath+"/public"));
}

      

CLIENT SIDE

Here is my html file:

<body>
    <div class="navbar-right" ng-controller="LoginCtrl">
        <form class="navbar-form" >
            <a class="btn btn-primary" ng-click="signin()" ng-show="!identity.isAuthenticated()">Sign in</a>
            <a class="btn btn-primary" ng-click="signout()" ng-show="identity.isAuthenticated()">Sign out | {{identity.currentUser.name}}</a>
        </form> 
    </div>
    <ng-view></ng-view>

      

Here is my login controller:

$scope.signin = function(username, password) {
    authService.authenticateUser(username, password).then(function(success) {
        if (success){
            console.log("You have successfully signed in!");
        }
    });
}

$scope.signout = function() {
    authService.logoutUser().then(function() {
        console.log("You have successfully signed out!");
        $location.path('/');
    });
}

      

And here is my service that handles communication with the server (authService.js):

carApp.factory('authService', function($http, Identity, $q, $cookieStore, $resource) {
return {
    authenticateUser: function(username, password) {
        var dfd = $q.defer();
        $http.get('/auth/facebook').
            success(function(data, status, headers, config) {
                if (data.success) {
                    Identity.currentUser = response.data.user;
                    $cookieStore.put('user', response.data.user);
                    dfd.resolve(true);
                } else {
                    $cookieStore.remove('user');
                    dfd.resolve(false);
                }
            });
        return dfd.promise;
    },
    logoutUser: function() {
        var dfd = $q.defer();
        $http.get('/logout').success(function() {
            Identity.currentUser = undefined;
            $cookieStore.remove('user');
            dfd.resolve();
        });
        return dfd.promise;
    }

      

+3


source to share


3 answers


You cannot make ajax request to another address. Even if the address is the same and the port is different, you will have problems with the same initial policy.

You can do this with nginx and redirect the request with proxy_pass

.

Check: http://distinctplace.com/infrastructure/2013/10/14/internal-redirect-to-another-domain-with-proxy_pass-and-nginx/



something like

server
{
  listen 80; 
  server_name localhost;

  location /auth/facebook/request {
    proxy_pass http://(...)facebook.com/(...);
  }
}

      

0


source


I'm not sure if this solves your problem, but I recently went through something similar while trying to make facebook login to angular app. make sure on facebook app settings page,

https://developers.facebook.com/apps/{your_app_id}/settings/   

      



change the "site url" to whatever your local site is. For example:

http://localhost:8080/

      

+2


source


Hi I'm not sure if this help will help you.

    app.config(['$httpProvider', function ($httpProvider){
      $httpProvider.defaults.useXDomain = true;
   // $httpProvider.defaults.cache = true;
      $httpProvider.defaults.withCredentials = true;
   // $httpProvider.defaults.xsrfCookieName = '';
   // $httpProvider.defaults.xsrfHeaderName = '';
      delete $httpProvider.defaults.headers.common['X-Requested-With'];
}]);

      

+1


source







All Articles