Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PassportJS: How to get req.user in my views

I am using pssportjs with express 2.x and a sessions storage. After a login I am getting req.User only once. As soon as I redirect again req.User is undefined.

Here is my 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'));
});

These are my routes:

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
            });
});

And finally this is how I am trying to access the user object in my view:

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

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

After authenticating with facebook my view displays firstname and lastname correctly. After another page request req.User is undefiend (deserializing is not being invoced).

What am I doing wrong?

like image 536
Sven Avatar asked Jun 25 '12 08:06

Sven


4 Answers

Use dynamic helpers. Here's an example of my barebones user object:

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
        }
    }
});

Then from views you can simply use #{user.name} or if user.isAdmin etc as object user is now accessible to other parts of the app.

You can add it to app.js or require from an external file. I keep all of my dynamic helpers under /utils/helpers.js

like image 133
mvbl fst Avatar answered Nov 07 '22 14:11

mvbl fst


Did you set passport middleware? From the document, you need to do

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));
});

if you are using Express 3.x or Connect 2.x, set cookie secret instead of session secret

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));
});
like image 23
smagch Avatar answered Nov 07 '22 13:11

smagch


All right I got it:

The mistake I did was not being in the code I posted above, which is correct. I had a wrong way of linking to URLs so I somehow forced express to create a new session every time I used one of the broken links. With the new session I also lost my req.user object.

So if you are having similar issues, also check your links inside your html.

Thank you everyone for your help.

like image 33
Sven Avatar answered Nov 07 '22 15:11

Sven


app.post('/login', function(req, res){

const user = new User({
     username: req.body.username,
     password: req.body.password
});


req.login(user, function(err){
    if(!err){
        passport.authenticate("local")(req, res, function(){
            res.redirect('your rendered URL');
            // console.log(` username = ${user.username} and id = ${user.id}`);
            
        })

    }
    else{
        console.log(err);
    }
    
   
   
});

    req.session.user = user;

}

and then we can use this user anywhere we want I hope it help

like image 42
prakhar tiwari Avatar answered Nov 07 '22 13:11

prakhar tiwari