fastify-hashids: Obscure Your Database IDs Like a Pro!
Tags: node, javascript, tutorial, showdev
Published: 2023-07-26 22:46:19

Greetings, fellow developers! Today, I'd like to introduce you to a Fastify plugin that can significantly simplify handling sensitive data in your applications. Say hello to **[Fastify Hashids](https://github.com/andersonjoseph/fastify-hashids)**! This plugin seamlessly integrates Hashids into your routes, providing a straightforward way to encode and decode data securely.

## The Why behind Fastify Hashids

When building web applications, it's common to use numerical IDs as primary keys in databases. However, these IDs can unintentionally leak sensitive information due to their sequential nature. For instance, if records receive IDs in ascending order, it's easy to infer the total number of records present. This seemingly harmless detail might indirectly reveal additional information like the total number of users, orders, or partial revenue, potentially posing a security risk.

Hashids comes to the rescue by obfuscating numbers, effectively resolving this issue. Here's an example of how it works:

| ID  | Encoded ID |
| --- | ---------- |
| 1   | olejRejN   |
| 2   | pmbk5ezJ   |
| 3   | pnel5aKB   |
| 4   | MvbmOeYA   |
| 5   | openRe7A   |

You can find more details about hashids in the [official documentation](https://hashids.org/).

Now, my approach when working with Fastify involves using sequential numeric IDs on the backend. However, the real magic happens when data flows in and out of the server. At that point, I implement a hashing layer using Fastify Hashids to ensure robust security without complicating things internally.

![Hashing a response with fastify-hashids](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7jl0739bvj74kbzhywlf.png)

## Using Fastify Hashids

To get started, let's install the necessary packages for your project. Open your terminal and run:

```bash
pnpm install fastify fastify-hashids
```

With the packages installed, let's put Fastify Hashids to work by creating a basic Fastify server.

```js
// index.mjs
import Fastify from 'fastify'
import { randomInt } from 'crypto'

const fastify = Fastify({
  logger: true
})

// Declare a route
fastify.get('/user', async function handler (request) {
  const id = randomInt(100000);
  const name = 'John'

  request.log.info({originalId: id});
  return { 
    id,
    name
  }
})

// Run the server!
try {
  await fastify.listen({ port: 3000 })
} catch (err) {
  fastify.log.error(err)
  process.exit(1)
}
```

If we start our server using `node index.mjs` and make some requests to it, we'll see the following output:

```bash
curl localhost:3000
{"id": 85171, "name": "John"}
```

Additionally, the console will display logs like this:

```bash
{"level":30,"time":1690406026744,"pid":59530,"hostname":"ander-server","reqId":"req-2","originalId": 85171}
{"level":30,"time":1690406026744,"pid":59530,"hostname":"ander-server","reqId":"req-2","res":{"statusCode":200},"responseTime":0.5319289565086365,"msg":"request completed"}
```

Notice the `"originalId": 85171` in the logs, helping us track the original ID before encoding.

Now, let's integrate Fastify Hashids. All we need to do is import it and register it. That's it!

```javascript
// Import the framework and instantiate it
import Fastify from 'fastify'
import fastifyHashids from 'fastify-hashids'
import {randomInt} from 'crypto'

const fastify = Fastify({
  logger: true
})

// Register Fastify Hashids
await fastify.register(fastifyHashids);

// Declare a route
fastify.get('/user', async function handler (request) {
  const id = randomInt(100000);
  const name = 'John'

  request.log.info({originalId: id});
  return { 
    id,
    name
  }
})

// Run the server!
try {
  await fastify.listen({ port: 3000 })
} catch (err) {
  fastify.log.error(err)
  process.exit(1)
}

```

With this integration, the output will look different:

```bash
curl localhost:3000
{"id": "jy2z", "name": "John"}
```

The console will still display the original ID without encoding:

```bash
{"level":30,"time":1690406026744,"pid":59530,"hostname":"ander-server","reqId":"req-2","originalId": 79501}
```

Pretty cool, right?

Fastify Hashids also offers some options for fine-tuning your hashing experience. You can pass the following options to the plugin:

- `hashidsOptions.idRegexp`: A regular expression that `fastify-hashids` uses to automatically identify properties as IDs. By default, it matches variations of "id, ids, ID, userID," etc. You can customize this regex to match your specific property names. Set it to `null` to disable the regex-based identification.

- `hashidsOptions.propertyList`: An array of property names to include in the hashing process. Properties listed here will be considered for encoding with Hashids, in addition to those identified by the `idRegexp`.

For more options, such as salt and minimum length, check out the [hashids.js repo](https://github.com/niieani/hashids.js).

## Wrap-Up

Fastify Hashids is a great tool that effortlessly integrates Hashids into your Fastify applications. It's perfect for securing sensitive data like database IDs, enhancing your application's security without adding unnecessary complexity.

Since this plugin is open-source, you're welcome to [contribute, report issues, or suggest improvements](https://github.com/andersonjoseph/fastify-hashids).

Happy coding! 🚀