Purti Aggarwal
Aeologic
Published in
7 min readJul 5, 2020

--

Registration And Login With JWT Using NodeJs & ExpressJs

JWT provides a perfect system for issuing and validating authentication tokens. The authentication token will ensure that the client doesn’t need to log in every time they want to operate on the serve.

The JWT is separated into three parts by dot(.) which are

  1. Header: The header has two parts: First the type of token, which is JWT, Second the singing algorithm which is being used.
  2. Payload: The payload consists of the user data. The data means the ‘claims’ of the JWT. The data saved as a JSON object.
  3. Signature: The signature consist of the secret code which is hashed with the header and the payload. This is used to verify the authenticate the token.

Let’s start building the project

Step-1: Set up the directories

First, create the base folder(application) which contains all project-related directories. Now create the src folder which contains the server-side specific file.

Check out my previous blog on how to setup a project from scratch.

Inside the src folder create new folders — controller, DB, middleware, models & router.

Now the directory structure will look like:

Step-2: Setting up package.json file

We need to setup package.json file by running below command in the terminal inside application directory:

$ npm init -y

npm init -y command will take default configuration like description, name and other config.

If you want to provide custom configuration use npm init and it will ask you to enter all the details manually.

Step-3: Installing the modules.

$ npm i express mongoose mongodb jsonwebtoken bcryptjs validator body-parser
  1. Express: Express is used as a web application framework.
  2. Mongoose: The mongoose is used to connect the database with our project.
  3. Jsonwebtoken: Jsonwebtoken is used for Authentication and Authorization.
  4. Bcryptjs: Bcryptjs is used to hash and compare the password.
  5. MongoDB: MongoDB is a document database with the scalability and flexibility that you want with the querying and indexing that you need
  6. Validator: This library validates and sanitizes strings only.
  7. Body-parser: Extract the entire body portion of an incoming request stream and exposes it on req.body.

Here’s how our package.json will look like:

package.json file

Step-4: Configure the DataBase

First, we have to create a file ./src/db/mongoose.js under the root project.

Second, import the mongoose module in the file.

const mongoose = require('mongoose')

Third, declare the MongoDB URL for the connection

...
const MONGO_URL = mongodb://127.0.0.1:27017/app

Above 127.0.0.1:27017 is the localhost server and the app is the database name.

Fourth, and the last step to connect with the database.

...
mongoose.connect(MONGO_URL, () => {
console.log('Database is connected!')
}

Step-4: Creating the model

First, create a new file inside ./src/models/user.js & import the required modules:

const mongoose = require('mongoose')
const validator = require('validator')

Second, now we will create the user’s schema (Schema defines the structure of the data).

// Defining User collection schema structure.
// We have name, email, password field.
const userSchema = mongoose.Schema({
name: {
type: String,
require: true,
trim: true
},
email: {
type: String,
required: true,
trim: true,
lowercase: true,
unique: true,
validate(value){
if(!validator.isEmail(value)){
throw new Error('Email is invalid')
}
}
},
password: {
type: String,
required: true,
trim: true,
minlength: 7,
validate(value){
if(value.toLowerCase().includes('password')){
throw new Error('Password cannot contain "Password"')
}
}
}

})
const User = mongoose.model('User', userSchema)
module.exports = User

Now, we have to hash the password for security reasons before saving the password in the database.

...
const bcrypt = require('bcryptjs');
// This function will be called before user object get saved in the Users collection. It will simply hash the plain text passord if it is modified by the user.userSchema.pre('save', async function(next) {
const user = this
// It will check if the password is being modified or not.
if(user.isModified('password')) {
user.password = await bcrypt.hash(user.password, 8)
}
next()
)}
...

pre is used when we have to perform any task before saving, updating, delating or fetching the document from any collection.

Now we integrating the JWT into our application. The generateAuthToken method is responsible for generating the token. This method will be called when the user signs up and sign in.

...
const jwt = require('jsonwebtoken')
userSchema.methods.generateAuthToken = async function () {
const user = this
const token = jwt.sign({_id: user._id.toString() }, 'thesecretcode')
user.tokens = user.tokens.concat({ token })
await user.save()
return token
}
...

Note: “thesecretcode ”used in above for signing the token will be the private key and you need to generate a unique key for different projects.

Now we have to store the token in the database for the user who signing or registered.

// other property of model, you need to add this property in User Schema for storing the multiple token for each user....
tokens: [{
token: {
type: String,
required: true
}
}]
...

REGISTRATION API

First, we are going to route and test the registration API.

Step-5: Route the request

The router is used to define the interaction with APIs and used to send and receive the requests from the server.

First, we create the file ./src/router/userRouter.js

Now we have to route the request

const express = require('express')
const AuthController = require('../controller/authController')
const router = express.Router()//Signup request
router.post('/signup', AuthController.registration)
modue.exports = router

A router is supposed to forward the request to the appropriate controller function. So, our next step is to create the controller.

Step-6: Creating Controller

Now we are going to create a controller which helps in getting the requested data from the model.

Create the directory ./src/controller/userController.js

First, we create the controller for user signup and the sign in.

const User = require('../modeld/user')class AuthController {
static registration= async (req, res) => {
const user = new User(req.body)
try {
await user.save()
res.status(200).send({
status: 200,
message: 'Successfully Registered',
userData: user
})
} catch (error) {
res.status(400).send({
status: 400,
message: error.message
})
}
}

Step-7: Create the Index.js

Now we going to create the main file of our project that is the index.js

We have to require all files in index.js because it handles our application startups and all other functions.

const express = require('express')
const bodyParser = require('body-parser')
const userRouter = require('./router/userRouter')
require('./db/mongoose')
const app = express()

app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: true})
app.use(userRouter)const port = process.env.PORT || 3000app.listen(port, ()=> {
console.log('Server is up to '+ port)
})

Test Registration API

We have to send the data in the JSON form through the JSON body of the postman.

Send Registration API Data

If your code correctly then you will get the status 200 OK and the result as follow.

Result of Registration API

LOGIN API

For Login, we already have a model of the user now just we have to find the credentials in the database if credentials it exists you will get 200 OK status or not then you will get 404 Not Found.

So we have to make the function for finding the credentials in the model i.e, user.js.

...
userSchema.statics.findByCredentials = async (email, password) => {
const user = await User.findOne ({ email })
if(!user) {
throw new Error('Unable to Signin')
}
const isMatch = await bcrypt.compare(password, user.password)
if(!isMatch) {
throw new Error('Unable to Signin')
}
return user
}
...

Step-8: Creating Controller

We are creating the controller for user sign in.

...

static signin = async (req, res) => {
try{
//find the credentials from the database
const user = await User.fendByCredentials(req.body.email , req.body.password)
//generate a token
const token = await user.generateAuthToken()
res.status(200).send({
status: 200,
message: 'Successfully Signin'
data: {
userData: user, token
}
})
}catch(error) {
res.status(400).send({
status: 400,
message: error.message
})
}
}
...

Step-9: Create the router

Now, route the request for the sign in.

...router.post('/signin', AuthController.signin)...

Test Login API

We have to send the credentials in the JSON form through the JSON body of the postman.

Send Sign-in Request
Result of Sign-in API

Summary

In this blog, we learned about JWT. JWT is a standard that defines a compact and self-contained way to securely transmit information between a client and a server as a JSON object. In this blog, we made the registration and the login REST API. Here we did the basic validation as well keeping in mind to hash the password before saving in the database. Also integrated the function for the JWT authentication.

In my next blog, we will learn how to upload single and multiple images and save them in the database. Hopefully, this article helps you with Registration And Login With JWT Using NodeJs & ExpressJs.
For the reference of the above code https://github.com/purtiAggarwal123/registration-and-login-with-jwt-authentication.git

Feel free to connect with us read more articles from Aeologic.com.

Aeologic Technologies is a dynamic, solution, and value-driven technology company. We position ourselves as a new generation cutting edge technology company. We work creatively to enable businesses with leading technologies and solutions. You can connect with us on Facebook, Twitter, and LinkedIn for any queries.

--

--