✒️
SEI 802
  • Introduction
  • About These Notes
  • Syllabus
  • Development Workflow
    • Installfest
      • Mac OSX
      • Linux
      • Git Configuration
      • Sublime Packages
    • Command Line
      • The Terminal
      • Filesystem Navigation
      • File Manipulation
      • Additional Topics
    • Intro to Git
      • Version Control
      • Local Git
      • Remote Git
      • Git Recipes
    • Group Collaboration
      • Git Workflows
      • Project Roles and Tools
    • VS Code Tips & Tricks
  • HTML/CSS
    • HTML
    • CSS Selectors
    • CSS Box Model and Positioning
      • Box Model
      • Display and Positioning
      • Flexbox
      • Grid
      • Flexbox & Grid Games
      • Floats and Clears
      • Additional Topics
    • Advanced CSS
      • Responsive Design
      • Pseudo-Classes/Elements
      • Vendor Prefixes
      • Custom Properties
      • Additional Topics
    • Bootstrap
    • CSS Frameworks
    • Accessibility
  • JavaScript
    • Primitives
    • Arrays
    • Objects
    • Control Flow
      • Boolean Expressions
      • Conditionals
      • Loops
      • Promises
    • Functions
      • Callbacks
      • Timing Functions
      • Iterators
    • DOM and Events
    • DOM Manipulation
    • HTML5 Canvas
    • How To Reduce Redundancy
    • (2019) JavaScript OOP
    • (2016) OOP with Classes
    • (1995) OOP with Prototypes
      • Constructors
      • Prototypes
    • Intro to TDD
    • Scoping
    • Inheritance
      • Prototypal Inheritance
      • Call, Apply, and other Functions
      • ES6 Inheritance
      • Resources
    • Custom Node Modules
    • Additional Topics
      • AJAX, Fetch, and Async/Await
      • AJAX w/JSON and Localstorage
        • AJAX w/JSON
        • Local Storage
      • Async module
      • Data Scraping
  • jQuery
    • Intro
      • DOM Manipulation
      • Reddit Practice
      • Styling
      • Events
    • Plugins
    • AJAX
  • APIs
    • Fetch
    • AJAX w/jQuery
    • AJAX w/Fetch
  • Databases
    • Intro to SQL
    • Advanced SQL
    • MongoDB
      • Intro to NoSQL
      • CRUD in MongoDB
      • Data Modeling
      • Intermediate Mongo
  • Node/Express
    • Node
      • Intro to Node
      • Node Modules
      • Node Package Manager (NPM)
    • Express
      • Intro to Express
        • Routes
        • Views
        • Templates
        • Layouts and Controllers
        • CRUD & REST
          • Get and Post
          • Put and Delete
      • APIs with Express (request)
      • APIs with Express (axios)
    • Sequelize
      • Terminology
      • Setup
      • Using Models
      • Seeding Data
      • Validations and Migrations
      • Resources
      • 1:M Relationships
      • N:M Relationships
    • Express Authentication
      • Research Components
      • Code Components
      • Auth in Theory
        • Sessions
        • Passwords
        • Middleware
        • Hooks
      • Auth in Practice
        • Create the User
        • User Signup
        • Sessions
        • User Login
        • Authorization and Flash messages
    • Testing with Mocha and Chai
    • Mongoose
      • Mongoose Associations
    • JSON Web Tokens
      • Codealong
    • Additional Topics
      • oAuth
      • Geocoding with Mapbox
      • Geocoding and Google Maps
      • Cloudinary
      • Websockets with Socket.io
      • SASS
  • Ruby
    • Intro to Ruby
    • Ruby Exercises
    • Ruby Classes
    • Ruby Testing with Rspec
    • Ruby Inheritance
    • Ruby Data Scraping
  • Ruby on Rails
    • Intro to Rails
    • APIs with Rails
    • Asset Pipeline
    • Rails Auth and 1-M
      • Auth Components
    • Rails N:M
    • ActiveRecord Polymorphism
    • Additional Topics
      • oAuth
      • SASS
      • Rails Mailers
      • Cloudinary
      • Jekyll
  • React (Updated 2019)
    • ES6+/ESNext
      • Const and Let
      • Arrow Functions
      • Object Literals and String Interpolation
      • ES6 Recap
      • ES6 Activity
    • Intro to React
      • Create React App
      • Components and JSX
      • Virtual DOM
      • Props
      • Dino Blog Activity
      • Nested Components
      • Lab: LotR
    • React State
      • Code-Along: Mood Points
      • Code-Along: Edit Dino Blog
      • Lab: Simple Calc
      • Lifting State
    • React Router
      • Browser History/SPAs
      • React Router (lesson and full codealong)
      • Router Lab
    • Fetch and APIs
      • APIs with Fetch and Axios
      • Fetch the Weather
    • React Hooks
    • React LifeCycle
      • Lab: Component LifeCycle
    • React Deployment
    • Additional Topics
      • React Frameworks
        • Material UI Theming
      • Typescript
        • More Types and Syntax
        • Tsconfig and Declaration Files
        • Generics with Linked List
      • Redux
      • TypeScript
      • Context API
      • React Native
  • Meteor
  • Deployment and Config
    • Deploy - Github Pages
    • Deploy - Node/Sequelize
    • Deploy - Node/MongoDB
    • Deploy React
    • Deploy - Rails
      • Foreman (Environment Variables)
    • Deploy - AWS Elastic Beanstalk
    • Deploy - S3 Static Sites
    • Deploy - Django
    • Deploy - Flask
  • Data Structures and Algorithms
    • Recursion
    • Problem Solving - Array Flatten
    • Binary Search
    • Algorithm Complexity
    • Stacks and Queues
    • Bracket Matching
    • Ruby Linked Lists
      • Sample Code
      • Beginner Exercises
      • Advanced Exercises
    • JS Linked Lists
      • Sample Code
      • Beginner Exercises
      • Beginner Solutions
    • Hash Tables
    • Intro to Sorting
    • Insertion Sort
    • Bucket Sort
    • Bubble Sort
    • Merge Sort
    • Quick Sort
    • Heap Sort
    • Sorting Wrapup
    • Hashmaps
    • Trees and Other Topics
  • Python
    • Python Installation
    • Intro to Python
    • Python Lists
    • Python Loops
    • Python Dictionaries
    • Python Sets and Tuples
    • Python Cheatsheet
    • Python Functions
    • Python Classes
    • Python Class Inheritance
    • Intro to Flask
    • Intro to SQLAlchemy
      • Flask and SQLAlchemy
    • Using PyMongo
    • Intro to Django
    • CatCollector CodeAlong
      • URLs, Views, Templates
      • Models, Migrations
      • Model Form CRUD
      • One-to-Many Relations
      • Many-to-Many Relations
      • Django Auth
    • Django Cheatsheet
    • Django Auth
    • Django Polls App Tutorial
    • Django School Tool Tutorial
    • Django 1:M Relationships
    • Custom Admin Views
    • Data Structures and Algorithms
      • Recursion
      • Binary Search
      • Stacks and Queues
      • Linked Lists
      • Binary Trees
      • Bubble Sort
      • TensorFlow & Neural Networks
    • Adjacent Topics
      • Raspberry Pi
      • Scripting
  • Assorted Topics
    • History of Computer Science
    • Regular Expressions
    • Intro to WDI (Course Info)
    • Being Successful in WDI
    • Internet Fundamentals
      • Internet Lab
    • User Stories and Wireframing
      • Wireframing Exercise: Build an Idea
    • Post WDI
      • Learning Resources
      • Deliverables -> Portfolio
      • FAQ
  • Projects
    • Project 1
    • Project 2
    • Project 3
      • Project 3 Pitch Guidelines
    • Project 4
    • Past Projects
      • Project 1
      • Project 2
      • Project 3
      • Project 4
      • Portfolios
    • Post Project 2
    • MEAN Hackathon
      • Part 1: APIs
      • Part 2: Angular
    • Portfolio
  • Web Development Trends
  • Resources
    • APIs and Data
    • Tech Websites
    • PostgreSQL Cheat Sheet
    • Sequelize Cheat Sheet
    • Database Administration
  • Archived Section
    • (Archived) ReactJS
      • Intro to React
        • Todo List Codealong
        • Additional Topics
      • Deploy React
      • React with Gulp and Browserify
        • Setting up Gulp
        • Additional Gulp Tasks
      • React Router
        • OMDB Router
        • OMDB Search
        • Additional Resources
      • React Animations
        • CSS Animations
    • AngularJS
      • Intro to AngularJS
        • Components and SPA
        • Create an Angular App
      • Angular Directives and Filters
      • Angular Animation
      • Angular Bootstrap Directives
        • Bootstrap Modals
      • Angular $http
      • Angular Services
        • Service Recipes
        • ngResource
        • Star Wars Codealong
      • Angular Routing
      • Angular + Express
      • Angular Authentication
        • Additional Topics
      • Angular Components
      • Angular Custom Filters
      • Angular Custom Directives
Powered by GitBook
On this page
  • Objectives
  • What is OAuth?
  • Starting Point
  • Notes when testing

Was this helpful?

  1. Node/Express
  2. Additional Topics

oAuth

PreviousAdditional TopicsNextGeocoding with Mapbox

Last updated 3 years ago

Was this helpful?

Objectives

  • Describe OAuth and its purpose

  • Explain how OAuth and Auth are different

  • Use Passport strategies for oAuth authorization

What is OAuth?

You see many sites with buttons that allow for users to sign up with their Facebook or Twitter credentials. OAuth makes all this possible.

is an agreed-upon set of standards for authorization with a third party service. It involves:

  1. Leaving a website

  2. Authenticating with the third party

  3. Then the third party will redirect the user back to the original website with, among other things, an access token that can be persisted and used to request more information later.

Since OAuth is a set of standards that are universally accepted, there's a whole bunch of libraries we can use to make this happen - like

facebook-login

You probably know this as "Login with Facebook": you click on "Login with Facebook", you're redirected to Facebook's application, and then you get back to your site. As a developer, one benefit is your application gets a whole bunch of information it can use - or persist - later on, from Facebook. A downside for the users is that in order to login, they're giving a lot of data to the requesting application. Developers and companies love this, though, because they can use all this data.

How it works

A visitor of our website clicks Login with Facebook, and leaves our original application and are brought to Facebook - as a developer, you lose everything you had (params from a form, for example).

As a Facebook user, when you login, you pass in two important pieces of information to Facebook: the app ID and the app secret that identifies the application requesting the information.

After our app is given the OK, Facebook sends back an access token. With that access token, Facebook can identify users of our application as real Facebook users. These access tokens only last so long, usually expiring after a week or so, but with this access token we can call out to Facebook, if we want, and get Facebook data associated with that Facebook user.

IMPORTANT NOTE: OAuth is an authorization standard, which is not the same as authentication. Authentication occurs when you're redirected to Facebook. Authorization occurs when you receive the access token after authentication.

Starting Point

We'll be working off a functioning Express authentication example, which you can find finished here:

For OAuth, we'll assume that you've gone through the authentication lecture, and are familiar with sessions, bcrypt, and flash messages in Express.

Create Facebook app

  • Add the Facebook Login product

    • Enable Client OAuth Login

    • Add http://localhost:3000/auth/facebook/callback to Valid OAuth redirect URIs

Once you get signed up, add your app id and secret to your .env file. We'll also add a variable for our site URL, which will be used in the Passport configuration.

FACEBOOK_APP_ID=insertkeyhere
FACEBOOK_APP_SECRET=insertkeyhere
BASE_URL=http://localhost:3000

Add Facebook attributes

OAuth uses an access token that is sent back from the provider to authorize the user. We need to store that token along with the user's identifier from Facebook. We'll need to create a migration to our existing user in order to add these additional columns.

sequelize migration:create --name addFacebookIdAndToken

Add the following to your migration in migrations/*-addFacebookIdAndToken.js

'use strict';

module.exports = {
  up: function (queryInterface, Sequelize) {
    // add facebookId and facebookToken as columns
    return queryInterface.addColumn('users', 'facebookId', Sequelize.STRING).then(function() {
      return queryInterface.addColumn('users', 'facebookToken', Sequelize.STRING);
    });
  },

  down: function (queryInterface, Sequelize) {
    // remove facebookToken and facebookId as columns
    return queryInterface.removeColumn('users', 'facebookToken').then(function() {
      return queryInterface.removeColumn('users', 'facebookId');
    });
  }
};

Lastly, run this migration.

sequelize db:migrate

Setup Passport Facebook

To setup the passport middleware, install the following module.

npm install passport-facebook

Configuring passport-facebook

You'll want to configure your Passport Facebook module within config/ppConfig.js. This is a lot of code, so we'll explain the logic using comments.

// at the very top, require the passport-facebook strategy
var FacebookStrategy = require('passport-facebook').Strategy;

/*
 * Below the LocalStrategy, setup passport to use the FacebookStrategy.
 * We'll need to pass along the app id, app secret, and callback URL from
 * environment variables. We'll also want to define the fields we're
 * getting from Facebook, and enabling proof, which tells Facebook to
 * check the client secret in order to verify our server
 */
passport.use(new FacebookStrategy({
  clientID: process.env.FACEBOOK_APP_ID,
  clientSecret: process.env.FACEBOOK_APP_SECRET,
  callbackURL: process.env.BASE_URL + '/auth/facebook/callback',
  profileFields: ['id', 'email', 'displayName'],
  enableProof: true
}, function(accessToken, refreshToken, profile, cb) {
  /*
   * This function we're inside will be called once our user is authenticated
   * by Facebook. We can access our token and profile, as well as run a callback
   * function that accepts an error and a user
   */

  // pull the email from the user's Facebook profile, if it exists
  var email = profile.emails ? profile.emails[0].value : null;

  // see if the user exists in the database by email
  db.user.find({
    where: { email: email },
  }).then(function(existingUser) {
    // if the user with a valid email exists already, link their existing account with their Facebook.
    if (existingUser && email) {
      existingUser.update({
        facebookId: profile.id,
        facebookToken: accessToken
      }).then(function(updatedUser) {
        cb(null, existingUser);
      }).catch(cb);
    } else {
      // if the user doesn't exist, findOrCreate the user on the user's Facebook id
      db.user.findOrCreate({
        where: { facebookId: profile.id },
        defaults: {
          facebookToken: accessToken,
          name: profile.displayName,
          email: email
        }
      }).spread(function(user, created) {
        // if the user is created, we're done
        if (created) {
          return cb(null, user);
        } else {
          // if the user wasn't created, they exist. Update their access token
          user.facebookToken = accessToken;
          user.save().then(function() {
            cb(null, user);
          }).catch(cb);
        }
      }).catch(cb);
    }
  }).catch(cb)
}));

Setup authentication routes

In controllers/auth.js, we can use passport.authenticate to setup two Facebook authentication routes. The first route will redirect the user to Facebook for authentication (GET /auth/facebook). The second route is the callback route that will be called by Facebook, once the user is authenticated.

router.get('/facebook', passport.authenticate('facebook', {
  scope: ['public_profile', 'email']
}));

router.get('/facebook/callback', passport.authenticate('facebook', {
  successRedirect: '/',
  failureRedirect: '/auth/login',
  failureFlash: 'An error occurred, please try later',
  successFlash: 'You have logged in with Facebook'
}));

Scope

The scope is how we ask for additional access to the user's facebook account. To facilitate login we need "public_profile" and "email", but we can ask for any level of access depending on our needs including the ability to post to the user's wall or ask for info about their posts or friends.

Adding Facebook Login Functionality

In order to login via Facebook, the last piece in the puzzle is a button to access GET /auth/facebook.

Add the following to the bottom of auth/login.ejs, outside the form.

<a href="/auth/facebook" class="btn btn-primary">
  Login via Facebook
</a>

Notes when testing

  • Ensure that your app is running using foreman.

  • Try testing login under various conditions.

  • For more security, you can choose to delete the facebookToken when converting the user to JSON.

  • You may run into issues with Facebook authentication. Be patient and debug if encountered.

To make any of our apps work, we need to first declare our app as a Facebook application using Facebook's . Ultimately, we'll be defining the set of permissions / information we are requesting from the user.

To get started we need to go to the Facebook developer portal and create an app . Follow the instructions to create an app, and ensure you enable the following configurations:

More info:

developer interface
https://github.com/WDI-SEA/express-authentication/tree/brian-finished
https://developers.facebook.com/
profileFields documentation
Facebook scope documentation
OAuth
Passport