Keystone-classic: User signin code appears twice, differently

Created on 23 Jun 2016  路  6Comments  路  Source: keystonejs/keystone-classic

The code to sign in a user is here:

    User.model.findOne({ email: emailRegExp }).exec(function (err, user) {
        if (user) {
            keystone.callHook(user, 'pre:signin', function (err) {
                if (err) return res.json({ error: 'pre:signin error', detail: err });
                user._.password.compare(req.body.password, function (err, isMatch) {
                    if (isMatch) {
                        session.signinWithUser(user, req, res, function () {
                            keystone.callHook(user, 'post:signin', function (err) {
                                if (err) return res.json({ error: 'post:signin error', detail: err });
                                res.json({ success: true, user: user });
                            });
                        });
    ...

And also here:

    var User = keystone.list(keystone.get('user model'));
    if (typeof lookup.email === 'string' && typeof lookup.password === 'string') {
        // ensure that it is an email, we don't want people being able to sign in by just using "\." and a haphazardly correct password.
        if (!utils.isEmail(lookup.email)) {
            return onFail(new Error('Incorrect email or password'));
        }
        // create regex for email lookup with special characters escaped
        var emailRegExp = new RegExp('^' + utils.escapeRegExp(lookup.email) + '$', 'i');
        // match email address and password
        User.model.findOne({ email: emailRegExp }).exec(function (err, user) {
            if (user) {
                user._.password.compare(lookup.password, function (err, isMatch) {
                    if (!err && isMatch) {
                        postHookedSigninWithUser(user, req, res, onSuccess, onFail);
                    } else {
                        onFail(err || new Error('Incorrect email or password'));
                    }
                });
            } else {
                onFail(err);
            }
        });
    } else {

The code is subtly different. I'm not clear which implementation is correct, but I suspect they aren't both correct. This code needs to be in exactly once place, so when security issues are fixed in one location they are also fixed in the other.

bug

All 6 comments

I wonder if this is a good opportunity to integrate passportjs, or if we should just make sure there is only one implementation right now.

I'd rather not pull in any more dependencies by default.

+1 for having a keystone-passportjs package that you can drop in to replace the simpler built-in auth

IMO this looks like a bug, it should be centralised logic. Sign in APIs need to be cleaned up anyway for 0.4, I'll pick this up.

Just realised I never left a comment here. To clarify, the code in the Admin route is newer. I prototyped it there, and it does what we want. The code in the generic session module is older but they are equivalent implementations, with one exception: the generic one doesn't pass the user to the pre:signing hook. It'll require refactoring to implement that. I'd like to review the whole thing with you @josephg to figure out a better way of implementing generic functionality that the route can hook into, but right now this isn't a major issue.

I used PassportJS before (via a generator for Angular) and it was great.

Closing as duplicate of newer open issue #3969 (Consolidate Signin Code)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

javierpelozo picture javierpelozo  路  5Comments

useralive003 picture useralive003  路  5Comments

zhdan88vadim picture zhdan88vadim  路  5Comments

jacqueslareau picture jacqueslareau  路  5Comments

schybo picture schybo  路  3Comments