Working with credentials in Adonis.js

Created on 22 Sep 2021671 words・3 min read

Credentials are a big part of any app really. Any key or id that is somehow relevant to another service and allows your app to interchange data with it can be considered as a credential data.

And you can keep and then feed that data to your app in many different ways, there are some enterprice solutions like Hashicorp Vault or AWS Secrets Manager that will help you with secrets and ids, keeping them secure and allow to share them easily.

Or you can simply keep them inside your .env file and share it with your teammates via some messenger or email, but obviously this is not very secure and convinient.

So here comes a custom credentials storage to place.

The Problem

For quite some time I had a real pain with managing secrets while using Adonis.js, the problem annoyed me very much. So, each and every time when I needed to setup a copy of a service somewhere, for example let's take Heroku (you can place here most popular PaaS providers), or migrate app to another server, for example let's take self-hosted solution like Dokku, I had to set environment keys by hand and I had a lot of them.

114 to be exact.

Yes, I had that many environment variables that had to be set by hand just for one app, and Heroku does not allow batch import. Yeah, you can use something like config:set, but anyway you'll have to copy each and every variable and paste it, or write a bash script that does it for you. But it will not make the task of keeping all of these keys in a safe place and easily accessible by others easier.

And you know what's the most annoying in this, I lost all the keys several times and had to regain them once again from all the services, it took me a lot of time, hours and hours.

The Solution

The idea of creating a credentials storage for Adonis.js came to my mind quite a while ago, as an occasional Ruby on Rails user I knew that they've done it already and it works like a charm. So I had to just dig their code a bit, research and create something similar that will solve my problem, but with some Node.js specific and nuanses.

That's how I created Adonis Credentials.

The algorythm looks like this:

  1. Create a .credentials file with some content
  2. Encrypt that content with the .key file
  3. Place the files somewhere
  4. Populate values from .credentials file to environment

This is basically how it works, in a more real world example, it should take some data, for adonis-credentials it should be a valid JSON object, that may look like this:

json
{
  "google": {
    "client_id": "some-text",
    "client_secret": "some-text"
  },
  "facebook": {
    "client_id": "some-text",
    "client_secret": "some-text"
  },
  "spotify": {
    "client_id": "some-text",
    "client_secret": "some-text"
  },
  "github": {
    "client_id": "some-text",
    "client_secret": "some-text"
  },
  "apple": {
    "client_id": "some-text",
    "client_secret": "some-text",
    "app_id": "some-text",
    "team_id": "some-text"
  },
  "stripe": {
    "public_key": "some-text",
    "secret_key": "some-text"
  }
}

And then encrypt it and turn into a very long string of random characters, which you can then commit to git repository, which you must not do with plain secrets.

The .key file holds the password to that string, so here comes another bonus, this key is the only string that you should keep somewhere safe. Not 114 of them, but just one string, easy enough.

This technic brings several main positive aspects:

  1. Ability to versionise keys and secrets via git repository
  2. Ability to share the data easily via git repositiry
  3. Ability to keep and separate credentials for different environments (development, staging, production)
  4. A safer way on keeping secrets without the need of additional software

So, give it a try, it needs some additional steps to be performed to configure the provider properly, but they are easy to do and each step has an explanation on why you should do it.

Keep your secrets in a safe place!