web-dev-qa-db-fra.com

PassportJS: Comment obtenir req.user dans mes vues

J'utilise pssportjs avec Express 2.x et un stockage de sessions. Après une connexion, je ne reçois req.User qu'une seule fois. Dès que je redirige à nouveau req.User est indéfini.

Voici ma config:

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

passport.deserializeUser(function(userId, done) {
  User.findOne({_id: userId} ,function(err, user){
    done(err, user);
  });
});

// Authentication Strategy
passport.use(new FacebookStrategy({
    clientID: CONFIG.fb.appId,
    clientSecret: CONFIG.fb.appSecret,
    callbackURL: CONFIG.fb.callbackURL
  },
  function(accessToken, refreshToken, profile, done) {
    // asynchronous verification, for effect...
    process.nextTick(function () {

      User.findOne({ 'accounts.uid': profile.id, 'accounts.provider': 'facebook' }, function(err, olduser) {

          if(olduser) {
            done(null, olduser);
          } else {
            var newuser       = new User();
            var account       = {provider: "facebook", uid: profile.id};
            newuser.accounts.Push(account);
            newuser.firstname = profile.name.givenName;
            newuser.lastname  = profile.name.familyName;
            newuser.email     = "TBD...";

            newuser.save(function(err) {
              if(err) { throw err; }
              done(null, newuser);
            });
          }
        });
    });
  }
));

var app = module.exports = express.createServer();

// configure express
app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view engine', 'ejs');
  app.use(express.compiler({ src : __dirname + '/public', enable: ['less']}));
  app.use(express.cookieParser());
  app.use(express.bodyParser());
  app.use(express.methodOverride());

  //app.use(express.session({ secret: "keyboard cat" }));
  app.use(express.session({
    secret: "victory cat",
    store: new MongoStore({
      url: CONFIG.dbMongo.url
      })
  }));
  app.use(passport.initialize());
  app.use(passport.session());
  app.use(app.router);
  app.use(express.static(__dirname + '/public'));
});

Ce sont mes itinéraires:

app.get('/auth/facebook', passport.authenticate('facebook', { scope: ['user_status', 'user_photos'] }));

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

app.get('/index', function(req, res) {

            res.render('index.ejs', {
                siteTitle: "Welcome",
                siteUrl: CONFIG.server.siteUrl,
                user: req.user
            });
});

Et enfin, voici comment j'essaie d'accéder à l'objet utilisateur de mon point de vue:

<div class="page-header">
    <h3><%= siteTitle %></h3>
</div>  

<% if (!user) { %>
     <p>Not logged in !</p>
<% } else { %>
     <p>Hello, <%= user.firstname %> <%= user.lastname %>.</p>
<% } %>

Après l'authentification avec facebook, mon affichage affiche correctement le prénom et le nom. Après une autre demande de page, req.User est indéfini (la désérialisation n'est pas appelée).

Qu'est-ce que je fais mal?

17
Sven

Utilisez des aides dynamiques. Voici un exemple d'objet user à nu:

app.dynamicHelpers({
    user: function(req, res){
        var roles, name;

        if (req.session && req.session.auth == true) {
            roles = ['member'];
            name = (req.session.user) ? req.session.user.name : 'Registered member';
            id = (req.session.user) ? req.session.user.id : 0;
        }
        else {
            roles = ['guest'];
            name = 'Guest';
            id = null;
        }

        return {
            name: name, 
            id: id,
            roles: roles,
            isGuest: roles.indexOf('guest') !== -1,
            isAdmin: roles.indexOf('admin') !== -1
        }
    }
});

Ensuite, à partir des vues, vous pouvez simplement utiliser #{user.name} ou if user.isAdmin etc., car l'objet user est désormais accessible à d'autres parties de l'application.

Vous pouvez l'ajouter à app.js ou l'exiger à partir d'un fichier externe. Je garde tous mes aides dynamiques sous /utils/helpers.js

10
mvbl fst

Avez-vous défini le middleware de passeport? À partir du document , vous devez faire

app.configure(function() {
  app.use(express.cookieParser());
  app.use(express.bodyParser());
  app.use(express.session({ secret: 'keyboard cat' }));
  app.use(passport.initialize());
  app.use(passport.session());
  app.use(app.router);
  app.use(express.static(YOUR_STATIC_DIR_PATH));
});

si vous utilisez Express 3.x ou Connect 2.x, définissez le secret des cookies au lieu du secret de la session

app.configure(function() {
  app.use(express.cookieParser('keyboard cat'));
  app.use(express.session());
  app.use(express.bodyParser());
  app.use(passport.initialize());
  app.use(passport.session());
  app.use(app.router);
  app.use(express.static(YOUR_STATIC_DIR_PATH));
});
2
smagch

D'accord je l'ai eu:

L'erreur que j'ai commise n'était pas d'être dans le code que j'ai posté ci-dessus, ce qui est correct. J'avais un mauvais moyen de créer des liens vers des URL. J'ai donc forcé express à créer une nouvelle session chaque fois que j'ai utilisé l'un des liens rompus. Avec la nouvelle session, j'ai également perdu mon objet req.user.

Donc, si vous rencontrez des problèmes similaires, vérifiez également vos liens dans votre code HTML.

Merci à tous pour votre aide.

2
Sven

Vous pouvez transmettre les informations utilisateur à afficher dans le routeur:

res.render('user/dashboad', {
    ...
    user: req.session.passport.user,
    ...
0
Dung Vu