GithubHelp home page GithubHelp logo

jaredhanson / passport-remember-me Goto Github PK

View Code? Open in Web Editor NEW
219.0 11.0 102.0 215 KB

Remember Me cookie authentication strategy for Passport and Node.js

License: MIT License

JavaScript 100.00%

passport-remember-me's Introduction

Passport-Remember Me

Passport strategy for authenticating based on a remember me cookie.

This module lets you authenticate using a remember me cookie (aka persistent login) in your Node.js applications. By plugging into Passport, remember me authentication can be easily and unobtrusively integrated into any application or framework that supports Connect-style middleware, including Express.

Install

$ npm install passport-remember-me

Usage

Configure Strategy

The remember me authentication strategy authenticates users using a token stored in a remember me cookie. The strategy requires a verify callback, which consumes the token and calls done providing a user.

The strategy also requires an issue callback, which issues a new token. For security reasons, remember me tokens should be invalidated after being used. The issue callback supplies a new token that will be stored in the cookie for next use.

passport.use(new RememberMeStrategy(
  function(token, done) {
    Token.consume(token, function (err, user) {
      if (err) { return done(err); }
      if (!user) { return done(null, false); }
      return done(null, user);
    });
  },
  function(user, done) {
    var token = utils.generateToken(64);
    Token.save(token, { userId: user.id }, function(err) {
      if (err) { return done(err); }
      return done(null, token);
    });
  }
));

Authenticate Requests

Use passport.authenticate(), specifying the 'remember-me' strategy, to authenticate requests.

This is typically used in an application's middleware stack, to log the user back in the next time they visit any page on your site. For example:

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(passport.authenticate('remember-me'));
  app.use(app.router);
});

Note that passport.session() should be mounted above remember-me authentication, so that tokens aren't exchanged for currently active login sessions.

Setting the Remember Me Cookie

If the user enables "remember me" mode, an initial cookie should be set when they login.

app.post('/login', 
  passport.authenticate('local', { failureRedirect: '/login', failureFlash: true }),
  function(req, res, next) {
    // issue a remember me cookie if the option was checked
    if (!req.body.remember_me) { return next(); }

    var token = utils.generateToken(64);
    Token.save(token, { userId: req.user.id }, function(err) {
      if (err) { return done(err); }
      res.cookie('remember_me', token, { path: '/', httpOnly: true, maxAge: 604800000 }); // 7 days
      return next();
    });
  },
  function(req, res) {
    res.redirect('/');
  });

Security Considerations

If not managed correctly, using a "remember me" cookie for automatic authentication increases a service's exposure to potential security threats. There are a number of techniques to reduce and mitigate these threats, and it is a matter of application-level policy to asses the level of risk and implement appropriate counter measures.

The following list is recommended reading for understanding these risks:

Examples

For a complete, working example, refer to the login example.

Tests

$ npm install
$ make test

Build Status

Credits

License

The MIT License

Copyright (c) 2013 Jared Hanson <http://jaredhanson.net/>

passport-remember-me's People

Contributors

jaredhanson avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

passport-remember-me's Issues

dont understand example

Hi, I don't understand your example.

Why when you consumetoken you don't clear cookie and save a new cookie in issuetoken ?

Thx

support for signed cookies

when using express.cookieParser(secret') i'd like to pass an option to get the signed cookie if I've set it as signed.

Cannot read property 'remember_me' of undefined

I just test this strategy and it wont work. When i go to any route it show the error message:
Cannot read property 'remember_me' of undefined
I followed exactly as the Usage in README.md

Implementation of Persistent Login Cookie Best Practice with the strategy

I'm just curious about this:

Within the linked scenario of the best practice remember me cookie validation(http://jaspan.com/improved_persistent_login_cookie_best_practice), you have to check for the correct triplet of uid, series id and token in the database. I would put it in the verification callback. Then if you validated the cookie this way, you have to replace the token field with a new one, leaving the other two intact (or delete the whole document/row and add a new one with the same credentials, except for the token which have to be a fresh one). This part should go to the issue callback as I see it.

Now my question is if there is a standard way to share those credentials among the callbacks, especially the series id which have to be used for the db lookup to insert the new token if i'm getting it right, (the user id probably presented in the request after verification).

Moreover, for sake of performance, is there an advisement for doing only a single database round trip, changing the token field at once instead of clearing it first, aka consuming the token during verification, and setting the new one next during the issue part of the process.

In other words I'm a bit confused about what to do when, and how to access the cookie information or part of it in the issue callback.

Please enlighten me if I'm not understanding the practice or the intent of strategy correctly, or maybe if we have a better way to do the whole thing now in 2015. Also I'm happy to answer any question in case I wasn't able to make myself clear!

And thank you of course for the great module (passport.js) and also for this strategy!

remember_me cookie resets secure and sameSite flags on consume

The first time when I log in I set the cookie like this:

res.cookie('remember_me', token, { path: '/', httpOnly: true, maxAge: 604800, secure: true, sameSite: true, });

I can see in my browser the secure and sameSite are correct.
Then I delete connect.sid to verify if the remember_me token is working and the session still persists.
The session still works but the remember_me cookie has now secure and sameSite false.

Can't log out

The problem is that I just want the login form auto-filled when i come back to the login page.
For me it works to much because once logged-in i can't log out.
This is my code using mongoDB to store tokens

passport.use(new RememberMeStrategy(
		function(token, done) {
			Token.findOneAndRemove({ value: token })
			.populate('user')
			.exec( function (err, doc) {
				if(err) return done(err);
				if(!doc) return done(null,false);
				return done(null, doc.user);
			});
		},
		function(user, done) {
			crypto.randomBytes(64, (err, buf) => {
				const value = buf.toString('hex');
				const token = new Token({
					value: value,
					user: user._id
				});
				token.save((err) => {
					if (err) return done(err);
					console.log(value);
					return done(null, value)
				});
			});
		}
));

Example doesn't work

Hi guys,
I'm trying to implement a remember-me strategy for my NodeJS application with Passport, I have tried the main example available on the official Passport website (https://www.passportjs.org/packages/passport-remember-me/) but that doesn't work, I have an error from the package and I don't now how to fix that :

TypeError: Cannot read properties of undefined (reading 'remember_me')
    at Strategy.authenticate (/Users/.../node_modules/passport-remember-me/lib/strategy.js:51:26)
    at attempt (/Users/.../node_modules/passport/lib/middleware/authenticate.js:369:16)
    at authenticate (/Users/.../node_modules/passport/lib/middleware/authenticate.js:370:7)
    at Layer.handle [as handle_request] (/Users/.../node_modules/express/lib/router/layer.js:95:5)
    at trim_prefix (/Users/.../node_modules/express/lib/router/index.js:328:13)
    at /Users/.../node_modules/express/lib/router/index.js:286:9
    at Function.process_params (/Users/.../node_modules/express/lib/router/index.js:346:12)
    at next (/Users/.../node_modules/express/lib/router/index.js:280:10)
    at strategy.pass (/Users/.../node_modules/passport/lib/middleware/authenticate.js:346:9)
    at SessionStrategy.authenticate (/Users/.../node_modules/passport/lib/strategies/session.js:75:10)

Do you have any solution or alternative for that ?

Remember me strategy not compatible with passport 0.3.0?

It seems that remember-me strategy includes passport 0.1.1 in its package.json file as a dependency.

In 0.1.1 there is no null check before this assignment self._passport.session.user = obj;

In the latest version, however, the null check exists, so probably what is needed is to update the dependency.

Undefined functions

The functions utils.generateToken() and Token.consume() are used but not said from where they come.

login without 'remember me' seems to survive Chrome restart

These steps show the issue:

  • start your /examples/login
  • open tab in Chrome. type localhost:3000/account. You get login as expected
  • type bob, secret, do not check 'remember me'. You get home as expected
  • go to /account, go to /home
  • Close tab, close Chrome. (Do not restart server.)
  • Restart Chrome, open new tab, type localhost:3000/account
  • You get bob's account info.

Chrome's dev tools show Express' connect.sid cookie as Expires=Session. However it's value after the Chrome restart is the same as before. I would have expected Chrome to delete it and then Express to create a new value.

What am I missing here? Is there any way to require a login when Chrome is restarted? Thanks.

Edit:
This looks similar: http://stackoverflow.com/questions/10957800/google-chrome-session-expire-null-not-working
I did not see anything in the Windows7 task manager that looked Chrome' or addon'ish.

Updated Remember Me Example

Hello. I updated the remember-me example based on Express.js v4
If you please, I would like to create a pull request for my changes.

Crash Due to passport version mismatch

I'm using passport 0.3.x version of passportjs. The passport used in passport-remember-me is 0.1.x.

The problem I was facing was strange. When I login using chrome, things used to work. However if I do the same in InCognito Mode the browser would crash. Pretty strange(node and chrome suppose to be independent)

So going through the code I found out that the in case of normal cookie enabled browser the initialize.js and session.js of the installed passport was used. However in InCognito mode, initialize.js of installed passport(0.3) was used and session.js of passport-remember-me( passport 0.1) was used. This was causing a crash cause req._passport.session was not set (flow has changed in passport 0.3)

Changing the passport to passport-strategy solved the issue. However still wondering how this all happens..

passport-remember-me is not working with passport 0.5.2

Hi.
I've updated to passport 0.5.2.
With this version passport-remember-me isn't working anymore.

TypeError: Cannot set properties of undefined (setting 'user')
    at [mydir]\node_modules\passport-remember-me\node_modules\passport\lib\passport\http\request.js:45:35
    at pass ([mydir]\node_modules\passport\lib\authenticator.js:274:43)
    at serialized ([mydir]\node_modules\passport\lib\authenticator.js:283:7)
    at UserSerializer.serializeUser ([mydir]\dist\auth\user.serializer.js:23:9)
    at [mydir]\node_modules\@nestjs\passport\dist\passport\passport.serializer.js:8:61
    at pass ([mydir]\node_modules\passport\lib\authenticator.js:291:9)
    at Authenticator.serializeUser ([mydir]\node_modules\passport\lib\authenticator.js:296:5)
    at IncomingMessage.req.login.req.logIn ([mydir]\node_modules\passport-remember-me\node_modules\passport\lib\passport\http\request.js:43:29)
    at [mydir]\node_modules\@nestjs\passport\dist\auth.guard.js:63:64
    at new Promise (<anonymous>)

I think it is because the dependency of this package is ~0.1.1

  "dependencies": {
    "pkginfo": "0.2.x",
    "passport": "~0.1.1"
  },

When i replace the passport dependency manually with the content of version 0.5.2 its working again:

grafik

Combining RememberMe with Google OAuth?

I am currently using Google OAuth (via Passport and passport-google-oauth) to authenticate people to an application. This is working as expected - no issues with that part.

What I would like to do is then layer a RememberMe token on top of the OAuth so that for 30 days after you authenticate you don't need to authenticate again to Google.

How can I combine this package with passport-google-oauth to get that effect? Can I have multiple passport.authenticate() calls where the RememberMe one eliminates the need to call out to Google?

What to do on done(null, error)

Hi,

Thanks for this awesome library. I am using it in Production, and I have a doubt about what to do when I can't authenticate the user with a given token.

Right now I'm calling done(null, error) but that return the error and render it in the web, and that's not what I want. I want to be able, for example, to clean the user cookie and redirect him to the home page.

How can I do that? Can I have access to the req, res objects inside the Strategy configuration?

passport.use(
  new RememberMeStrategy(
    (token, done) => {
      loginWithHash(token).then(response => {
        if (!response.success) {
            // HERE: instead of doing that, I want to clean the user cookies and redirect to home
             return done(response.error);
        }
        return done(null, response.data);
      });
    },
    (user, done) => done(null, user.hash),
  ),
);

Thanks in advance.

Project continuation

I would like to get a discussion started about the future of this project. I believe it is still being used but the last commit dates back 3 years ago.

I think this plugin is well authored and there's not much to do besides upgrading the passport dependency to v0.3, which would fix some of the issues and PRs.

@jaredhanson, I believe you simply do not have the time. Would you agree to assign contributors that volunteer to work on this project? I am short of time myself but maybe some of the other contributors are interested? What about you, @ilich, @pravin-d, @bazineta, @jackred, @vincentbriglia, @numasi, @shaharyakir, @eddyystop?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.