Simple auth system using JWT
Tags: javascript, webdev, beginners, programming
Published: 2022-08-09 04:23:00

Continuation of the last post, I will try to implement auth system by using JWT (Json Web Token) for my Multiplayer TicTacToe game.

[Live Website](https://tictactoe.khusyasy.com/)
[Source Code](https://github.com/Khusyasy/ws-tictactoe)

## What is JWT

JWT is an authorization token created from the backend, passed to the frontend and then the frontend can send this token alongside requests to access protected API routes, it is to make sure that the request from user X is indeed made by user X itself. Usually JWT token is created with expiration time.

There is a downside here for using JWT, every token that was created and not yet expired can still be used for accessing the protected API routes. Which is usually not what you wanted.

> Little disclaimer here: I think JWT itself is actually very simple, but implementing it the right way is the hard part, so if you know a better way or have a correction, please let me know! thanks.

## JWT Revoke Method

So to invalidate and limit the access of the token, from what I have found is mainly 2 methods:

1. Blacklist/Whitelist the token.
2. Use per user secret key for the token.

To be honest I still don't know the pros/cons of those methods, but I'm going to use the second one.

## Creating User Personal Key

> note: all of the examples shown are simplified version

```js
const bcrypt = require('bcrypt');

function generatePersonalKey() {
  return bcrypt.genSaltSync(10);
}
```

First the personal key, we need to create a function to generate the keys, like random strings, numbers, or anything. But here I created `generatePersonalKey()` by using the [bcrypt](https://www.npmjs.com/package/bcrypt) packages to create a random salt.

```js
const mongoose = require('mongoose');

const UserSchema = new mongoose.Schema({
  username: String,
  password: String,
  personalKey: String,
});
```

And for example my `UserSchema` ([mongoose](https://www.npmjs.com/package/mongoose)), we just initialize the personalKey when the user is created. And when user logged out we just regenerate the personalKey, this way the tokens before will always be invalid because they used the different key.

## Creating JWT

```js
const jwt = require('jsonwebtoken');

const payload = { username: 'khusyasy' };
const token =
  jwt.sign(payload, user.personalKey, {
    expiresIn: '1h',
  });
```

To create the token itself I used [jsonwebtoken](https://www.npmjs.com/package/jsonwebtoken) packages. It is actually very simple like the example above. After that we set the response cookies with the flag `httpOnly` so the token cannot be set/get by using javascript on the browser.

## Checking Authorization

When I first read about this I'm very confused, how do you know which key to use, if you can't even read the token?

Well it turns out we can... just by using `decode` to read the payload and getting the user personalKey, and then using the personalKey to verify the token itself. For example:

```js
const payload = jwt.decode(token);

const user = await User.findOne({ username: payload.username });

try {
  const verified = jwt.verify(token, user.personalKey);
  // token is verified
} catch (err) {
  // token is invalid
}
```

That is all for today, thank you for reading!

### packages used:

- [bcrypt](https://www.npmjs.com/package/bcrypt)
- [jsonwebtoken](https://www.npmjs.com/package/jsonwebtoken)
- [mongoose](https://www.npmjs.com/package/mongoose)