Skip to content

My first tech blog on how to understanding a login authentication app using the concept of Model-View-Controller and Objective-relation Mapping methodology.

Notifications You must be signed in to change notification settings

Dragontalker/markdown-document-login-authentication

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tech Blog - Reverse Engineering

1. Introduction

When joining a new team as a full stack developer, you will be expected to inspect a lot of code that was made by developers who worked on the project before. Therefore, being able to dissect the code and understanding the underlying logic of the code is a key skill for a professional full stack developer.

Here is a overview of directory structure of the source code we got:

.
├── config
│   ├── middleware
│   │   └── isAuthenticated.js      
│   │
│   ├── config.json     
│   └── passport.js     
│   
├── models     
│   ├── index.js       
│   └── user.js         
│ 
├── public     
│   ├── js
│   │   ├── login.js    
│   │   ├── members.js
│   │   └── signup.js
│   │
│   ├── stylesheets  
│   │   └── style.css
│   │
│   ├── login.html
│   ├── members.html
│   └── signup.html
│
├── routes      
│   ├── api-routes.js   
│   └── html-routes.js  
│ 
├── node_modules
│ 
├── server.js
│ 
└── package.json

2. Background Information

In this blog, we will take a look at a full stack project which is a login authentication system. It follows a MVC (Model-View-Controller) architect design pattern and uses ORM (Object-Ralational Mapping) in its model component. Furthermore, it uses hash function as encryption method for password data. These are the three key concepts we have to understand before we discuss the code inside this project. Let's take a deeper look at them.


2.a. What is MVC?

Here is a definition from Wikipedia:

Model-View-Controller (usually known as MVC) is a software design pattern commonly used for developing user interfaces that divides the related program logic into three interconnected elements. This is done to separate internal representations of information from the ways information is presented to and accepted from the user.

In our own words, MVC describes how data flows in our web application. For example, when the user tries to login, the email and password are passed from View to Controller, Controller then selected the correct model to possess this data. Once the data is processed by the Model and returns the result, then Controller updates the View based on that result. Therefore, understanding the MVC is equivalent to understanding the data flow itself. This is why we called it a architect design pattern.


2.b. What is ORM?

Here is a definition from Wikipedia:

Object-relational Mapping (ORM, O/RM and O/R mapping tool) in computer science is a programming technique for converting data between incompatible type systems using object-oriented programming languages. This creates, in effect, a "virtual object database" that can be used from within the programming language. There are both free and commercial packages available that perform object-relaional mapping, although some programmers opt to construct their own ORM tools.

ORM is just an alternative way to database query language. Traditionally, we just pass a query language string such as "SELECT * FROM tables" into the database to interact with it. ORM, on the other hand, use a object structure to perform the same task, which is more similar to JavaSript syntax.


2.c. What is Hash?

Here is a definition from Wikipedia:

A hash function is any function that can be used to map data of arbitrary size to fixed_size values.

Sounds complicated eh? Do not worry, we just need to know this is the way to encrypt our password so it does not get stolen by other people on the internet. That is all we need to know and packages such as bcrupt and passport will take care of everything.


3. Techs: What You Need To get started

This blog is intended for developer who has some knowledge in full stack development. The prelimianry knowledge includes:

  • Front-end Development:
    • HTML
    • CSS
    • JavaScript
    • jQuery
    • Ajax
  • Back-end Development:
    • Node.js
    • Express.js
    • JSON
    • API
  • Database:
    • MySQL

If you do not understand any of the technology listed above, make sure you do a quick Google search or take a YouTube tutorial to gain an idea of how it works. These technologies are essential to understand this project. If you are ready, let us move to the more advance parts.

There are three advanced topics we are going to disucss in details, includes:

  1. Using Sequelize as a Object-Relational Mapping tool between Node.js and MySQL;
  2. Using Bcrypt to encrypt password data and Passport as an authentication too.
  3. Identifying the different components of MVC.
  4. Understanding data flow in MVC for two main feature: Sign Up and Log In.

Ready? Let's get started!


3.a. Sequelize as ORM

Sequelize has many useful features, where we will be only using two of them in this project. If you are interested in Sequalize, check the official documents on their website.

The two functions we will be using are create and findOne.


3.a.i. create() method

create builds a new table on our MySQL database, which is equivalent to CREATE TABLE in query language. Here is a quick example from Sequelize online document.

const user = await User.create({
  username: 'alice123',
  isAdmin: true
}, { fields: ['username'] });
// let's assume the default of isAdmin is false
console.log(user.username); // 'alice123'
console.log(user.isAdmin); // false

This method is mainly used to store user information when Sign Up event is triggered from signup.html.


3.a.ii. findOne() method

findOne searches the table and return the query that matching the searching criteria, which is equivalent to 'SELECT FROM ... WHERE ...' in query language. Here is a quick example from Sequelize online document.

const project = await Project.findOne({ where: { title: 'My Title' } });
if (project === null) {
  console.log('Not found!');
} else {
  console.log(project instanceof Project); // true
  console.log(project.title); // 'My Title'
}

This method is mainly used to matching user information when Log In event is triggered from login.html.


3.b. Npm package: bcrpyt

As we mentioned in previous sections, bcrypt is a library that helps us hash the password data. Here is a quick usage example from their npm page:

bcrypt.genSalt(saltRounds, function(err, salt) {
    bcrypt.hash(myPlaintextPassword, salt, function(err, hash) {
        // Store hash in your password DB.
    });
});

3.c. Npm package: passport

As a companion to bcrypt, passports helps handle the authentication process when user tries to log in. Here is a quick usage example from their npm page:

passport.use(new LocalStrategy(
  function(username, password, done) {
    User.findOne({ username: username }, function (err, user) {
      if (err) { return done(err); }
      if (!user) { return done(null, false); }
      if (!user.verifyPassword(password)) { return done(null, false); }
      return done(null, user);
    });
  }
));

4. Understanding the MVC

Okay, now we have all the tools we need, time to dissect the code! Remember the direcotry structure graph in the intruduction section? Let's divide that graph into components of MVC so that we have a better picture of how MVC works.


4.a. Model Components

As we have discussed, Model includes all the stuffs related to database. config.json and index.js covers the connection configurations to database. user.js is where the encryption happens, and passport.js is where the authentication happens.

.  
├── config
│   ├── config.json   |==> Database connection information
│   └── passport.js   |==> Package: passport
│ 
└── models     
    ├── index.js      |==> Package: Sequelize
    └── user.js       |==> Package: Sequalize + bcrypt

4.b. View Components

The View part is the most straightforward. The usages are included in the chart below.

.
└── public     
    ├── stylesheets  
    │   └── style.css   |==> Local stylesheet
    │
    ├── login.html      |==> Default home page, also accessable from signup.html
    ├── members.html    |==> Accessable from login.html if LogIn successfully
    └── signup.html     |==> Accessable from login.html

4.c. Controller Components

For Controller, there are three categories of controllers: Session-controller, Font-end-controller, and Back-end-controller. Session-controller trackes the login status, so that as long as user is logged in, reloading the page does not log out the user. Front-end-controllers are just DOM event listeners which tracks the user actions such as submit and click. Back-end-controllers are server-side event handlers, for APIs and static files.

.
├── config
│   └── middleware
│       └── isAuthenticated.js    |==> Session Controller, need Package: express-session
│ 
├── public     
│   └── js
│       ├── login.js      |==> LogIn event controller
│       ├── members.js    |==> LogOut event controller
│       └── signup.js     |==> SignIn event controller
│
├── routes      
│   ├── api-routes.js     |==> API endpoints controller
│   └── html-routes.js    |==> HTML endpoints controller
│ 
└── server.js   |==> Middleware required for: passport + express-session

5. Understanding the data flow in MVC

Now we are familiar with the techs and understand the responsibility of each file. Let's connection everything together and see how data flows through MVC.


5.a. Data flow of Sign Up action

File: signup.html
Data: input from id: email-input 
Data: input from id: password-input
│ 
├──> Captured by Front-end Controller @ signup.js
│     
├──> 'Post' request to endpoint '/api/signup' @ api-routes.js 
│       
├──> Calling data model @ user.js
│       
├──> Encrypt the passwor data by calling bcrypt.hashSync()  @ user.js
│       
├──> Calling Sequelize.define() to store emaill and hased password to MySQL  @ user.js
│       
└──> Once done, return status 307 and redirect to endpoint '/api/login'
     │
     └──> If failed, return status 401 and error JSON message

5.b. Data flow of Log In action

File: login.html
Data: input from id: email-input 
Data: input from id: password-input
│ 
├──> Captured by Front-end Controller @ login.js
│     
├──> 'Post' request to endpoint '/api/login' @ api-routes.js 
│       
├──> Calling passport.authenticate() to verify the password @ api-routes.js
│       
├──> Calling validationPassword() method on password data @ passport.js
│
├──> Calling bcrypt.compareSync() method on match the password @ passport.js
│    │
│    └──> If failed, return status 401 and error JSON message
│       
└──> Successful authentication redirect to endpoint '/members'  @ login.js

5.c. Data flow of Log Out action

File: members.html
Hyper-refernece: /logout
│     
├──> 'Get' request to endpoint '/logout' @ api-routes.js 
│       
├──> Calling req.logout() to remove the user object stored in session @ api-routes.js
│            
└──> Successful logout redirect to endpoint '/'  @ api-routes.js

6. Wrap Up

MVC is a big concept in web development and it definitely takes time to fully understand how it works in real project. I hope this blog provides new insights that will help you build your own authentication project. If you have any questions, please contact me at [email protected] or post an issue at my GitHub page. Happy Hacking!

About

My first tech blog on how to understanding a login authentication app using the concept of Model-View-Controller and Objective-relation Mapping methodology.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published