How to create a Authentication API using Node

Srikar Kusumanchi
Clever Programmer
Published in
6 min readNov 18, 2020

Everyone has authentication built-in to their websites and mobile applications these days. Authentication plays a huge part in the software development field and today you are going to learn how to create an Authentication REST API using Node. Before we start, be sure to have the following.

Pre-Requisites

  • Node
  • Text Editor (I will be using VS Code)
  • Determination
  • Computer
  • Wi-fi

After you have all of the above that I listed, you are ready to get started.

A Basic REST API

Let’s now create a simple REST API in NodeJS that uses Express. Create a new directory in which our project will live and run the following:

$ npm init

Keep everything as default values for now, we can edit this later should we need to.

Now that we have initialized our project, we’ll need to install the express.js Node Module:

$ npm install express --save

This will go away and fetch the required express node module which we’ll be using to construct the REST API that we will be securing.

Note — We are using Express here in this particular example, but the concepts in this tutorial are framework-agnostic and can be used with other web application frameworks such as Koa.

Now that we have all of our dependencies installed, we can go ahead and write some code! Create a new file within your project directory called index.js.

index.js

const express = require('express')
const app = express()
const port = 3000
app.get('/', (req, res) => res.send('Hello World!'))
app.listen(port,
() => console.log(`Simple Express app listening on port ${port}!`))

This is an incredibly simple application that returns Hello World! whenever you hit the / path on port 3000. You can subsequently start this application like so:

$ node index.js

Example app listening on port 3000!

With this now running, navigate to http://localhost:3000/ in your browser and you will see your application returning the expected Hello World! back to you.

Adding a few Endpoints

Now that we have a basic NodeJS application up and running on port 3000, let’s look at how we can extend this and add a few endpoints which we can subsequently protect.

I’m going to keep this super simple for now so that we can focus on the JWT authorization and not the underlying application.

Open up your index.js file once again. Let’s add a few new HTTP GET endpoints:

index.js

const express = require('express')
const app = express()
const port = 3000
app.get('/', (req, res) => res.send('Hello World!'))// let's first add a /secret api endpoint that we will be protecting
app.get('/secret', (req, res) => {
res.json({ "message" : "THIS IS SUPER SECRET, DO NOT SHARE!" })
})
// and a /readme endpoint which will be open for the world to see
app.get('/readme', (req, res) => {
res.json({ "message" : "This is open to the world!" })
})
app.listen(port,
() => console.log(`Simple Express app listening on port ${port}!`))

Now that we have these endpoints, let’s re-run our application to ensure we haven’t broken anything:

$ node index.js

Simple Express app listening on port 3000!

Let’s open up http://localhost:3000/secret in our browser window now that this is up and running. You will see the following response:

http://localhost:3000/secret

{
"message": "THIS IS SUPER SECRET, DO NOT SHARE!"
}

And when we open up the /readme endpoint, we should see the following:

http://localhost:3000/secret

{
"message": "This is open to the world!"
}

Perfect, in this step we have been able to add 2 additional endpoints to our application that we will be attempting to protect with JWT validation in the next step of this tutorial.

Generating a Valid JWT

In this step, we are going to create 1 additional endpoint for our application that will return a valid JWT token for us to test out the authentication in subsequent steps.

In order for us to generate and validate these JWTs, we’ll need to first import the jsonwebtoken node module:

$ npm install --save jsonwebtoken

Once we have this node module installed, we can then go ahead and create a custom /jwt endpoint which will create a JWT token for us which features an incredibly simple payload { "body": "stuff" } and is signed using a private key that I generated for a deprecated project.

Create a new file within your project direct called private.pem and add the following key:

private.pem

-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAyVTQ9QxfutaYXKBbYfZbH2vhIWoIPEjAFSbsy1PZoIcclUQR
hJ8t2m7v47M8eEyYd7EvXTNdoN6CDs0DoNC9KESATZV5SUVr7sk9pOcMrm0VryAd
h7hQbbHWqyKmOehCt1JdX7gV2i5XnRb5qYQSyoB8sGdfR4SQ9q1XPRIpBP8RYXCP
WPmwnmtzYjfs+VVMp+ByNWgM8Qvyc3Z13tHKHWfTokbEbJJE0xfFG6CVFZy+T7uq
0UxhkWh8tekaDbfrIYtgC8HRHfRPcqvsN/pkJM0DIU4UNIf2TeLARa+iATNiF5IX
DeAAkIqoQL0tgt6S+8HIEPGiQ3gpGE56DON06QIDAQABAoIBAAvIxyJQwxmwjeJ+
EFs/jD3elqLaDflZWMTkLmAIXGik/+tMvKnCl3B9pdTyHMv9z77RxC/0XbqYy4wK
O/ghv7CnscrYwOyk/5hOdyk7zOY4xFgnzRKwmySQkDwcHxasnZsVWxnLMJxAsigj
vCFL9b2cn6/DnTQWclW996k/ct8z5DzodH/O+JyQl2MvLgjtf1OupbNZcjt4kMRP
GS5em5banlycUtPE0NAcS0QXleHLj5BXOp0AyD+PWfzhWcctiK7p+vmwXv6OVtlu
DIiTTOnsjoMq7skfVzRpjmAesllXBb1evwsrVK7cjYefEsVZ5DzOVLNU5Iug3HCf
RnftUAECgYEA6uWhJ9la1VpiYgEai4F61Rxs/MAQzmWVl0NQhPrczLCdRXfhmeBP
w1a4VkCD7FlZq/UuL4bSnU2JINL/enmrfZfdLdQgjY1VgPNki6v4Da9sqi+D17Wb
w863h/X29cukttFgUQdPO66bwsitoNVDsBqyf2hlFWC+rRPovoFA9WkCgYEA22s2
njRgoV6mTTCgXoZMs8unJ2CTd+BuVP1wDVsHR0VnK7blVlIW9Hop0ZmFK3I41kw3
3LXT6RSmZXsdgAsm3VuWlDVFY6t+JUUGYOfZZVNgUX0J597hf2SwxfJ8cgNHuSEO
glxc/dzHXMgamf8+84RCK3NSGP8xmuI/Wm5JE4ECgYEAmFelVTradlTQSc99b8zh
5SUyahoGzFWF1zyJFDW+zeIdndhKMIoSMRYlJ4tgBAFO7v9snNZL8kk/DlLJ7pzK
ZAICKJ7THfrz4VX5d7xofDexug5m65eVFkETNtKHAJK6mPbiCKs87/AmhQWx1gV6
iNRHv+ns5RiBka6/3A3oG0ECgYEAl+qIO0rqaG++1ozHTArSCl4DUlkkYQhLe56p
OSYASRE9WF/eM0DM0eHPGGahdC42OfE1cCOYH7WDa5mtGB0ggHxMKjsj2tk+kpFS
1D9SHjx24JShCiAfonNVjQfRr6KjwwKnKAzI+Z8ljRCikmLN9A5rPegvPE1by++/
i132TIECgYAiDd+OSokfZYi8mqjIoMI946+Hlb7lisb7CXksM69A+oWJrfkCwOMq
O3tExLbxtd7KZuAg1xH2thimIeT6tuCbCSAFGzr4EWCe7iavVzevHr98ivPLYXte
dyWl3YlvqO+SUuieGvHISlekblMO/4tcUscmKmo+FgkMroBsePcdEA==
-----END RSA PRIVATE KEY-----

Next, open up your index.js and add the following:

index.js

const jwt = require('jsonwebtoken');
const fs = require('fs')
app.get('/jwt', (req, res) => {
let privateKey = fs.readFileSync('./private.pem', 'utf8');
let token = jwt.sign({ "body": "stuff" }, "MySuperSecretPassPhrase", { algorithm: 'HS256'});
res.send(token);
})

When we open up http://localhost:3000/jwt in our browser after restarting our application, we should see a valid JSON Web Token returned to us:

http://localhost:3000/jwt

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJib2R5Ijoic3R1ZmYiLCJpYXQiOjE1NTg4MTUyMzl9.3Z8G-kCEfr2Xch1FnaEAOeywcVs6aJZ3sbCARybWCgM

Awesome, we now have a valid JWT that we can use to test the authentication we are going to be building in the next part of this tutorial!

Authentication Middleware

Let’s have a look at the authentication function which will look at an incoming request and parse it for an Authorization header.

index.js

function isAuthenticated(req, res, next) {
if (typeof req.headers.authorization !== "undefined") {
// retrieve the authorization header and parse out the
// JWT using the split function
let token = req.headers.authorization.split(" ")[1];
let privateKey = fs.readFileSync('./private.pem', 'utf8');
// Here we validate that the JSON Web Token is valid and has been
// created using the same private pass phrase
jwt.verify(token, privateKey, { algorithm: "HS256" }, (err, user) => {

// if there has been an error...
if (err) {
// shut them out!
res.status(500).json({ error: "Not Authorized" });
throw new Error("Not Authorized");
}
// if the JWT is valid, allow them to hit
// the intended endpoint
return next();
});
} else {
// No authorization header exists on the incoming
// request, return not authorized and throw a new error
res.status(500).json({ error: "Not Authorized" });
throw new Error("Not Authorized");
}
}

Now that we have this isAuthorized function, we can update our /secret endpoint to use this function as middleware.

index.js

app.get('/secret', isAuthorized, (req, res) => {
res.json({ "message" : "THIS IS SUPER SECRET, DO NOT SHARE!" })
})

If we restart our application and try hitting the /secret endpoint once again, we should see the following response:

http://localhost:3000/secret

{
"error": "Not Authorized"
}

Perfect, this has worked exactly as expected and we aren’t able to access our /secret endpoint without the appropriate Authorization header set. Let’s attempt to hit this endpoint with a curl command, we’ll add the Authorization header and set it to jwt along with a valid JWT retrieved from our /jwt endpoint.

curl -H “Authorization: jwt “ http://localhost:3000/secret

{"message":"THIS IS SUPER SECRET, DO NOT SHARE!"}%

Awesome, with this valid JWT in our Authorization header, we’ve been able to access the /secret endpoint!

Conclusion

In this tutorial, we have managed to create an `isAuthenticated` middleware function that we can wrap our express API Endpoints with. This `isAuthenticated` function parses incoming `HTTP` requests to check if they have the appropriate `Authorization` header set and then checks to see whether the value of this header is a valid JWT token that has been signed with a specific private key.

I’m done. Now, what’s next?

The fun doesn’t end here, it continues. You can keep making new things and learn new things with the other blogs that Clever Programmer has published.

There are many more clones, tips, and so much more to come. I know you’re hyped and ready, but you have to wait. You can also check the YouTube channel if you’re way too excited about some cool content.

Share this with anybody you think would benefit from this. Have any suggestions? Feel free to hit me up!

See you in the next one!

Srikar Kusumanchi

--

--

Srikar Kusumanchi
Clever Programmer

Blogger, freelancer, web/mobile app developer! Let’s connect! IG: srikar.programs