├── .gitignore ├── README.md ├── app.js ├── bin └── www ├── config ├── auth.js ├── database.js └── passport.js ├── models └── user.js ├── package-lock.json ├── package.json ├── public └── stylesheets │ └── style.css ├── routes ├── index.js └── users.js └── views ├── error.ejs ├── index.ejs ├── login.ejs ├── partials └── head.ejs ├── profile.ejs └── signup.ejs /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | npm-debug.log 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # express-authentication 2 | 3 | Simple authentication app using express, node & passport. 4 | 5 | Authenticate locally or through Facebook, Twitter or Google. 6 | 7 | ## Prerequisites 8 | 9 | * [Git](http://git-scm.com/) 10 | * [Node.js with npm](https://nodejs.org/en/) 11 | * [MongoDB](https://docs.mongodb.org/manual/installation/) 12 | 13 | ## Installation 14 | 15 | * ` git clone https://github.com/danielgynn/express-authentication.git` 16 | * `cd express-authentication` 17 | * `npm install` 18 | * You will need a Mongo instance running. In a new terminal window run `mongod` 19 | * `node app` 20 | 21 | Head over to [http://localhost:3000](http://localhost:3000) 22 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var path = require('path'); 3 | var favicon = require('serve-favicon'); 4 | var logger = require('morgan'); 5 | var cookieParser = require('cookie-parser'); 6 | var bodyParser = require('body-parser'); 7 | 8 | var port = process.env.PORT || 3000; 9 | 10 | var passport = require('passport'); 11 | var LocalStrategy = require('passport-local').Strategy; 12 | 13 | var mongoose = require('mongoose'); 14 | var flash = require('connect-flash'); 15 | var session = require('express-session'); 16 | 17 | var routes = require('./routes/index'); 18 | var users = require('./routes/users'); 19 | 20 | var configDB = require('./config/database.js'); 21 | mongoose.connect(configDB.url); 22 | 23 | var app = express(); 24 | 25 | app.set('views', path.join(__dirname, 'views')); 26 | app.set('view engine', 'ejs'); 27 | 28 | //app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); 29 | app.use(logger('dev')); 30 | app.use(bodyParser.json()); 31 | app.use(bodyParser.urlencoded({ extended: false })); 32 | app.use(cookieParser()); 33 | app.use(express.static(path.join(__dirname, 'public'))); 34 | 35 | app.use(session({ secret: 'shhsecret', resave: true, saveUninitialized: true })); 36 | app.use(passport.initialize()); 37 | app.use(passport.session()); 38 | app.use(flash()); 39 | 40 | require('./config/passport')(passport); 41 | 42 | app.use('/', routes); 43 | app.use('/users', users); 44 | 45 | app.use(function(req, res, next) { 46 | var err = new Error('Not Found'); 47 | err.status = 404; 48 | next(err); 49 | }); 50 | 51 | if (app.get('env') === 'development') { 52 | app.use(function(err, req, res, next) { 53 | res.status(err.status || 500); 54 | res.render('error', { 55 | message: err.message, 56 | error: err, 57 | }); 58 | }); 59 | } 60 | 61 | app.use(function(err, req, res, next) { 62 | res.status(err.status || 500); 63 | res.render('error', { 64 | message: err.message, 65 | error: {}, 66 | }); 67 | }); 68 | 69 | app.listen(port); 70 | 71 | module.exports = app; 72 | -------------------------------------------------------------------------------- /bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | var app = require('../app'); 8 | var debug = require('debug')('express-authentication:server'); 9 | var http = require('http'); 10 | 11 | /** 12 | * Get port from environment and store in Express. 13 | */ 14 | 15 | var port = normalizePort(process.env.PORT || '3000'); 16 | app.set('port', port); 17 | 18 | /** 19 | * Create HTTP server. 20 | */ 21 | 22 | var server = http.createServer(app); 23 | 24 | /** 25 | * Listen on provided port, on all network interfaces. 26 | */ 27 | 28 | server.listen(port); 29 | server.on('error', onError); 30 | server.on('listening', onListening); 31 | 32 | /** 33 | * Normalize a port into a number, string, or false. 34 | */ 35 | 36 | function normalizePort(val) { 37 | var port = parseInt(val, 10); 38 | 39 | if (isNaN(port)) { 40 | // named pipe 41 | return val; 42 | } 43 | 44 | if (port >= 0) { 45 | // port number 46 | return port; 47 | } 48 | 49 | return false; 50 | } 51 | 52 | /** 53 | * Event listener for HTTP server "error" event. 54 | */ 55 | 56 | function onError(error) { 57 | if (error.syscall !== 'listen') { 58 | throw error; 59 | } 60 | 61 | var bind = typeof port === 'string' 62 | ? 'Pipe ' + port 63 | : 'Port ' + port; 64 | 65 | // handle specific listen errors with friendly messages 66 | switch (error.code) { 67 | case 'EACCES': 68 | console.error(bind + ' requires elevated privileges'); 69 | process.exit(1); 70 | break; 71 | case 'EADDRINUSE': 72 | console.error(bind + ' is already in use'); 73 | process.exit(1); 74 | break; 75 | default: 76 | throw error; 77 | } 78 | } 79 | 80 | /** 81 | * Event listener for HTTP server "listening" event. 82 | */ 83 | 84 | function onListening() { 85 | var addr = server.address(); 86 | var bind = typeof addr === 'string' 87 | ? 'pipe ' + addr 88 | : 'port ' + addr.port; 89 | debug('Listening on ' + bind); 90 | } 91 | -------------------------------------------------------------------------------- /config/auth.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | facebookAuth: { 3 | clientID: '896605267054808', 4 | clientSecret: '28f6a7d2842d5f9ba19e449131694902', 5 | callbackURL: 'http://localhost:3000/auth/facebook/callback', 6 | }, 7 | twitterAuth: { 8 | consumerKey: 'sOM9aZpoEyNAXKqvEUHd2O7cN', 9 | consumerSecret: '6I1x0PgH41AxuqtAKcfRqYtWDMKNv0TBaaoegW3RP3o1ks7NPk', 10 | callbackURL: 'http://localhost:3000/auth/twitter/callback', 11 | }, 12 | googleAuth: { 13 | clientID: '262575533252-sviar9bm39g5c4dnlb6erkpvjme4hit2.apps.googleusercontent.com', 14 | clientSecret: '1K1fRgOmy1WJK4_Z8ycGRyuz', 15 | callbackURL: 'http://localhost:3000/auth/google/callback', 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /config/database.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | url: 'mongodb://localhost/expressauth', 3 | }; 4 | -------------------------------------------------------------------------------- /config/passport.js: -------------------------------------------------------------------------------- 1 | var LocalStrategy = require('passport-local').Strategy; 2 | var FacebookStrategy = require('passport-facebook').Strategy; 3 | var TwitterStrategy = require('passport-twitter').Strategy; 4 | var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy; 5 | var User = require('../models/user'); 6 | var configAuth = require('./auth'); 7 | 8 | module.exports = function(passport) { 9 | 10 | passport.serializeUser(function(user, done) { 11 | done(null, user.id); 12 | }); 13 | 14 | passport.deserializeUser(function(id, done) { 15 | User.findById(id, function(err, user) { 16 | done(err, user); 17 | }); 18 | }); 19 | 20 | passport.use('local-signup', new LocalStrategy({ 21 | usernameField: 'email', 22 | passwordField: 'password', 23 | passReqToCallback: true, 24 | }, 25 | function(req, email, password, done) { 26 | process.nextTick(function() { 27 | User.findOne({ 'local.email': email }, function(err, user) { 28 | if (err) 29 | return done(err); 30 | if (user) { 31 | return done(null, false, req.flash('signupMessage', 'That email is already taken.')); 32 | } else { 33 | var newUser = new User(); 34 | newUser.local.email = email; 35 | newUser.local.password = newUser.generateHash(password); 36 | newUser.save(function(err) { 37 | if (err) 38 | throw err; 39 | return done(null, newUser); 40 | }); 41 | } 42 | }); 43 | }); 44 | })); 45 | 46 | passport.use('local-login', new LocalStrategy({ 47 | usernameField: 'email', 48 | passwordField: 'password', 49 | passReqToCallback: true, 50 | }, 51 | function(req, email, password, done) { 52 | User.findOne({ 'local.email': email }, function(err, user) { 53 | if (err) 54 | return done(err); 55 | if (!user) 56 | return done(null, false, req.flash('loginMessage', 'No user found.')); 57 | if (!user.validPassword(password)) 58 | return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.')); 59 | return done(null, user); 60 | }); 61 | })); 62 | 63 | passport.use(new FacebookStrategy({ 64 | clientID: configAuth.facebookAuth.clientID, 65 | clientSecret: configAuth.facebookAuth.clientSecret, 66 | callbackURL: configAuth.facebookAuth.callbackURL, 67 | profileFields: ['id', 'email', 'first_name', 'last_name'], 68 | }, 69 | function(token, refreshToken, profile, done) { 70 | process.nextTick(function() { 71 | User.findOne({ 'facebook.id': profile.id }, function(err, user) { 72 | if (err) 73 | return done(err); 74 | if (user) { 75 | return done(null, user); 76 | } else { 77 | var newUser = new User(); 78 | newUser.facebook.id = profile.id; 79 | newUser.facebook.token = token; 80 | newUser.facebook.name = profile.name.givenName + ' ' + profile.name.familyName; 81 | newUser.facebook.email = (profile.emails[0].value || '').toLowerCase(); 82 | 83 | newUser.save(function(err) { 84 | if (err) 85 | throw err; 86 | return done(null, newUser); 87 | }); 88 | } 89 | }); 90 | }); 91 | })); 92 | 93 | passport.use(new TwitterStrategy({ 94 | consumerKey: configAuth.twitterAuth.consumerKey, 95 | consumerSecret: configAuth.twitterAuth.consumerSecret, 96 | callbackURL: configAuth.twitterAuth.callbackURL, 97 | }, 98 | function(token, tokenSecret, profile, done) { 99 | process.nextTick(function() { 100 | User.findOne({ 'twitter.id': profile.id }, function(err, user) { 101 | if (err) 102 | return done(err); 103 | if (user) { 104 | return done(null, user); 105 | } else { 106 | var newUser = new User(); 107 | newUser.twitter.id = profile.id; 108 | newUser.twitter.token = token; 109 | newUser.twitter.username = profile.username; 110 | newUser.twitter.displayName = profile.displayName; 111 | newUser.save(function(err) { 112 | if (err) 113 | throw err; 114 | return done(null, newUser); 115 | }); 116 | } 117 | }); 118 | }); 119 | })); 120 | 121 | passport.use(new GoogleStrategy({ 122 | clientID: configAuth.googleAuth.clientID, 123 | clientSecret: configAuth.googleAuth.clientSecret, 124 | callbackURL: configAuth.googleAuth.callbackURL, 125 | }, 126 | function(token, refreshToken, profile, done) { 127 | process.nextTick(function() { 128 | User.findOne({ 'google.id': profile.id }, function(err, user) { 129 | if (err) 130 | return done(err); 131 | if (user) { 132 | return done(null, user); 133 | } else { 134 | var newUser = new User(); 135 | newUser.google.id = profile.id; 136 | newUser.google.token = token; 137 | newUser.google.name = profile.displayName; 138 | newUser.google.email = profile.emails[0].value; 139 | newUser.save(function(err) { 140 | if (err) 141 | throw err; 142 | return done(null, newUser); 143 | }); 144 | } 145 | }); 146 | }); 147 | })); 148 | 149 | }; 150 | -------------------------------------------------------------------------------- /models/user.js: -------------------------------------------------------------------------------- 1 | var mongoose = require('mongoose'); 2 | var bcrypt = require('bcrypt-nodejs'); 3 | 4 | var userSchema = mongoose.Schema({ 5 | local: { 6 | name: String, 7 | email: String, 8 | password: String, 9 | }, 10 | facebook: { 11 | id: String, 12 | token: String, 13 | email: String, 14 | name: String, 15 | username: String, 16 | }, 17 | twitter: { 18 | id: String, 19 | token: String, 20 | displayName: String, 21 | username: String, 22 | }, 23 | google: { 24 | id: String, 25 | token: String, 26 | email: String, 27 | name: String, 28 | }, 29 | }); 30 | 31 | userSchema.methods.generateHash = function(password) { 32 | return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null); 33 | }; 34 | 35 | userSchema.methods.validPassword = function(password) { 36 | return bcrypt.compareSync(password, this.local.password); 37 | }; 38 | 39 | module.exports = mongoose.model('User', userSchema); 40 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-authentication", 3 | "version": "0.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.2.13", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", 10 | "integrity": "sha1-5fHzkoxtlf2WVYw27D2dDeSm7Oo=", 11 | "requires": { 12 | "mime-types": "2.1.17", 13 | "negotiator": "0.5.3" 14 | } 15 | }, 16 | "array-flatten": { 17 | "version": "1.1.1", 18 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 19 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 20 | }, 21 | "async": { 22 | "version": "2.1.4", 23 | "resolved": "https://registry.npmjs.org/async/-/async-2.1.4.tgz", 24 | "integrity": "sha1-LSFgx3iAMuTdbL4lAvH5osj2zeQ=", 25 | "requires": { 26 | "lodash": "4.17.4" 27 | } 28 | }, 29 | "basic-auth": { 30 | "version": "1.0.4", 31 | "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz", 32 | "integrity": "sha1-Awk1sB3nyblKgksp8/zLdQ06UpA=" 33 | }, 34 | "bcrypt-nodejs": { 35 | "version": "0.0.3", 36 | "resolved": "https://registry.npmjs.org/bcrypt-nodejs/-/bcrypt-nodejs-0.0.3.tgz", 37 | "integrity": "sha1-xgkX8m3CNWYVZsaBBhwwPCsohCs=" 38 | }, 39 | "bluebird": { 40 | "version": "3.5.0", 41 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", 42 | "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=" 43 | }, 44 | "body-parser": { 45 | "version": "1.13.3", 46 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.13.3.tgz", 47 | "integrity": "sha1-wIzzMMM1jhUQFqBXRvE/ApyX+pc=", 48 | "requires": { 49 | "bytes": "2.1.0", 50 | "content-type": "1.0.4", 51 | "debug": "2.2.0", 52 | "depd": "1.0.1", 53 | "http-errors": "1.3.1", 54 | "iconv-lite": "0.4.11", 55 | "on-finished": "2.3.0", 56 | "qs": "4.0.0", 57 | "raw-body": "2.1.7", 58 | "type-is": "1.6.15" 59 | } 60 | }, 61 | "bson": { 62 | "version": "1.0.4", 63 | "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.4.tgz", 64 | "integrity": "sha1-k8ENOeqltYQVy8QFLz5T5WKwtyw=" 65 | }, 66 | "buffer-shims": { 67 | "version": "1.0.0", 68 | "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", 69 | "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=" 70 | }, 71 | "bytes": { 72 | "version": "2.1.0", 73 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", 74 | "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=" 75 | }, 76 | "connect-flash": { 77 | "version": "0.1.1", 78 | "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz", 79 | "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA=" 80 | }, 81 | "content-disposition": { 82 | "version": "0.5.1", 83 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.1.tgz", 84 | "integrity": "sha1-h0dsamfI2qh+Muh2Ft+IO6f7Bxs=" 85 | }, 86 | "content-type": { 87 | "version": "1.0.4", 88 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 89 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 90 | }, 91 | "cookie": { 92 | "version": "0.1.3", 93 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", 94 | "integrity": "sha1-5zSlwUF/zkctWu+Cw4HKu2TRpDU=" 95 | }, 96 | "cookie-parser": { 97 | "version": "1.3.5", 98 | "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.5.tgz", 99 | "integrity": "sha1-nXVVcPtdF4kHcSJ6AjFNm+fPg1Y=", 100 | "requires": { 101 | "cookie": "0.1.3", 102 | "cookie-signature": "1.0.6" 103 | } 104 | }, 105 | "cookie-signature": { 106 | "version": "1.0.6", 107 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 108 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 109 | }, 110 | "core-util-is": { 111 | "version": "1.0.2", 112 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 113 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 114 | }, 115 | "crc": { 116 | "version": "3.4.4", 117 | "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.4.tgz", 118 | "integrity": "sha1-naHpgOO9RPxck79as9ozeNheRms=" 119 | }, 120 | "debug": { 121 | "version": "2.2.0", 122 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", 123 | "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", 124 | "requires": { 125 | "ms": "0.7.1" 126 | } 127 | }, 128 | "depd": { 129 | "version": "1.0.1", 130 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", 131 | "integrity": "sha1-gK7GTJ1tl+ZcwqnKqTwKpqv3Oqo=" 132 | }, 133 | "destroy": { 134 | "version": "1.0.4", 135 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 136 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 137 | }, 138 | "ee-first": { 139 | "version": "1.1.1", 140 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 141 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 142 | }, 143 | "ejs": { 144 | "version": "2.5.5", 145 | "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.5.tgz", 146 | "integrity": "sha1-bvTpVOp9z1T2aq0v56pCGTLZ7Xc=" 147 | }, 148 | "es6-promise": { 149 | "version": "3.2.1", 150 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz", 151 | "integrity": "sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q=" 152 | }, 153 | "escape-html": { 154 | "version": "1.0.3", 155 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 156 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 157 | }, 158 | "etag": { 159 | "version": "1.7.0", 160 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", 161 | "integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg=" 162 | }, 163 | "express": { 164 | "version": "4.13.4", 165 | "resolved": "https://registry.npmjs.org/express/-/express-4.13.4.tgz", 166 | "integrity": "sha1-PAt288d1kMg0VzkGHsC9O6Bn7CQ=", 167 | "requires": { 168 | "accepts": "1.2.13", 169 | "array-flatten": "1.1.1", 170 | "content-disposition": "0.5.1", 171 | "content-type": "1.0.4", 172 | "cookie": "0.1.5", 173 | "cookie-signature": "1.0.6", 174 | "debug": "2.2.0", 175 | "depd": "1.1.1", 176 | "escape-html": "1.0.3", 177 | "etag": "1.7.0", 178 | "finalhandler": "0.4.1", 179 | "fresh": "0.3.0", 180 | "merge-descriptors": "1.0.1", 181 | "methods": "1.1.2", 182 | "on-finished": "2.3.0", 183 | "parseurl": "1.3.2", 184 | "path-to-regexp": "0.1.7", 185 | "proxy-addr": "1.0.10", 186 | "qs": "4.0.0", 187 | "range-parser": "1.0.3", 188 | "send": "0.13.1", 189 | "serve-static": "1.10.3", 190 | "type-is": "1.6.15", 191 | "utils-merge": "1.0.0", 192 | "vary": "1.0.1" 193 | }, 194 | "dependencies": { 195 | "cookie": { 196 | "version": "0.1.5", 197 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.5.tgz", 198 | "integrity": "sha1-armUiksa4hlSzSWIUwpHItQETXw=" 199 | }, 200 | "depd": { 201 | "version": "1.1.1", 202 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", 203 | "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" 204 | } 205 | } 206 | }, 207 | "express-session": { 208 | "version": "1.15.6", 209 | "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.15.6.tgz", 210 | "integrity": "sha512-r0nrHTCYtAMrFwZ0kBzZEXa1vtPVrw0dKvGSrKP4dahwBQ1BJpF2/y1Pp4sCD/0kvxV4zZeclyvfmw0B4RMJQA==", 211 | "requires": { 212 | "cookie": "0.3.1", 213 | "cookie-signature": "1.0.6", 214 | "crc": "3.4.4", 215 | "debug": "2.6.9", 216 | "depd": "1.1.1", 217 | "on-headers": "1.0.1", 218 | "parseurl": "1.3.2", 219 | "uid-safe": "2.1.5", 220 | "utils-merge": "1.0.1" 221 | }, 222 | "dependencies": { 223 | "cookie": { 224 | "version": "0.3.1", 225 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 226 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 227 | }, 228 | "debug": { 229 | "version": "2.6.9", 230 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 231 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 232 | "requires": { 233 | "ms": "2.0.0" 234 | } 235 | }, 236 | "depd": { 237 | "version": "1.1.1", 238 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", 239 | "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" 240 | }, 241 | "ms": { 242 | "version": "2.0.0", 243 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 244 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 245 | }, 246 | "utils-merge": { 247 | "version": "1.0.1", 248 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 249 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 250 | } 251 | } 252 | }, 253 | "finalhandler": { 254 | "version": "0.4.1", 255 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.1.tgz", 256 | "integrity": "sha1-haF8bFmpRxfSYtYSMNSw6+PUoU0=", 257 | "requires": { 258 | "debug": "2.2.0", 259 | "escape-html": "1.0.3", 260 | "on-finished": "2.3.0", 261 | "unpipe": "1.0.0" 262 | } 263 | }, 264 | "forwarded": { 265 | "version": "0.1.2", 266 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 267 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 268 | }, 269 | "fresh": { 270 | "version": "0.3.0", 271 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", 272 | "integrity": "sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8=" 273 | }, 274 | "hooks-fixed": { 275 | "version": "2.0.2", 276 | "resolved": "https://registry.npmjs.org/hooks-fixed/-/hooks-fixed-2.0.2.tgz", 277 | "integrity": "sha512-YurCM4gQSetcrhwEtpQHhQ4M7Zo7poNGqY4kQGeBS6eZtOcT3tnNs01ThFa0jYBByAiYt1MjMjP/YApG0EnAvQ==" 278 | }, 279 | "http-errors": { 280 | "version": "1.3.1", 281 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", 282 | "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", 283 | "requires": { 284 | "inherits": "2.0.3", 285 | "statuses": "1.4.0" 286 | } 287 | }, 288 | "iconv-lite": { 289 | "version": "0.4.11", 290 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.11.tgz", 291 | "integrity": "sha1-LstC/SlHRJIiCaLnxATayHk9it4=" 292 | }, 293 | "inherits": { 294 | "version": "2.0.3", 295 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 296 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 297 | }, 298 | "ipaddr.js": { 299 | "version": "1.0.5", 300 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.0.5.tgz", 301 | "integrity": "sha1-X6eM8wG4JceKvDBC2BJyMEnqI8c=" 302 | }, 303 | "isarray": { 304 | "version": "1.0.0", 305 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 306 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 307 | }, 308 | "kareem": { 309 | "version": "1.5.0", 310 | "resolved": "https://registry.npmjs.org/kareem/-/kareem-1.5.0.tgz", 311 | "integrity": "sha1-4+QQHZ3P3imXadr0tNtk2JXRdEg=" 312 | }, 313 | "lodash": { 314 | "version": "4.17.4", 315 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", 316 | "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" 317 | }, 318 | "lodash.get": { 319 | "version": "4.4.2", 320 | "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", 321 | "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" 322 | }, 323 | "media-typer": { 324 | "version": "0.3.0", 325 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 326 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 327 | }, 328 | "merge-descriptors": { 329 | "version": "1.0.1", 330 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 331 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 332 | }, 333 | "methods": { 334 | "version": "1.1.2", 335 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 336 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 337 | }, 338 | "mime": { 339 | "version": "1.3.4", 340 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", 341 | "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=" 342 | }, 343 | "mime-db": { 344 | "version": "1.30.0", 345 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", 346 | "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" 347 | }, 348 | "mime-types": { 349 | "version": "2.1.17", 350 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", 351 | "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", 352 | "requires": { 353 | "mime-db": "1.30.0" 354 | } 355 | }, 356 | "mongodb": { 357 | "version": "2.2.33", 358 | "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.33.tgz", 359 | "integrity": "sha1-tTfEcdNKZlG0jzb9vyl1A0Dgi1A=", 360 | "requires": { 361 | "es6-promise": "3.2.1", 362 | "mongodb-core": "2.1.17", 363 | "readable-stream": "2.2.7" 364 | } 365 | }, 366 | "mongodb-core": { 367 | "version": "2.1.17", 368 | "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.17.tgz", 369 | "integrity": "sha1-pBizN6FKFJkPtRC5I97mqBMXPfg=", 370 | "requires": { 371 | "bson": "1.0.4", 372 | "require_optional": "1.0.1" 373 | } 374 | }, 375 | "mongoose": { 376 | "version": "4.13.5", 377 | "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-4.13.5.tgz", 378 | "integrity": "sha512-xcQ2Igh7hZwrxeBSh1eTW0dC0leQfcj2YA/VfOj/2nBqa5Iab3I8W3ivvs228Jw5qQqtvId1rnXW/QEHEVBNMw==", 379 | "requires": { 380 | "async": "2.1.4", 381 | "bson": "1.0.4", 382 | "hooks-fixed": "2.0.2", 383 | "kareem": "1.5.0", 384 | "lodash.get": "4.4.2", 385 | "mongodb": "2.2.33", 386 | "mpath": "0.3.0", 387 | "mpromise": "0.5.5", 388 | "mquery": "2.3.3", 389 | "ms": "2.0.0", 390 | "muri": "1.3.0", 391 | "regexp-clone": "0.0.1", 392 | "sliced": "1.0.1" 393 | }, 394 | "dependencies": { 395 | "ms": { 396 | "version": "2.0.0", 397 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 398 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 399 | } 400 | } 401 | }, 402 | "morgan": { 403 | "version": "1.6.1", 404 | "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.6.1.tgz", 405 | "integrity": "sha1-X9gYOYxoGcuiinzWZk8pL+HAu/I=", 406 | "requires": { 407 | "basic-auth": "1.0.4", 408 | "debug": "2.2.0", 409 | "depd": "1.0.1", 410 | "on-finished": "2.3.0", 411 | "on-headers": "1.0.1" 412 | } 413 | }, 414 | "mpath": { 415 | "version": "0.3.0", 416 | "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.3.0.tgz", 417 | "integrity": "sha1-elj3iem1/TyUUgY0FXlg8mvV70Q=" 418 | }, 419 | "mpromise": { 420 | "version": "0.5.5", 421 | "resolved": "https://registry.npmjs.org/mpromise/-/mpromise-0.5.5.tgz", 422 | "integrity": "sha1-9bJCWddjrMIlewoMjG2Gb9UXMuY=" 423 | }, 424 | "mquery": { 425 | "version": "2.3.3", 426 | "resolved": "https://registry.npmjs.org/mquery/-/mquery-2.3.3.tgz", 427 | "integrity": "sha512-NC8L14kn+qxJbbJ1gbcEMDxF0sC3sv+1cbRReXXwVvowcwY1y9KoVZFq0ebwARibsadu8lx8nWGvm3V0Pf0ZWQ==", 428 | "requires": { 429 | "bluebird": "3.5.0", 430 | "debug": "2.6.9", 431 | "regexp-clone": "0.0.1", 432 | "sliced": "0.0.5" 433 | }, 434 | "dependencies": { 435 | "debug": { 436 | "version": "2.6.9", 437 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 438 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 439 | "requires": { 440 | "ms": "2.0.0" 441 | } 442 | }, 443 | "ms": { 444 | "version": "2.0.0", 445 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 446 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 447 | }, 448 | "sliced": { 449 | "version": "0.0.5", 450 | "resolved": "https://registry.npmjs.org/sliced/-/sliced-0.0.5.tgz", 451 | "integrity": "sha1-XtwETKTrb3gW1Qui/GPiXY/kcH8=" 452 | } 453 | } 454 | }, 455 | "ms": { 456 | "version": "0.7.1", 457 | "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", 458 | "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" 459 | }, 460 | "muri": { 461 | "version": "1.3.0", 462 | "resolved": "https://registry.npmjs.org/muri/-/muri-1.3.0.tgz", 463 | "integrity": "sha512-FiaFwKl864onHFFUV/a2szAl7X0fxVlSKNdhTf+BM8i8goEgYut8u5P9MqQqIYwvaMxjzVESsoEm/2kfkFH1rg==" 464 | }, 465 | "negotiator": { 466 | "version": "0.5.3", 467 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz", 468 | "integrity": "sha1-Jp1cR2gQ7JLtvntsLygxY4T5p+g=" 469 | }, 470 | "oauth": { 471 | "version": "0.9.15", 472 | "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", 473 | "integrity": "sha1-vR/vr2hslrdUda7VGWQS/2DPucE=" 474 | }, 475 | "on-finished": { 476 | "version": "2.3.0", 477 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 478 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 479 | "requires": { 480 | "ee-first": "1.1.1" 481 | } 482 | }, 483 | "on-headers": { 484 | "version": "1.0.1", 485 | "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", 486 | "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" 487 | }, 488 | "parseurl": { 489 | "version": "1.3.2", 490 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", 491 | "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" 492 | }, 493 | "passport": { 494 | "version": "0.3.2", 495 | "resolved": "https://registry.npmjs.org/passport/-/passport-0.3.2.tgz", 496 | "integrity": "sha1-ndAJ+RXo/glbASSgG4+C2gdRAQI=", 497 | "requires": { 498 | "passport-strategy": "1.0.0", 499 | "pause": "0.0.1" 500 | } 501 | }, 502 | "passport-facebook": { 503 | "version": "2.1.1", 504 | "resolved": "https://registry.npmjs.org/passport-facebook/-/passport-facebook-2.1.1.tgz", 505 | "integrity": "sha1-w50LUq5NWRYyRaTiGnubYyEwMxE=", 506 | "requires": { 507 | "passport-oauth2": "1.4.0" 508 | } 509 | }, 510 | "passport-google-oauth": { 511 | "version": "0.2.0", 512 | "resolved": "https://registry.npmjs.org/passport-google-oauth/-/passport-google-oauth-0.2.0.tgz", 513 | "integrity": "sha1-6ah+nNO8cbCIGfpEglzFv0ZKiUo=", 514 | "requires": { 515 | "passport-oauth": "1.0.0", 516 | "pkginfo": "0.3.1" 517 | } 518 | }, 519 | "passport-local": { 520 | "version": "1.0.0", 521 | "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", 522 | "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=", 523 | "requires": { 524 | "passport-strategy": "1.0.0" 525 | } 526 | }, 527 | "passport-oauth": { 528 | "version": "1.0.0", 529 | "resolved": "https://registry.npmjs.org/passport-oauth/-/passport-oauth-1.0.0.tgz", 530 | "integrity": "sha1-kK/2M4dUDwIImvKM2tOep/gNd98=", 531 | "requires": { 532 | "passport-oauth1": "1.1.0", 533 | "passport-oauth2": "1.4.0" 534 | } 535 | }, 536 | "passport-oauth1": { 537 | "version": "1.1.0", 538 | "resolved": "https://registry.npmjs.org/passport-oauth1/-/passport-oauth1-1.1.0.tgz", 539 | "integrity": "sha1-p96YiiEfnPRoc3cTDqdN8ycwyRg=", 540 | "requires": { 541 | "oauth": "0.9.15", 542 | "passport-strategy": "1.0.0", 543 | "utils-merge": "1.0.0" 544 | } 545 | }, 546 | "passport-oauth2": { 547 | "version": "1.4.0", 548 | "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.4.0.tgz", 549 | "integrity": "sha1-9i+BWDy+EmCb585vFguTlaJ7hq0=", 550 | "requires": { 551 | "oauth": "0.9.15", 552 | "passport-strategy": "1.0.0", 553 | "uid2": "0.0.3", 554 | "utils-merge": "1.0.0" 555 | } 556 | }, 557 | "passport-strategy": { 558 | "version": "1.0.0", 559 | "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", 560 | "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" 561 | }, 562 | "passport-twitter": { 563 | "version": "1.0.4", 564 | "resolved": "https://registry.npmjs.org/passport-twitter/-/passport-twitter-1.0.4.tgz", 565 | "integrity": "sha1-AaeZ4fdgvy3knyul+6MigvGJMtc=", 566 | "requires": { 567 | "passport-oauth1": "1.1.0", 568 | "xtraverse": "0.1.0" 569 | } 570 | }, 571 | "path-to-regexp": { 572 | "version": "0.1.7", 573 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 574 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 575 | }, 576 | "pause": { 577 | "version": "0.0.1", 578 | "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", 579 | "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" 580 | }, 581 | "pkginfo": { 582 | "version": "0.3.1", 583 | "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", 584 | "integrity": "sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE=" 585 | }, 586 | "process-nextick-args": { 587 | "version": "1.0.7", 588 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", 589 | "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" 590 | }, 591 | "proxy-addr": { 592 | "version": "1.0.10", 593 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.0.10.tgz", 594 | "integrity": "sha1-DUCoL4Afw1VWfS7LZe/j8HfxIcU=", 595 | "requires": { 596 | "forwarded": "0.1.2", 597 | "ipaddr.js": "1.0.5" 598 | } 599 | }, 600 | "qs": { 601 | "version": "4.0.0", 602 | "resolved": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", 603 | "integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc=" 604 | }, 605 | "random-bytes": { 606 | "version": "1.0.0", 607 | "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", 608 | "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" 609 | }, 610 | "range-parser": { 611 | "version": "1.0.3", 612 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz", 613 | "integrity": "sha1-aHKCNTXGkuLCoBA4Jq/YLC4P8XU=" 614 | }, 615 | "raw-body": { 616 | "version": "2.1.7", 617 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", 618 | "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", 619 | "requires": { 620 | "bytes": "2.4.0", 621 | "iconv-lite": "0.4.13", 622 | "unpipe": "1.0.0" 623 | }, 624 | "dependencies": { 625 | "bytes": { 626 | "version": "2.4.0", 627 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", 628 | "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=" 629 | }, 630 | "iconv-lite": { 631 | "version": "0.4.13", 632 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", 633 | "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=" 634 | } 635 | } 636 | }, 637 | "readable-stream": { 638 | "version": "2.2.7", 639 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", 640 | "integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=", 641 | "requires": { 642 | "buffer-shims": "1.0.0", 643 | "core-util-is": "1.0.2", 644 | "inherits": "2.0.3", 645 | "isarray": "1.0.0", 646 | "process-nextick-args": "1.0.7", 647 | "string_decoder": "1.0.3", 648 | "util-deprecate": "1.0.2" 649 | } 650 | }, 651 | "regexp-clone": { 652 | "version": "0.0.1", 653 | "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-0.0.1.tgz", 654 | "integrity": "sha1-p8LgmJH9vzj7sQ03b7cwA+aKxYk=" 655 | }, 656 | "require_optional": { 657 | "version": "1.0.1", 658 | "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", 659 | "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", 660 | "requires": { 661 | "resolve-from": "2.0.0", 662 | "semver": "5.4.1" 663 | } 664 | }, 665 | "resolve-from": { 666 | "version": "2.0.0", 667 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", 668 | "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" 669 | }, 670 | "safe-buffer": { 671 | "version": "5.1.1", 672 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", 673 | "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" 674 | }, 675 | "semver": { 676 | "version": "5.4.1", 677 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", 678 | "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" 679 | }, 680 | "send": { 681 | "version": "0.13.1", 682 | "resolved": "https://registry.npmjs.org/send/-/send-0.13.1.tgz", 683 | "integrity": "sha1-ow1fTILIqbrprQCh2bG9vm8Zntc=", 684 | "requires": { 685 | "debug": "2.2.0", 686 | "depd": "1.1.1", 687 | "destroy": "1.0.4", 688 | "escape-html": "1.0.3", 689 | "etag": "1.7.0", 690 | "fresh": "0.3.0", 691 | "http-errors": "1.3.1", 692 | "mime": "1.3.4", 693 | "ms": "0.7.1", 694 | "on-finished": "2.3.0", 695 | "range-parser": "1.0.3", 696 | "statuses": "1.2.1" 697 | }, 698 | "dependencies": { 699 | "depd": { 700 | "version": "1.1.1", 701 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", 702 | "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" 703 | }, 704 | "statuses": { 705 | "version": "1.2.1", 706 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz", 707 | "integrity": "sha1-3e1FzBglbVHtQK7BQkidXGECbSg=" 708 | } 709 | } 710 | }, 711 | "serve-favicon": { 712 | "version": "2.3.2", 713 | "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.3.2.tgz", 714 | "integrity": "sha1-3UGeJo3gEqtysxnTN/IQUBP5OB8=", 715 | "requires": { 716 | "etag": "1.7.0", 717 | "fresh": "0.3.0", 718 | "ms": "0.7.2", 719 | "parseurl": "1.3.2" 720 | }, 721 | "dependencies": { 722 | "ms": { 723 | "version": "0.7.2", 724 | "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", 725 | "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" 726 | } 727 | } 728 | }, 729 | "serve-static": { 730 | "version": "1.10.3", 731 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.10.3.tgz", 732 | "integrity": "sha1-zlpuzTEB/tXsCYJ9rCKpwpv7BTU=", 733 | "requires": { 734 | "escape-html": "1.0.3", 735 | "parseurl": "1.3.2", 736 | "send": "0.13.2" 737 | }, 738 | "dependencies": { 739 | "depd": { 740 | "version": "1.1.1", 741 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", 742 | "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" 743 | }, 744 | "send": { 745 | "version": "0.13.2", 746 | "resolved": "https://registry.npmjs.org/send/-/send-0.13.2.tgz", 747 | "integrity": "sha1-dl52B8gFVFK7pvCwUllTUJhgNt4=", 748 | "requires": { 749 | "debug": "2.2.0", 750 | "depd": "1.1.1", 751 | "destroy": "1.0.4", 752 | "escape-html": "1.0.3", 753 | "etag": "1.7.0", 754 | "fresh": "0.3.0", 755 | "http-errors": "1.3.1", 756 | "mime": "1.3.4", 757 | "ms": "0.7.1", 758 | "on-finished": "2.3.0", 759 | "range-parser": "1.0.3", 760 | "statuses": "1.2.1" 761 | } 762 | }, 763 | "statuses": { 764 | "version": "1.2.1", 765 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz", 766 | "integrity": "sha1-3e1FzBglbVHtQK7BQkidXGECbSg=" 767 | } 768 | } 769 | }, 770 | "sliced": { 771 | "version": "1.0.1", 772 | "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", 773 | "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" 774 | }, 775 | "statuses": { 776 | "version": "1.4.0", 777 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", 778 | "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" 779 | }, 780 | "string_decoder": { 781 | "version": "1.0.3", 782 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", 783 | "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", 784 | "requires": { 785 | "safe-buffer": "5.1.1" 786 | } 787 | }, 788 | "type-is": { 789 | "version": "1.6.15", 790 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", 791 | "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", 792 | "requires": { 793 | "media-typer": "0.3.0", 794 | "mime-types": "2.1.17" 795 | } 796 | }, 797 | "uid-safe": { 798 | "version": "2.1.5", 799 | "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", 800 | "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", 801 | "requires": { 802 | "random-bytes": "1.0.0" 803 | } 804 | }, 805 | "uid2": { 806 | "version": "0.0.3", 807 | "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz", 808 | "integrity": "sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I=" 809 | }, 810 | "unpipe": { 811 | "version": "1.0.0", 812 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 813 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 814 | }, 815 | "util-deprecate": { 816 | "version": "1.0.2", 817 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 818 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 819 | }, 820 | "utils-merge": { 821 | "version": "1.0.0", 822 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", 823 | "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=" 824 | }, 825 | "vary": { 826 | "version": "1.0.1", 827 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz", 828 | "integrity": "sha1-meSYFWaihhGN+yuBc1ffeZM3bRA=" 829 | }, 830 | "xmldom": { 831 | "version": "0.1.27", 832 | "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", 833 | "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=" 834 | }, 835 | "xtraverse": { 836 | "version": "0.1.0", 837 | "resolved": "https://registry.npmjs.org/xtraverse/-/xtraverse-0.1.0.tgz", 838 | "integrity": "sha1-t0G60BjveNip0ug63gB7P3lZxzI=", 839 | "requires": { 840 | "xmldom": "0.1.27" 841 | } 842 | } 843 | } 844 | } 845 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-authentication", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "bcrypt-nodejs": "0.0.3", 10 | "body-parser": "~1.13.2", 11 | "connect-flash": "^0.1.1", 12 | "cookie-parser": "~1.3.5", 13 | "debug": "~2.2.0", 14 | "ejs": "^2.5.5", 15 | "express": "~4.13.1", 16 | "express-session": "^1.12.1", 17 | "mongoose": "^4.2.6", 18 | "morgan": "~1.6.1", 19 | "passport": "^0.3.2", 20 | "passport-facebook": "^2.0.0", 21 | "passport-google-oauth": "^0.2.0", 22 | "passport-local": "~1.0.0", 23 | "passport-twitter": "^1.0.3", 24 | "serve-favicon": "~2.3.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | 6 | a { 7 | color: #00B7FF; 8 | } 9 | -------------------------------------------------------------------------------- /routes/index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var passport = require('passport'); 3 | var router = express.Router(); 4 | 5 | router.get('/', function(req, res, next) { 6 | res.render('index', { title: 'Express' }); 7 | }); 8 | 9 | router.get('/login', function(req, res, next) { 10 | res.render('login.ejs', { message: req.flash('loginMessage') }); 11 | }); 12 | 13 | router.get('/signup', function(req, res) { 14 | res.render('signup.ejs', { message: req.flash('signupMessage') }); 15 | }); 16 | 17 | router.get('/profile', isLoggedIn, function(req, res) { 18 | res.render('profile.ejs', { user: req.user }); 19 | }); 20 | 21 | router.get('/logout', function(req, res) { 22 | req.logout(); 23 | res.redirect('/'); 24 | }); 25 | 26 | router.post('/signup', passport.authenticate('local-signup', { 27 | successRedirect: '/profile', 28 | failureRedirect: '/signup', 29 | failureFlash: true, 30 | })); 31 | 32 | router.post('/login', passport.authenticate('local-login', { 33 | successRedirect: '/profile', 34 | failureRedirect: '/login', 35 | failureFlash: true, 36 | })); 37 | 38 | router.get('/auth/facebook', passport.authenticate('facebook', { scope: 'email' })); 39 | 40 | router.get('/auth/facebook/callback', passport.authenticate('facebook', { 41 | successRedirect: '/profile', 42 | failureRedirect: '/', 43 | })); 44 | 45 | router.get('/auth/twitter', passport.authenticate('twitter')); 46 | 47 | router.get('/auth/twitter/callback', passport.authenticate('twitter', { 48 | successRedirect: '/profile', 49 | failureRedirect: '/', 50 | })); 51 | 52 | router.get('/auth/google', passport.authenticate('google', { scope: ['profile', 'email'] })); 53 | 54 | router.get('/auth/google/callback', passport.authenticate('google', { 55 | successRedirect: '/profile', 56 | failureRedirect: '/', 57 | })); 58 | 59 | module.exports = router; 60 | 61 | function isLoggedIn(req, res, next) { 62 | if (req.isAuthenticated()) 63 | return next(); 64 | res.redirect('/'); 65 | } 66 | -------------------------------------------------------------------------------- /routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET users listing. */ 5 | router.get('/', function(req, res, next) { 6 | res.send('respond with a resource'); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /views/error.ejs: -------------------------------------------------------------------------------- 1 | <% include partials/head %> 2 | 3 |
4 |