Node.js Basics — Add Authentication to an Express App with jsonwebtoken
Tags: node, webdev, programming, javascript
Published: 2021-01-22 21:33:40

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**


Node.js is a popular runtime platform to create programs that run on it.

It lets us run JavaScript outside the browser.

In this article, we’ll look at how to start using Node.js to create programs.

### Bearer Token Authentication

We can generate a token to identify authenticated users.

When they want to make requests to our server, they send in the auth token to our server to decode it.

If it’s decoded successfully, then we let the user make the request.

We can install the `jsonwebtoken` package by running:

```
npm i jsonwebtoken
```

Then we can use it by writing:

```
const express = require('express');
const bodyParser = require('body-parser');
const jwt = require('jsonwebtoken');

const users = {
  foo: {
    username: 'foo',
    password: 'bar',
    id: 1
  },
  bar: {
    username: 'bar',
    password: 'foo',
    id: 2
  }
}

const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
  extended: true
}));

app.use(express.static('public'));
app.get('/', (req, res) => {
  res.sendFile('public/index.html');
});

app.post(
  '/login',
  function(req, res) {
    const {
      username,
      password
    } = req.body;
    const user = users[username];
    if (user === undefined) {
      return res.status(401).send('invalid user')
    }
    if (user.password !== password) {
      return res.status(401).send('invalid password')
    }

    const {
      id
    } = user;
    jwt.sign({
      id,
      username
    }, 'shhhhh', function(err, token) {
      res.send(token);
    });
  }
);

app.listen(3000, () => console.log('server started'));
```

In the `/login` route, we get the `username` and `password` properties that we make a request within the JSON request body.

Then we check the user in the `users` object.

If the username or password is invalid, then we send the status 401 with a message indicating the error.

Once everything is valid, then we create the token with the `jwt.sign` method.

The first argument is the data that will be in the token.

Then 2nd is the secret that we sign the token with.

The last argument is the callback that’s run when the token is created.

Then we send the token back to the client.

So if we make a POST request with the `/login` route and the following request body:

```
{
    "username": "foo",
    "password": "a"
}
```

We get `'invalid password'` return with the 401 status.

If we make the same request with a valid body like:

```
{
    "username": "foo",
    "password": "bar"
}
```

Then we get a signed token like:

```
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJmb28iLCJpYXQiOjE2MDA2MjUzOTd9.05p7hoD3Qma4ShXIVWi0pKBQIv4wqSvEIvuNhaJtens
```

Once we decode it, we should get all the data in the object returned.

To verify the token, we can use the `jwt.verify` method. For example, we can write:

```
const express = require('express');
const bodyParser = require('body-parser');
const jwt = require('jsonwebtoken');

const users = {
  foo: {
    username: 'foo',
    password: 'bar',
    id: 1
  },
  bar: {
    username: 'bar',
    password: 'foo',
    id: 2
  }
}

const app = express();
const SECRET= 'shhhhh';

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
  extended: true
}));

app.use(express.static('public'));
app.get('/', (req, res) => {
  res.sendFile('public/index.html');
});

app.post(
  '/login',
  function(req, res) {
    const {
      username,
      password
    } = req.body;
    const user = users[username];
    if (user === undefined) {
      return res.status(401).send('invalid user')
    }
    if (user.password !== password) {
      return res.status(401).send('invalid password')
    }

const {
      id
    } = user;
    jwt.sign({
      id,
      username
    }, SECRET, function(err, token) {
      res.send(token);
    });
  }
);

app.get('/secret', (req, res, next) => {
  console.log(req.headers)
  jwt.verify(req.headers.authorization, SECRET, function(err, decoded) {
    if (err){
      return res.status(403).send('unauthorized')
    }
    req.user = decoded;
    next()
  });
}, (req, res)=>{
  res.json(req.user);
})

app.listen(3000, () => console.log('server started'));
```

We added the `/secret` route that has a middleware that checks the `Authorization` header for the token.

Then we pass that into the `jwt.verify` method to check the token.

The 2nd argument is the same secret string that we used to sign the token.

We need this to do the check properly.

Then once we decoded the string, we return 403 error if there’s an error.

Otherwise, we set `req.user` to the decoded token object so we can use it in our route.

Then we call `next` to call the route handler.

If we make a GET request to the `/secret` route, we should get the user data returned in the response.

### Conclusion

We can use the `jsonwebtoken` package to issue and verify JSON web tokens for authentication.