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 withmongoose-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
- Create an app on facebook/google developer console
- Get App ID & Secret and store it in .dotenv file
- Download npm packages
const GoogleStrategy = require('passport-google-oauth20).Strategy;
const FacebookStrategy = require('passport-facebook').Strategy;
const findOrCreate = require('mongoose-findorcreate');
- Initialise Passport library with express
app.use(session({
secret: "mysecret",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
- 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);
- 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);
});
});
- 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);
});
}
));
- Handle GoogleAuth / FacebookAuth roomComputingResolution
app.get('/auth/google',
passport.authenticate('google', {scope: ['profile']}));
app.get('/auth/facebook',
passport.authenticate('facebook'));
- 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');
}
);