how to redirect to original page after successful

2020-03-06 03:06发布

问题:

I am using node passport-google-oauth module and trying to redirect the page back to the original path after successful authentication using a session based approached suggested in Custom returnUrl on Node.js Passport's Google strategy. However, I find inside my callback, the redirect info stored in session was always wiped out so I was forced to redirect to a default ('/' in this case).

Here is the logging output from my code snippet. It seems when it's inside the callback, the returnTo got wiped out. Is it a design of the passport-google-oauth? If so, how can one redirect back to the original page after a successful authentication?

// output from

Storing url: /newroom
in /auth/google, returnTo = /newroom
in /auth/google/callback, returnTo = undefined
Storing url: /newroom
in /auth/google, returnTo = /newroom
in /auth/google/callback, returnTo = undefined

// code snippet

var express = require('express'),
[sic]
passport = require('passport'),
GoogleStrategy = require('passport-google-oauth').OAuth2Strategy,
cookieParser = require('cookie-parser'),
expressSession = require('express-session'),
bodyParser = require('body-parser'); 

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

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

passport.use(new GoogleStrategy({
        clientID: GOOGLE_CLIENT_ID,
        clientSecret: GOOGLE_CLIENT_SECRET,
        callbackURL: 'http://' + MY_HOST + '/auth/google/callback',
    },
    function(accessToken, refreshToken, profile, done) {
        process.nextTick(function() {
            console.log('Profile:' + profile);
            return done(null, profile);
        });
    }
));

var auth = function(req, res, next){
    if (!req.session.user) {
        console.log('Storing url: ' + req.url);
        req.session.returnTo = req.url;
        res.redirect('/auth/google');
    } else if (!userIsValid(req.session.user)) {
        // handle invalid user
    } else {
        next();
    }
};

app.get('/auth/google', function(req, res, next) {
        console.log("in /auth/google, returnTo = " + req.session.returnTo);
        passport.authenticate('google',
            {
                scope: ['https://www.googleapis.com/auth/userinfo.profile',
                    'https://www.googleapis.com/auth/userinfo.email']
            }
        )(req, res, next)
    }
);

app.get('/auth/google/callback', function(req, res, next) {
    console.log("in /auth/google/callback, returnTo = " + req.session.returnTo);
    passport.authenticate('google', function(err, user, info) {
        console.log("in /auth/google/callback callback");
        if (err || !user) {
            res.redirect('/auth/google');
        } else {
            var returnTo = req.session.returnTo ? req.session.returnTo : '/';
            delete req.session.returnTo;
            console.log('Redirecting to: ' + returnTo);
            req.session.user = user;
            res.redirect(returnTo);
        }
    })(req, res, next);
});

回答1:

I use

res.redirect(req.headers.referer); 

but problem is sometimes it works sometimes it doesn't as if the user will be first time logging through facebook, facebook will first display the permission dialog which overwrites the referer header var but if user has already granted permission to your app he/she will be redrected back to the url from wherever they are coming.

SBE - Sorry for Bad English ;)



回答2:

Can also store the first URL in the session, only if the variable is currently not set. Then post login if this var is set, then re direct to that.

This is better than a header which might not be accurate from a 3rd party oauth.

In Java I would do it in a filter (check for a session variable to, say redirect_to or first_url, if its null then set it, if not the login/ sign up page). In node js can use middleware as explained in https://stackoverflow.com/a/13336055/1643558

Quoting that answer: I have a middleware I use with app.get('/account', auth.restrict, routes.account) that sets redirect_to in the session...then I redirect to /login

auth.restrict = function(req, res, next){
    if ( !req.session.userid ) {
        req.session.redirect_to = '/account';
            res.redirect('/login');
    } else {
        next();
    }
};

Then in routes.login.post I do the following:

var redirect_to = req.session.redirect_to ? req.session.redirect_to : '/';
delete req.session.redirect_to;
//is authenticated ?
res.redirect(redirect_to);