cft

Implementing basic JWT-based authentication with LoopBack 4 and Docker for complete noobs (1/2)

When I started working on the back-end of my pet project, I dreaded the moment when I had to implement authentication and authorization (like any other developer out there).


user

Julia Mihet

3 years ago | 5 min read

LoopBack is a popular IBM library for building API’s fast and deploying them as micro services. It offers out of the box integration with TypeScript, Jest, Mocha and Docker (among others). In this article, I will share with you my noob’s journey of setting up basic JWT-based authentication using LoopBack 4 and MongoDB ran inside a Docker container.

I followed this official LoopBack 4 tutorial for adding JWT-based authentication to an existing app and adapted it to include the Docker/ MongoDB set up (which was the most difficult part for me).

Throughout the article, I will often refer to LoopBack 4 as LoopBack.

When I started working on the back-end of my pet project, I dreaded the moment when I had to implement authentication and authorization (like any other developer out there). I was a bit relieved because I knew I am familiar enough with TypeScript and Node.js to do this with LoopBack 4. But, on the other hand, I was a complete Docker noob and I wanted to run everything in Docker.

Before we move on, let me explain my technical choices.

  1. Why LoopBack? I needed micro services and I wanted a short(ish) development time*. If I really wanted to do more learning, I would have gone for Flask or Django, but I was confident enough I can handle Node.js and not have to learn too many new things in one go.
  2. Why Docker? I’m lazy. I don’t want to be bothered installing 100 new programs on my laptop to do development. I want to start Docker and have everything I need there.

Ok, back to the coding.

*let’s not fool ourselves, I wish it would have taken me 2 weeks of intense programming after work, but “real” summer decided to show up — I live in a rainy country, where “real” summer is something you enjoy while you can)

Step 1: Install dependencies

For this project, you will need the following programs installed on your local machine:

npm i -g @loopback/cli

Step 2 : Read the documentation

Here is some basic documentation for LoopBack 4:

For this particular tutorial, it’s also good if you skim the LoopBack documentation about controllers, models, relations between models, data sources and repositories.

The simplified structure of a LoopBack app looks something like this (the front-end is not part of the app, I just added it in the diagram for completeness).

The really magical part for me is the data source layer, because LoopBack has many data source connectors written for it that know how to communicate with various database solutions, like MongoDB, PostgreSQL, Redis and so on.

Step 3 : Implementation steps

Ok, so let’s write down the implementation steps:

  1. Boot a MongoDB instance on localhost through Docker, with a database named test_db. Because we are security mindful, we want to connect to this database with a username and a password that we keep in a local .env file (so we avoid sharing our credentials with the whole wide world when we share our project on GitHub, for example).
  2. Create a new datasource in our LoopBack project, and connect it to the newly created test_db database.
  3. Implement the JWT authentication example in the LoopBack 4 tutorial.
  4. Test that the api endpoints we created work as expected.

And now we finally get to the fun part… let’s write some code!

Step 4 : Create your project

lb4 auth-example

Follow the interactive terminal steps and make your choices of packages to be installed and whether you want yarn instead of npm. From experience, I noticed that yarn is faster than npm, so if you develop a bigger project, you can go for yarn. For our toy project, it doesn’t really matter which one you choose.

Step 5 : Run MongoDB in Docker

This is the step where I got stuck for several days, because I couldn’t figure out for the life of me how to create a new database in MongoDB via Docker (yes, yes, I’m a Docker noob).

For some time, I thought that the LoopBack Mongo connector will auto-magically create a new database for me. But no, creating a new database is Docker’s responsibility, not LoopBack’s.

So, we add a new docker-compose.yml file in the root directory of our project. Why Docker compose? Because it lets you run multiple containers from one single file. When your project grows, you just run docker-compose up and you’re ready to go.

In docker-compose.yml, you add the following code

docker-compose.yml

version: '3.7'
services:
mongo:
container_name: mongo
image: mongo:latest
env_file:
- .env
ports:
- 27017:27017
volumes:
- ./init-mongo.sh:/docker-entrypoint-initdb.d/init-mongo.sh
- ./data/db:/data/db

If you want a detailed explanation of each line, please go to the article here.

Brief explanation:

  • we use the latest Mongo server image to boot the Docker container
  • we use the .env file for the MongoDB credentials to be able to log in to the database in the container. Many docker-composeexamples use the environment property instead of env_file, and that’s fine for examples and toy projects, but not ok for actual development
  • the MongoDB port will be forwarded from the container to our localhost port 27017
  • the entry point for our MongoDB container is the shell script init-mongo.sh

In our root directory we will then add the 2 files we need:

.env

WARNING: (I’m sharing this with you for illustration purposes, but you should never share/commit this file. This should be kept local and added to .gitignore. In the README.md of your repo, you can instruct the people cloning your code to create their own local .env file and add their own credentials there).

MONGO_INITDB_ROOT_USERNAME=<yourMongoUser>
MONGO_INITDB_ROOT_PASSWORD=<yourMongoPassword>

init-mongo.sh

This is where we customize our Docker MongoDB instance.

#!/bin/bash
set -e

mongo <<EOF
use test_db
db.createUser({
user: '$MONGO_INITDB_ROOT_USERNAME',
pwd: '$MONGO_INITDB_ROOT_PASSWORD',
roles: [
{
role: 'userAdmin',
db: 'test_db'
},
{
role: 'readWrite',
db: 'test_db'
}
]
})
EOF

In this script, we do the following:

  1. Use the credentials from the .env file to create a new user
  2. This user will be created in our test_db database. In case this database doesn’t exist, MongoDB will know to create it by default.
  3. We assign various roles to the MongoDB user we create (readWrite is enough for what we need, but I also wanted to see the database users, so I added more roles).

Now we need to start the Docker container to make sure everything works as expected.

docker-compose up

If we don’t want to see the logs, we can run the command docker-compose up -d (-d comes from detached process = running in the background). But we want to see the logs, because there we can see this:

We can see our newly created user, with the name root and the 2 roles
We can see our newly created user, with the name root and the 2 roles

So there we have it! We successfully created a new user and a new database in a Docker container. In Part 2 of this guide, we will finally get to play with LoopBack 4.

Upvote


user
Created by

Julia Mihet


people
Post

Upvote

Downvote

Comment

Bookmark

Share


Related Articles