Pytanie req.session.passport jest pusty, deserializeUser nie jest wywoływany - ExpressJS, Passport


Mam problemy z używaniem sesji w Passport / ExpressJS.

Kiedy się loguję req.session, Widzę, że paszport jest {}:

{ cookie: 
 { path: '/',
  _expires: Mon Sep 29 2014 19:37:16 GMT-0300 (BRT),
  originalMaxAge: 3594522,
  httpOnly: true,
  secure: true },
passport: {} }

Ponadto uwierzytelniam się z Facebookiem i passport.deserializeUser nie jest wywoływany. To jest mój kod:

    passport.use(new FacebookStrategy({

    // pull in our app id and secret from our auth.js file
    clientID        : configAuth.facebookAuth.clientID,
    clientSecret    : configAuth.facebookAuth.clientSecret,
    callbackURL     : configAuth.facebookAuth.callbackURL

},

// facebook will send back the token and profile
function(token, refreshToken, profile, done) {

    // asynchronous
    process.nextTick(function() {

        console.log("profile " + profile.id);
        console.log("profile.name "+profile.name.givenName)

        // find the user in the database based on their facebook id
        User.findOne({ 'facebook.id' : profile.id }, function(err, user) {

            // if there is an error, stop everything and return that
            // ie an error connecting to the database
            if (err)
                return done(err);

            // if the user is found, then log them in
            if (user) {
                //returning undefined
                //console.log(user.name + " " + user.email);
                return done(null, user); // user found, return that user
            } else {
                // if there is no user found with that facebook id, create them
                var newUser = new User();

                // set all of the facebook information in our user model
                newUser.facebook.id    = profile.id; // set the users facebook id
                newUser.facebook.token = token; // we will save the token that facebook provides to the user
                newUser.facebook.name  = profile.name.givenName + ' ' + profile.name.familyName; // look at the passport user profile to see how names are returned
                newUser.facebook.email = profile.emails[0].value; // facebook can return multiple emails so we'll take the first

                // save our user to the database
                newUser.save(function(err) {
                    if (err)
                        throw err;

                    // if successful, return the new user
                    return done(null, newUser);
                });
            }

        });
    });

}));

// used to serialize the user for the session
passport.serializeUser(function(user, done) {
    console.log("serialize");
    done(null, user.id);
});

// used to deserialize the user
passport.deserializeUser(function(id, done) {
    console.log("deserialize");
    User.findById(id, function(err, user) {
        console.log(user);
        done(err, user);
    });
});

Próbowałem przenieść obie metody na początek, ale nie miało to znaczenia. passport.serializeUser nazywa się dobrze.

To tutaj inicjuję passport:

app.use (cookieParser());
app.use(session({ secret: 'appsecret', saveUninitialized: true, cookie: { secure: true, maxAge: new Date(Date.now() + 3600000) }, key:'connect.sid' }));

app.use(passport.initialize());
app.use(passport.session());

I to jest mój route:

// =====================================
// 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'
    }));

Czy ktoś może mi w tym pomóc?

Dzięki!


13
2017-09-29 21:55


pochodzenie


Czy możesz nam pokazać kod, w którym zainicjowano Passport? Ludzie często zapominają go zainicjować lub zrobić w złej kolejności. Powinien zostać zainicjowany w następujący sposób: app.use(express.session({ secret: 'keyboard cat' })); app.use(passport.initialize()); app.use(passport.session());  Czy mógłbyś nam pokazać kod trasy uwierzytelniania? - Waldo Jeffers
Edytowane w pytaniu :) - Larissa Leite
Ok, wszystko wydaje mi się w porządku. Głupie pytanie: powiedziałeś to passport jest pusty po wylogowaniu req.session. Gdzie (w kodzie) zrobiłeś to? Powiedziałeś też passport.serializeUser nazywa się dobrze., ale co się dzieje, gdy próbujesz zalogować się user param? - Waldo Jeffers
Loguję się w app.get ("/ home"), która jest trasą wywoływaną, gdy uwierzytelnianie zakończy się powodzeniem. użytkownik jest niezdefiniowany - Larissa Leite
@LarissaLeite Czy rozwiązałeś to? - Daniel Kmak


Odpowiedzi:


tło

Dla mnie problem z deserializeUser nie jest wywoływany i pusty obiekt paszportowy był problem z wieloma domenami. Kiedy wysyłałem żądanie ajax z localhost: 4200 do localhost: 1000 ciasteczek i sesje nie działały dla mojego klienta Ember.js. Jednak rozszerzenie listonosza otrzymało prawidłową odpowiedź. Również obiekt paszportowy został poprawnie wypełniony danymi. User.deserializeUser został poprawnie wywołany.

Rozwiązanie

Aby rozwiązać ten problem, musiałem ustawić poprawne nagłówki HTTP po stronie serwera i klienta. Server-side (node.js + express + paszport):

# The important part. Must go AFTER the express session is initialized
app.use passport.initialize()
app.use passport.session()

# Enable CORS
# X-Requested-With, X-AUTHENTICATION, X-IP
# https://stackoverflow.com/a/18290875/2166409
app.use (req, res, next) ->
  res.header 'Access-Control-Allow-Origin', 'http://localhost:4200'
  res.header 'Access-Control-Allow-Headers', 'Origin, X-Requested-With, X-AUTHENTICATION, X-IP, Content-Type, Accept'
  res.header 'Access-Control-Allow-Credentials', true
  res.header 'Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'
  next()

app.use '/api/v1', router

Strona klienta:

Jeśli używasz jQuery dodaj to do opcji $ .ajax:

xhrFields: { withCredentials:true }

Wtedy wszystko działa zgodnie z oczekiwaniami:

DESERIALIZE USER
{ id: '547fabf22a098ade53e6e48e',
  name: 'test',
  firstName: 'test',
  email: 'test@wp.pl' }
LOGIN SUCCESS SESSION
{ cookie: 
   { path: '/',
     _expires: Thu Dec 04 2014 20:26:52 GMT+0100 (CET),
     originalMaxAge: 3597205,
     httpOnly: false },
  passport: 
   { user: 
      { id: '547fabf22a098ade53e6e48e',
        name: 'test',
        firstName: 'test',
        email: 'test@wp.pl' } } }

Te odpowiedzi pomogły mi: o Ember.js, jQuery.ajax.


8
2017-12-04 18:41



Możesz sprawdzić, czy jest problem z cors, zaglądając do konsoli js, a następnie przezwyciężyć ją w rozwoju przy użyciu flagi -disable-web-security w przeglądarce. - Ashok Kumar Sahoo
Jesteś moim przyjacielem, jesteś mężczyzną! - Arnaldo Capo


Dla mnie główną przyczyną była wartość bezpieczeństwa ciasteczek w sesji ekspresowej.

app.use(require('express-session')({
    secret: 'crackalackin',
    resave: true,
    saveUninitialized: true,
    cookie : { secure : false, maxAge : (4 * 60 * 60 * 1000) }, // 4 hours
}));

Na moim komputerze lokalnym nie korzystałem z protokołów HTTP, więc gdy cookie.secure jest prawdziwe, sesja i obiekt użytkownika były puste. W trybie deweloperskim i bezpiecznym było fałszem, działało poprawnie.


5
2018-05-17 23:43



Rozwiązało to dla mnie po wielu godzinach poszukiwań! Dzięki! - Olly
Zajęło mi tylko 1 godzinę poszukiwań, ale to rozwiązało to dla mnie, dzięki! - Francisco Presencia
Jesteś moim ratownikiem! Dzięki, Greg, próbowałem wyłączenia corsa i to nie działało, ale twoje rozwiązanie działało pięknie. - 이준형


Moim rozwiązaniem było konsekwentne łączenie różnych stron mojej witryny.

Przedrostek adresu URL linku za pomocą "www." podczas uwierzytelniania, gdzie nie ma "www". rozpocznie nową sesję podczas łączenia z tą stroną z prefiksem. Możesz to sprawdzić za pomocą przeglądarki plików cookie, sprawdź, czy dla każdej z dwóch opcji istnieje wiele plików cookie.


0
2017-12-05 10:55