Вопрос по node.js, connect, passport.js, facebook – Использование PassportJS с Connect for NodeJS для аутентификации пользователей Facebook

6

Я пытаюсь интегрировать паспорт в мой сервер nodejs, используя connect, но, похоже, не могу сделать это правильно. Все руководства / примеры используют expressJS, поэтому я старался переформатировать код для работы с моим кодом, но, похоже, я не могу заставить его работать. Связанные части написаны ниже. Кто-нибудь есть какие-либо советы о том, в чем может быть проблема? passport.authenticate () никогда не вызывается (по крайней мере, сообщение console.log в обратном вызове аутентификации facebook никогда не печатается). В настоящее время я ничего не сохраняю в базе данных, поэтому, надеюсь, проблема должна быть чем-то действительно простым, чего я просто не вижу.

Единственное, что приходит на ум, - это потенциальный обратный вызов, который у меня есть для facebook, который является URL-адресом локального хоста (так как я все еще разрабатываю его локально). Я был в состоянии аутентифицироваться с Facebook очень хорошо, используя EveryAuth (из чисто локального экземпляра), но переключился на passportJS, так как у меня там были другие проблемы, которые, как представляется, passportJS решать.

passport = require('passport');
  fpass = require('passport-facebook').Strategy;

passport.serializeUser(function(user,done){
    done(null, user);
});
passport.deserializeUser(function(obj,done){
    done(null,obj);
});

passport.use(new fpass({
        clientID:'facebook app id',
        clientSecret:'facebook app secret',
        callbackURL:'http://localhost:3000/auth/facebook/callback'
    },
    function(accessToken, refreshToken, fbUserData, done){
        console.log('got here');
        return done(null,fbUserData);
    }
));



    function checkLoggedIn(req, res, next){
        console.log("req.user: " + req.user);
        if(req.user)
            next();
        else{
            console.log('\nNot LOGGED IN\n');
            if(req.socket.remoteAddress || req.socket.socket.remoteAddress == '127.0.0.1'){
                var folder,contentType;
                console.log('req url = '+req.url);
                if(req.url == '/'){
                    folder = __dirname + '/landingPage.html';
                    contentType = 'text/html';
                }
                else if(req.url == '/auth/facebook'){
                    passport.authenticate('facebook');
                    return;
                }
                else if(req.url == '/auth/facebook/callback'){
                    passport.authenticate('facebook', {failureRedirect: '/failbook', successRedirect:'/'});
                    return;
                }
                if(folder){
                    console.log('got to folder part\n\n');
                    fs.readFile(folder, function(error, content){
                      if(error){
                        res.writeHead(500);
                        res.end();
                      }
                      else{
                        res.writeHead(200, {'Content-Type': contentType});
                        res.end(content);
                      }
                    });
                  }
                    else{ res.writeHead(500); res.end();}
            }
            else {res.writeHead(500); res.end();}
        }
    }

  connect.createServer(
    connect.cookieParser(),
    connect.bodyParser(),
    connect.session({secret:'wakajakamadaka'}),
    passport.initialize(),
    passport.session(),
    checkLoggedIn).listen(8888);
  console.log('Server has started.');
}

У кого-нибудь есть какие-либо советы или видят сбои в том, что я делаю? Две другие мои альтернативы - это переключиться обратно на все и выяснить, что там происходит, или перейти на ExpressJS, но я бы не стал использовать ни одну из этих опций.

Лучший,
Сами

Ваш Ответ

1   ответ
8

passport.authenticate возвращает функцию, которая обычно используется в цепочке промежуточного программного обеспечения, которая вызывается сreq а такжеres Экспресс.

Он будет работать автономно внутри другого промежуточного программного обеспечения или обработчика маршрута, такого как вашcheckLoggedIn функция, но вы должны явно вызвать функцию, возвращенную сreq, res, а такжеnext чтобы он обработал запрос.

else if(req.url == '/auth/facebook'){
  // NOTE: call the function returned to process the request
  passport.authenticate('facebook')(req, res, next);
  return;
}

Хорошо выглядит в противном случае. Дайте мне знать, если это поможет вам.


UPDATE

Джаред немного помог мне выйти за пределы стекового потока, и мы полностью выяснили проблему. Я обновляю этот ответ, чтобы включить новую информацию, которую мы нашли.


1) Очевидно, одна проблема заключается в том, что промежуточное ПО redirect () существует в Express, но не в Connect (по крайней мере, не в текущей версии). При использовании connect вам нужно изменить строку 97 файла authenticate.js в модуле PassportJS сreturn res.redirect(options.successRedirect); чтобы:

var redirect = function(redirectionURL){
    res.writeHead(302, {'location':redirectionURL});
    res.end();             
}

return redirect(options.successRedirect);

Обратите вниманиеoptions.successRedirect выше так же, какsuccessRedirect в коде функции обратного вызова. Это будет линияpassport.authenticate('facebook', {failureRedirect: '/failbook', successRedirect:'/'}); в коде в моем вопросе.


2) Другое дело, что я использую модуль кластера в своем приложении (не то, что показано в моем фрагменте кода выше). Это означает, что данные сеанса неправильно читаются приложением nodeJS, что привело к моим проблемам.This problem will affect any library that relies on sessions, including all other authentication modules that use sessions (e.g. everyauth, connect-auth, etc.) Я процитирую Джареда для решения:

Quick reply: are you using cluster or spinning up multiple server instances?

If so, the built-in MemoryStore for the session won't work properly, and you need to switch to something like this: https://github.com/visionmedia/connect-redis

Or one of the other session stores listed here: https://github.com/senchalabs/connect/wiki

The reason is that you'll end up hitting a server which didn't serve the original request, and thus doesn't have that session information in its own memory. That sounds like what could be going on if deserializeUser isn't called 100% of the time.

Надеюсь, это поможет тому, кто сделает это здесь!

Паспорт должен вызывать ваши функции serializeUser / deserializeUser, если все работает правильно. Можете ли вы добавить туда лог-операторы, чтобы проверить, если это так, а также аргументы, которые он получает. Кроме того, мне любопытно, еслиfbUserData содержит информацию о пользователе после входа в систему. Дай мне знать это. Стремимся заставить вас работать!
хм, я становлюсь дальше, чем был раньше, но это еще не совсем работает. сейчас я регистрирую обратный звонок с Facebook. Я проверяю & / auth / facebook / callback & apos; против req.url.split ("?") [0], чтобы обратный вызов регистрировался. добавление (req, res, next) после вызова функции вызывает бесконечный цикл перенаправления. есть идеи? thisissami
очевидно, проблема заключается в том, что в connect больше нет промежуточного программного обеспечения redirect (), а в Express - нет. я заменил эту строку моей собственной возвращаемой функцией, которая выполняет то же самое. Данные на фейсбуке теперь работают должным образом, и стандарт & # apos; # _ = _ & apos; тот фейсбук возвращается до браузера. однако req.user по-прежнему не определен для будущих запросов. Любая идея относительно того, что может быть причиной этого? Должен ли я вызвать serializeUser в любой момент времени? thisissami
почти там ... с(req,res,next) добавленный в конец аутентификационного вызова обратного вызова, функция ответа facebook достигается с правильными данными facebook. Тем не менее, я получаюTypeError: Object #<ServerResponse> has no method 'redirect', Оскорбительная строка кодаreturn res.redirect(options.successRedirect); в строке 97 файла authenticate.js. Есть идеи, в чем может быть проблема? thisissami
Я думаю, вам нужно использоватьconnect.query() промежуточное ПО в вашемcreateServer установка промежуточного программного обеспечения. Паспорт ожидаетreq.query быть заполненным во многих случаях, включая получение кода авторизации в обратном вызове Facebook.

Похожие вопросы