Authentication & Security

L1: Register & Login Users

  • This will be the default implementation of taking user input via a form and storing into database

L2: Database Encryption

  • Cesar Cipher
  • Mongoose uses AES-256 for its encryption. Both encryption and authentication can be done with mongoose-encryption npm packages
  • dotenv package, create a .env file using environment variables to store sensitive data
require('dotenv').config();

L3: Hashing Passwords

  • A hash function (SHA-256) usually takes in a value and runs it through a hash function to generate a hash. This process is one way and you can't go back (Hash -> password) as it is not possible, way too time consuming
  • The md5 package can be used to provide hash functions
  • At L3, some vulnerabilities such as Hash Tables hacks & dictionary attacks are possible

L4: Salting & Hashing

  • User's password + Salt (Stored in database)
  • Salt Rounds
  • Round 1: <password> + 23423(Salt 1) -> Hash
  • Round 2: Hash + 32423(Salt 2) -> Final Hash
  • bcrypt is a popular package for salting and hashing

L5: Cookies & Sessions

  • Cookies are used to store data on your browser. For e.g. Items in shopping cart on e-commerce platform
  • Session is a period of time when the browser interacts with the server. After the initial login, the session is created till the time the user logs out
  • Using Passport.js to add cookies & Sessions
  • Packages: passport, passport-local, passport-local-mongoose, express-session

L6: OAUTH: 3rd party Token-based authorisation(Login with Facebook/GOOGLE/Twitter)

Utilising a third party such as Facebook/Google helps to perform the heavy lifting of securing user login data

Why OAuth:

  • Granular Access Level, when a user login with Facebook, the app developer can determine the type of data needed from facebook. E.g. Email, Friends.

  • Read / Read and Write Access

  • Revoke Access to go into facebook to deauthorize your app

  • Npm packages: GoogleStrategy / FacebookStrategy & mongoose-findorcreate

Workflow of Facebook/Google OAUTH

  1. Create an app on facebook/google developer console
  2. Get App ID & Secret and store it in .dotenv file
  3. Download npm packages
const GoogleStrategy = require('passport-google-oauth20).Strategy;
const FacebookStrategy = require('passport-facebook').Strategy;
const findOrCreate = require('mongoose-findorcreate');
  1. Initialise Passport library with express
app.use(session({
    secret: "mysecret",
    resave: false,
    saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
  1. Initialising Passport with MongoDB
  • Create a schema, & add GoogleID/FacebookID as a field to store it in MongoDB
  • Add the findorcreate plugin to userSchema
const userSchema = mongoose.Schema({
    email: String, 
    password: String,
    googleId: String,
    facebookId: String
});
userSchema.plugin(findOrCreate);
  1. After the model, create the Strategy and serialise and deserialise the user
passport.use(User.createStrategy());

passport.serializeUser(function (user, cb) {
    process.nextTick(function () {
        cb(null, {id:user.id, username: user.username, name: user.name});
    });
});

passport.deserializeUser(function (user,cb) {
    process.nextTick(function (){
        return cb(null,user);
    });
});
  1. Add Google/Facebook Passport Strategy
//GOOGLE OAUTH
passport.use(new GoogleStrategy({
    clientID: process.env.CLIENT_ID,
    clientSecret: process.env.CLIENT_SECRET,
    callbackURL: "http://localhost:3000/auth/google/secrets",
    userProfileURL: "https://www.googleapis.com/oauth2/v3/userinfo"
},
    function(accessToken, refreshToken, profile, cb) {
        console.log(profile);
        User.findOrCreate({ googleId: profile.id}, function(err,user) {
            return cb(err,user);
        });
    }
));

//FACEBOOK OAUTH
passport.use(new FacebookStrategy({
    clientID: process.env.CLIENT_ID_FB,
    clientSecret: process.env.CLIENT_SECRET_FB,
    callbackURL: "http://localhost:3000/auth/facebook/secrets"
},
    function(accessToken, refreshToken, profile, cb) {
        console.log(profile);
        User.findOrCreate({ facebookId: profile.id}, function(err,user) {
            return cb(err,user);
        });
    }
));

  1. Handle GoogleAuth / FacebookAuth roomComputingResolution
app.get('/auth/google', 
        passport.authenticate('google', {scope: ['profile']}));
app.get('/auth/facebook', 
        passport.authenticate('facebook'));
  1. Redirect back to HomePage route (/secrets) on success
app.get('/auth/google/secrets', 
        passport.authenticate('google', {failureRedirect: '/login'}),
        function (req,res) {
            //Successful Authentication
            res.redirect('/secrets');
        }
);

app.get('/auth/facebook/secrets', 
        passport.authenticate('facebook', {failureRedirect: '/login'}),
        function (req,res) {
            //Successful Authentication
            res.redirect('/secrets');
        }
);