简体   繁体   中英

How can I impersonate another user with Passport.js in Node?

Using Passport.js in Node, is there a way for me to allow one user to impersonate another? eg. as an Administrator in the application, I want to be able to log in as another user, without knowing their password.

Most simply, I would be satisfied if I could change the serialized user data (user ID) so when deserializeUser is called it will just assume the identity of the alternate user. I've tried replacing the value at req._passport.session.user and the value at req.session.passport.user but the net effect is just that my session seems to become invalid and Passport logs me out.

Passport provides a req.logIn method in case you want to do the authentication manually. You can use it to login any user even regardless of authentication.

Here's how you can use it. Have the Admin login normally, who'll have an isAdmin flag set.

Then place a middleware before passport.authenticate in your login route. This will login the new user based only on their username, if the currently logged in user isAdmin .

app.post('/login',

    function forceLogin(req, res, next) {
        if (!req.user.isAdmin) return next(); // skip if not admin
        User.findOne({
            username: req.body.username    // < entered username
        }, function(err, user) {
            // no checking for password
            req.logIn(user);
            res.redirect('/users/' + user.username);
        });
    },

    passport.authenticate('local'),
    function(req, res) {
        res.redirect('/users/' + req.user.username);
    }
);

I have another way to impersonate, because:

  • I didn't want to mess with internals of authentication/passport like session storage / logIn / etc. You must understand them really well and also they are prone to change so I'd say it's not an option for me.
  • Also, I'd like to still be able to tell if action is made from superuser (impersonated) or normal user (not impersonated).

What I do is:

  • Have a route for user with superadmin role to impersonate, like /superadmin/impersonate?username=normaluser1 which sets req.user.impersonated.userid = normaluser1.userid

  • Then I have a middleware, which checks if user is superadmin and is impersonated:

    if (req.user.isAdmin && req.user.impersonated) { req.user.userid = req.user.impersonated.userid; }

Also, I have found this to be a good article about user impersonation. Similar to my approach, and good for inspiration for building something similar.

The answer to your question is basically : no. The reason is this: the sessions library that is being used 99% of the time is signing the cookies, so if you tamper with the data the web server will reject it.

The way around this is to write your own passport authentication strategy that obviously doesn't do this, but I'm assuming you're talking about working with the built-in strategies here.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM