├── server ├── config.js ├── package.json ├── permission-handler.js ├── passport-facebook.js ├── passport-twitter.js └── start.js ├── README.md ├── .gitignore ├── client ├── app.css └── index.html └── LICENSE /server/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | HTTP_PORT: 7072, 3 | HOST_NAME: process.env.HOST_NAME, 4 | 5 | FACEBOOK_ID: process.env.FACEBOOK_ID, 6 | FACEBOOK_SECRET: process.env.FACEBOOK_SECRET, 7 | 8 | TWITTER_KEY: process.env.TWITTER_KEY, 9 | TWITTER_SECRET: process.env.TWITTER_SECRET 10 | } -------------------------------------------------------------------------------- /server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "src/start.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "deepstream.io": "^1.0.0", 13 | "express": "^4.13.4", 14 | "express-session": "^1.13.0", 15 | "lodash": "^4.9.0", 16 | "passport": "^0.3.2", 17 | "passport-facebook": "^2.1.0", 18 | "passport-twitter": "^1.0.4", 19 | "use-express-middleware": "^1.0.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ds-tutorial-passport-auth 2 | A basic example on how to integrate facebook auth using the amazing passport.js library and use-express-middleware 3 | 4 | Steps: 5 | - cd server 6 | - npm install 7 | - HOST_NAME=`HOST_NAME` FACEBOOK_ID=`FACEBOOK_ID` FACEBOOK_SECRET=`FACEBOOK_SECRET` TWITTER_KEY=`TWITTER_KEY` TWITTER_SECRET=`TWITTER_SECRET` node start.js 8 | 9 | Note: You need a facebook application, twitter application and to ensure the hostname provided is accessible publicly ( either by hosting it on a public accesible machine or using a tool like [ngrok](https://ngrok.com/) to expose your localhost ). 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | node_modules 28 | 29 | # Optional npm cache directory 30 | .npm 31 | 32 | # Optional REPL history 33 | .node_repl_history 34 | -------------------------------------------------------------------------------- /server/permission-handler.js: -------------------------------------------------------------------------------- 1 | var useExpressMiddleware = require( 'use-express-middleware' ); 2 | 3 | function PermissionHandler( middleware ) { 4 | this._middleware = middleware; 5 | } 6 | 7 | PermissionHandler.prototype.isValidUser = function( connectionData, authData, callback ) { 8 | useExpressMiddleware( connectionData.headers, this._middleware, ( req, res ) => { 9 | if( req.user ) { 10 | callback( null, req.user.id ); 11 | } else { 12 | callback( 'Login Denied' ); 13 | } 14 | } ); 15 | }; 16 | 17 | PermissionHandler.prototype.canPerformAction = function( id, message, callback ) { 18 | callback(null, true ); 19 | }; 20 | 21 | module.exports = PermissionHandler; -------------------------------------------------------------------------------- /client/app.css: -------------------------------------------------------------------------------- 1 | a { 2 | padding: 20px; 3 | margin: 20px; 4 | border: 1px solid #ccc; 5 | display: block; 6 | text-decoration: none; 7 | color: #fff; 8 | border-radius: 5px; 9 | text-align: center; 10 | } 11 | .login, .app { 12 | margin: 0 auto; 13 | margin-top: 100px; 14 | max-height: 400px; 15 | width: 300px; 16 | } 17 | .facebook { 18 | background-color: #3B5998; 19 | } 20 | .twitter { 21 | background-color: #45B0E3; 22 | } 23 | .logout { 24 | background-color: #002638; 25 | } 26 | .fa { 27 | margin-right: 5px; 28 | font-size: 20px; 29 | } 30 | .app { 31 | display: none; 32 | font-size: 20px; 33 | text-align: center; 34 | } 35 | .loggedin .login { 36 | display: none; 37 | } 38 | .loggedin .app { 39 | display: block; 40 | } -------------------------------------------------------------------------------- /server/passport-facebook.js: -------------------------------------------------------------------------------- 1 | var config = require( './config' ); 2 | var PassportFacebook = require( 'passport-facebook' ); 3 | 4 | function enablePassportFacebook( app, passport ) { 5 | passport.use( new PassportFacebook( { 6 | clientID: config.FACEBOOK_ID, 7 | clientSecret: config.FACEBOOK_SECRET, 8 | callbackURL: '//' + config.HOST_NAME + '/login/facebook/return' 9 | }, 10 | ( accessToken, refreshToken, profile, cb ) => { 11 | return cb( null, profile ); 12 | } ) ); 13 | 14 | app.get( '/login/facebook', passport.authenticate('facebook') ); 15 | 16 | app.get( '/login/facebook/return', 17 | passport.authenticate('facebook', { failureRedirect: '/login' }), 18 | ( req, res ) => { 19 | res.redirect('/'); 20 | } ); 21 | } 22 | 23 | module.exports = enablePassportFacebook; 24 | -------------------------------------------------------------------------------- /server/passport-twitter.js: -------------------------------------------------------------------------------- 1 | var config = require( './config' ); 2 | var PassportTwitter = require('passport-twitter').Strategy; 3 | 4 | function enablePassportTwitter( app, passport ) { 5 | passport.use( new PassportTwitter( { 6 | consumerKey: config.TWITTER_KEY, 7 | consumerSecret: config.TWITTER_SECRET, 8 | callbackURL: '//' + config.HOST_NAME + '/login/twitter/return' 9 | }, 10 | ( accessToken, refreshToken, profile, cb ) => { 11 | return cb( null, profile ); 12 | } ) ); 13 | 14 | app.get('/login/twitter', passport.authenticate('twitter') ); 15 | 16 | app.get('/login/twitter/return', 17 | passport.authenticate('twitter', { failureRedirect: '/login' } ), 18 | ( req, res ) => { 19 | res.redirect('/'); 20 | } 21 | ); 22 | } 23 | 24 | module.exports = enablePassportTwitter; 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 deepstreamHub GmbH 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /client/index.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |