Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
touchto-core / lib / authentication.js
Size: Mime:
import config from 'config';
import debugModule from 'debug';
import crypto from 'crypto';
import passport from 'passport';
import phpass from 'phpass';
import fbPassport from 'passport-facebook';
import googPassport from 'passport-google-oauth';
import localPassport from 'passport-local';
import User from '../modules/user';

const debug = debugModule( 'touchto:authentication' );

const FacebookStrategy = fbPassport.Strategy;
const GoogleStrategy = googPassport.OAuth2Strategy;
const LocalStrategy = localPassport.Strategy;

let OAuthRead;
let createPasswordHash;

// General Authentication Config

if ( config.has( 'auth.enabled' ) && config.get( 'auth.enabled' ) ) {
    passport.serializeUser = ( user, req, done ) => done( 'null', user.id );
    passport.deserializeUser = ( id, req, done ) => {
        User.Model.findById( id ).exec()
            .then( user => done( null, user ) )
            .catch( ( err ) => {
                console.error( err.stack );
                return done( err );
            } );
    };
    const passwordhash = new phpass.PasswordHash();
    createPasswordHash = password => passwordhash.hashPassword( password );
    OAuthRead = ( token, tokenSecret, profile, done ) => {
        let username = profile.name.givenName.trim()[0];
        username += profile.name.familyName.trim();
        username = username.toLowerCase().trim();

        const provider = {
            id: profile.id,
            name: profile.provider,
            profile,
            access_token: token,
        };
        const doc = {
            username,
            name: profile.displayName,
            first_name: profile.name.givenName,
            last_name: profile.name.familyName,
            mail: profile.emails[0].value.toLowerCase().trim(),
        };

        doc[profile.provider] = provider;
        if ( profile.photos.length > 0 ) doc.photo = profile.photos[0].value;
        
        const providercriteria = {};
        providercriteria[`${profile.provider}.id`] = profile.id;
        providercriteria[`${profile.provider}.name`] = profile.provider;

        const criteria = {};
        criteria.$or = [
            providercriteria,
            {
                mail: profile.emails[0].value.toLowerCase().trim(),
            }];

        User.Model.findAndUpdate( criteria, doc ).then( ( user ) => {
            if ( user === null ) {
                done( null, false );
            } else {
                done( null, user );
            }
        } )
        .catch( () => {
            User.Model.createFromOAuth( doc ).then( ( user ) => {
                if ( user === null ) {
                    done( null, false );
                } else {
                    done( null, user );
                }
            } ).catch( () => {
                done( null, false );
            } );
        } );
    };
}

/** Auth Methods **/

/** *** GOOGLE *** **/

if ( config.has( 'auth.google.enabled' ) && config.get( 'auth.google.enabled' ) === true ) {
    const GOOGLE_CONSUMER_ID = config.get( 'auth.google.GOOGLE_CONUSMER_ID' );
    const GOOGLE_CONSUMER_SECRET = config.get( 'auth.google.GOOGLE_CONSUMER_SECRET' );
    const GOOGLE_RETURN_URL = config.get( 'auth.google.GOOGLE_RETURN_URL' );

    passport.use( new GoogleStrategy( {
        clientID: GOOGLE_CONSUMER_ID,
        clientSecret: GOOGLE_CONSUMER_SECRET,
        callbackURL: GOOGLE_RETURN_URL,
    },
    OAuthRead ) );
}

/** *** FACEBOOK *** **/

if ( config.has( 'auth.facebook.enabled' ) && config.get( 'auth.facebook.enabled' ) === true ) {
    const FACEBOOK_APP_ID = config.get( 'auth.facebook.FACEBOOK_APP_ID' );
    const FACEBOOK_APP_SECRET = config.get( 'auth.facebook.FACEBOOK_APP_SECRET' );
    const FACEBOOK_APP_CALLBACK = config.get( 'auth.facebook.FACEBOOK_APP_CALLBACK' );
    const FACEBOOK_APP_SIGNUP_CALLBACK = config.get( 'auth.facebook.FACEBOOK_APP_SIGNUP_CALLBACK' );

    passport.use( new FacebookStrategy( {
        clientID: FACEBOOK_APP_ID,
        clientSecret: FACEBOOK_APP_SECRET,
        callbackURL: FACEBOOK_APP_CALLBACK,
        profileFields: ['id', 'displayName', 'email', 'first_name', 'last_name', 'picture'],
    },
    OAuthRead ) );

    passport.use( 'facebookregister', new FacebookStrategy( {
        clientID: FACEBOOK_APP_ID,
        clientSecret: FACEBOOK_APP_SECRET,
        callbackURL: FACEBOOK_APP_SIGNUP_CALLBACK,
        profileFields: ['id', 'displayName', 'email', 'first_name', 'last_name', 'picture'],
    },
    OAuthRead ) );
}

/** *** LOCAL *** **/

if ( config.has( 'auth.local.enabled' ) && config.get( 'auth.local.enabled' ) === true ) {
    passport.use( new LocalStrategy( ( username, password, done ) => {
        const criteria = {
            mail: username,
        };
        User.Model.findOne( criteria )
            .select( '+passwd' )
            .exec()
        .then( ( user ) => {
            // No user came up
            if ( user === null ) done( null, false, { message: 'Invalid credentials', } );

            // Check for successful auth
            if ( user.checkhash( password ) ) {
                user.set( 'last_login', Date.now() );
                user.save( ( err ) => {
                    if ( err ) {
                        console.error( err.stack );
                        done( err );
                    } else {
                        User.Model.findById( user.get( '_id' ) )
                            .exec()
                        .then( ( updUser ) => {
                            done( null, updUser );
                        } )
                        .catch( ( error ) => {
                            done( error );
                        } );
                    }
                } );
            } else {
                done( null, false, { message: 'Invalid credentials', } );
            }
        } )
        .catch( ( err ) => {
            console.error( err.stack );
            done( null, false, { message: 'Invalid credentials', } );
        } );
    } ) );
}

const isAuthenticated = ( req, res, next ) => {
    if ( req.isAuthenticated() ) {
        return next();
    } else if ( req.xhr ) {
        return res.status( 401 ).end();
    }
    const error = new Error();
    error.status = 401;
    throw error;
};

export default {
    isAuthed: isAuthenticated,
    hasher: phpass.PasswordHash,
    createPasswordHash, // WONT NECESSARILY HAVE A VALUE
};