Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom returnUrl on Node.js Passport's Google strategy

I'm using Express and Passport OpenID Google strategy and I would like to set returnURL on each auth request to be able to return to the page that initiated that auth.

The situation is that I have HTML5 slides application with Node.js backend (and with social stuff and editor and Portal and extensions... https://github.com/bubersson/humla) and I want be able to log in user on some slide (via slide menu...) but then I want him to get back to same slide easily.

So I would need something like this?

app.get('/auth/google', function(req,res) {
   var cust = "http://localhost:1338/"+req.params.xxx;
   passport.authenticate('google', returnURL:cust, function ...
} 

I've read Passport's guide, but still don't know how to do that. I know this wouldn't be safe, but how else could I do it?

Or how can I make the application to return to the page from where the login has been initiated? Or is there a way to make OpenID authentication using AJAX (and still be able to use passport as well)?

like image 781
bubersson Avatar asked Mar 27 '12 08:03

bubersson


3 Answers

I've figured this out for my apps Twitter authentication, I am sure that the GoogleStrategy is quite similar. Try a variant of this:

Assuming you have defined the route for the callback from the authentication service like so (from the passport guide):

app.get('/auth/twitter/callback',
  passport.authenticate('twitter', {
      successRedirect: authenticationRedirect(req, '/account')
    , failureRedirect: '/'
  })
);

Just change that block to this:

app.get('/auth/twitter/callback', function(req, res, next){
  passport.authenticate('twitter', function(err, user, info){
    // This is the default destination upon successful login.
    var redirectUrl = '/account';

    if (err) { return next(err); }
    if (!user) { return res.redirect('/'); }

    // If we have previously stored a redirectUrl, use that, 
    // otherwise, use the default.
    if (req.session.redirectUrl) {
      redirectUrl = req.session.redirectUrl;
      req.session.redirectUrl = null;
    }
    req.logIn(user, function(err){
      if (err) { return next(err); }
    });
    res.redirect(redirectUrl);
  })(req, res, next);
});

Now, define your middleware for authenticated routes to store the original URL in the session like this:

ensureAuthenticated = function (req, res, next) {
  if (req.isAuthenticated()) { return next(); }

  // If the user is not authenticated, then we will start the authentication
  // process.  Before we do, let's store this originally requested URL in the
  // session so we know where to return the user later.

  req.session.redirectUrl = req.url;

  // Resume normal authentication...

  logger.info('User is not authenticated.');
  req.flash("warn", "You must be logged-in to do that.");
  res.redirect('/');
}

Works!

like image 159
mkoistinen Avatar answered Nov 13 '22 02:11

mkoistinen


Wherever you have your login button, append the request's current URL as a query parameter (adjust for whatever templating system you use):

<a href='/auth/google?redirect=<%= req.url %>'>Log In</a>

Then, add middleware to your GET /auth/google handler that stores this value in req.session:

app.get('/auth/google', function(req, res, next) {
  req.session.redirect = req.query.redirect;
  next();
}, passport.authenticate('google'));

Finally, in your callback handler, redirect to the URL stored in the session:

app.get('/auth/google/callback', passport.authenticate('google',
  failureRedirect: '/'
), function (req, res) {
  res.redirect(req.session.redirect || '/');
  delete req.session.redirect;
});
like image 40
namuol Avatar answered Nov 13 '22 01:11

namuol


Try res.redirect('back'); in the callback for passport.authenticate

like image 5
nak Avatar answered Nov 13 '22 03:11

nak