In your routine work you login to several websites in a day using the unique username and password with which you have created an account to login into the website. It is these unique credentials that ensure security of your data related to you on the websites. But additional layer of security is a must and thus JWT can help in authentication, authorization and secure information exchange.
Authentication is crucial in web applications as it
needs to be ensured that only authenticated users can access the resources on
the application. JWT ensures strong authentication as the ID token returned to
the client is unique to each user when he/she login into the application. Also,
JWT ensures security of information transmitting between the parties as you are
certain that information is actually coming from a trusted party which is supposed
to send it.
Now lets understand what exactly is JWT. JWT is a
encoded string of characters that is generated using a secret key. This encrypted
string of characters ensures information security and is only accessible by the
party which holds the secret key with which it was encrypted.
Lets understand through a real-world scenario. You go
to a website (we call it client) and sign in using a username and password. The
client sends a request to the server with these username and password. At the
server side, these username and password is checked and if they are valid then
a JWT token is created using a secret key. This token is sent back to the
client. Now, whenever the client again sends the request then this token must
be send along with it by adding it in request header. JWT token contains
encrypted information pertaining to user level access like expiration date and
to which resources the user has access etc.
But have you
ever wondered the complexities that goes behind the authorization process. Lets
dig deeper by getting our hands on code! But before proceeding with writing the
code, you must be knowing about how to create REST API using node.js. You can
go through various tutorials before moving ahead with learning user
authentication with JWT.
Setting up the environment
Before coding, we need to setup the environment. You need
to create a node.js project by running the following command.
npm init
You need to install following dependencies first in the folder where all your source code will be saved. Run the below command in the command prompt.
npm install bcryptjs body-parser express jsonwebtoken mongoose
After all the dependencies are installed you need to setup the database and provide all the details in db.js file.
Configuring the Database
To configure the database, we will use mongodb as the
database. For that login to cloud.mongodb.com then create a cluster. When the
cluster is created, then connect with the cluster by selecting the Connect
button. Then select Connect to your Application and copy the connection string
url that we will use to connect with our database. The connection string will
look something like this as shown below which we have to add in our application
code:
mongodb+srv://<username>:<password>@cluster0.kjdhwak.mongodb.net/?retryWrites=true&w=majority
Replace the <username> and <password> with
the username and password which you have put for your cluster. Put the below
code in db.js.
const mongoose = require('mongoose');
// the URI Connection String to connect to mongodb cluster running on cloud. If do not use //database name in the connection string, mongodb will create a new database for you. Here we //define a connectionURL to contains the connection string.
var connectionUrl = 'mongodb+srv://nikhil:<password>@cluster0.kjdhwak.mongodb.net/?retryWrites=true&w=majority';
//this function establishes a connection between node.js app and mongodb database running online on cloud
//useNewUrlParser: You can set it True to use the new MongoDB
connection string parser.
//useUnifiedTopology: You can set it True to use the new Server
Discovery and Monitoring engine
var conn = mongoose.connect(
connectionUrl,
{ useNewUrlParser: true, useUnifiedTopology: true },
(err) => {
if (err) throw err;
console.log('Connected to Database!');
}
);
module.exports = conn;
Defining the authorization and authentication route
for the users
Once you define the database structure for your
application, we need to focus on defining the structure of authorizing the
users. Here we will define how the users will be authorized and allowed to
login in the application.
We also need to define the authorization structure for
the application wherein we will define to which resources the users will have
access.
You need to create a user schema in the Users.js file.
Create a ‘user’ folder and paste the below code in that. Through user schema
you can define the blueprint to create user models and what properties it
should include like name, email, password etc.
var mongoose = require('mongoose');
var UserSchema = new mongoose.Schema({
name: String,
email: String,
password: String
});
mongoose.model('User', UserSchema);
module.exports = mongoose.model('User');
Then lets first create a .env file in the our project
in VS Code to hold the secret key which will be used to create the JWT token.
Please note that this secret key is very important and you need to keep
it confidential at all times. This secret key should not be visible to public
at any time.
SECRET_KEY=’ABCEFGHIJKLMNOPQRSTUVWXYZ’
Now, lets start building the authentication logic!
For this add a folder named ‘authorization’ and create
a file named ‘authController.js’ under it. Add below code in this file.
const express = require('express');
const router = express.Router();
//create a body parser middle ware
var bodyParser = require('body-parser');
// the body parser is then used to populate the req.body with the inputs that the request
router.use(bodyParser.urlencoded({ extended: false }));
router.use(bodyParser.json());
var User = require('../user/User');
Now, once you are done with this, lets dive into the
process of creating the JWT. For that you need to add the modules jwtwebtoken
and bcryptjs. Add the below code into the authController.js file.
var jwt = require('jsonwebtoken');
var bcrypt = require('bcryptjs');
var SECRET_KEY = process.env.SECRET_KEY;
Run the below command after opening the terminal.
npm install jsonwebtoken bcryptjs
–save
Till this point, we followed all steps that are
necessary for authentication.
Now we will create a /register endpoint where we will
register the user, create a JWT token.
router.post('/register', function(req, res) {
var hashedPassword = bcrypt.hashSync(req.body.password, 8);
User.create({
name : req.body.name,
email : req.body.email,
password : hashedPassword
},
function (err, user) {
if (err) return res.status(500).send("There was a problem registering the
user.")
// create a token
var token = jwt.sign({ id: user._id }, SECRET_KEY, {
expiresIn: 86400 // expires in 24 hours
});
res.status(200).send({ auth: true, token: token });
});
});
The user is asked to submit three items in this case:
a name, an email address, and a password. We're going to use Bcrypt's hashing
algorithm to quickly encrypt the password. Next, make a new user by using the hashed
password along with a name and email. We can easily produce a token for that
user once it has been successfully created.
A payload and the secret key are the only parameters
required by the jwt.sign() method. It produces a distinctive string of
characters that serves as the payload. In this instance, the payload is an
object that merely contains the user's id. Let's create some code that uses the
token we received from the register endpoint to obtain the user id.
Now, below is the code to get the user id from the
token that we received from the request body. Add this code in
authController.js.
router.get('/person', function(req, res) {
var token = req.headers['x-access-token'];
if (!token) return res.status(401).send({ auth: false, message: 'Token not provided.' });
jwt.verify(token, config.secret, function(err, decoded) {
if (err) return res.status(500).send({ auth: false, message: 'Token authentication failed!' });
res.status(200).send(decoded);
});
});
module.export = router;
you need to add a reference to the controller in app.js.
//app.js
var authController = require('./authorization/authController');
app.use('/api/auth', authController);
module.exports = app;
Now go back to the terminal in VS Code project then change the
directory to where your actual code resides and then type below command:
node server.js
If things move smoothly and there are no bugs (which are integral part of developer’s life) you are able to connect to the database!
Till that time happy coding!
0 Comments