Create a secure API with AdonisJS and Postgres — Part 1

Let’s begin…

First install adonisjs cli

npm i -g @adonisjs/cli

If your get a permission denied error, run npm i with sudo permissions

sudo npm i -g @adonisjs/cli

Once the installation is completed, execute below command

adonis new secure-api --api-only

Do You see the api-only flag? Well that indicates to adonis to clone a boilerplate code with API structure not a fullstack application.

AdonisJS API new project

Start your server with

adonis serve --dev

Go to your browser and open http://127.0.0.1:3333

Server is up and runing with our first route /

It is time to start coding, to do that, open the folder with your IDE(I’m using VS Code) and you will see the project’s structure

Project’s structure

Open .env file and edit it with your preferred information

HOST=127.0.0.1
PORT=3333 #server's port
NODE_ENV=development #if you set it to production, debug errors will be turned off
APP_NAME=RestAPI #your application's name
APP_URL=http://${HOST}:${PORT}
CACHE_VIEWS=false
APP_KEY=mulhgTjgI0xDvpsDWLXMJfJYCzn30B5F
DB_CONNECTION=pg
##database
DB_HOST=*****.alexcasarrubias.com.mx
DB_PORT=5432
DB_USER=myusername
DB_PASSWORD=mypassword123!.
DB_DATABASE=adonis
## end - database section
HASH_DRIVER=bcrypt

Let’s start with our authentication

If You created the project with — api only — auth module will be install automatically, if not, execute below command

adonis install @adonisjs/auth

To tell our application that will use an authentication method, we should add to our providers in start/app.js file below dependency:

  '@adonisjs/auth/providers/AuthProvider'

Providers’ section should looks like this:

const providers = [
"@adonisjs/framework/providers/AppProvider",
"@adonisjs/auth/providers/AuthProvider",
"@adonisjs/bodyparser/providers/BodyParserProvider",
"@adonisjs/cors/providers/CorsProvider",
"@adonisjs/lucid/providers/LucidProvider",
"@adonisjs/auth/providers/AuthProvider",
];

Now, open your start/kernel.js file and add below dependencies to globalMiddelware and namedMiddleware’s sections

globalMiddleware =>  'Adonis/Middleware/AuthInit'

namedMiddleware => auth: 'Adonis/Middleware/Auth'

Sections should look like this

const globalMiddleware = ["Adonis/Middleware/BodyParser","App/Middleware/ConvertEmptyStringsToNull","Adonis/Middleware/AuthInit",];
const namedMiddleware = {
auth: "Adonis/Middleware/Auth",guest: "Adonis/Middleware/AllowGuestOnly",};

Configuration

Open config/auth.js and check jwt is set as authenticator

authenticator — jwt

Open a terminal, go to your project’s folder and create a

adonis make:controller UserController

Set the controller for Http Request

Open app/controllers/Http/UserController and create two methods:

  • login
  • showUser

Add below code to our methods

async login({ request, auth }) {const { email, password } = request.all();await auth.attempt(email, password);return "Hell yeah!";}show({ auth, params }) {if (auth.user.id !== Number(params.id)) {return "Unauthorized: Not your profile";}return auth.user;}

Open start/routes.js files and add the login route at the end of the file

Route.post('login', 'UserController.login')

If your server is not running, start it

adonis serve --dev

In your browser go to : http://127.0.0.1:3333/login

Method GET not found

http://127.0.0.1:3333/loginThis error is shown because our route is a POST method

Route.post('login', 'UserController.login')

I use postman to test my endpoints, I create a new request with POST method and http://127.0.0.1:3333/login clidk SEND

UPS! it’s failing!

Epic fail, again

Let’s see the error description

Hmmm… run $ npm install pg — save Cannot find module ‘pg’

Thank You! I have to run npm install pg — save command

npm install pg

Execute

adonis migration:run

Restart your server and try again

Ok, now… how can I test if login is working?

let’s add register one user(only for testing purposes)

Add a register route as POST

Route.post(“register”, “UserController.register”);

Add register user logic

async register({ request, auth }) {const { email, username, password } = request.all();const User = use("App/Models/User");const user = new User();user.username = username;user.email = email;user.password = password;await user.save();return user;
}

Create a register request in postman and execute it

I’ve added below json body to the request

{"username":"myuser","email":"myuser@yeah.com","password":"test1234"}

Open your login request in postmand and send below json to request body

{"email":"myuser@yeah.com","password":"test1234"}

It is running!

One more step to return JWT token and our backend is ready to work!

Open UserController.js file and set login logic as below:

async login({ request, auth }) {const { email, password } = request.all();return await auth.attempt(email, password);}

Execute again the Login request and the response should looks like below:

{“type”: “bearer”,“token”: “eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjMsImlhdCI6MTYwOTU1MzM0OX0.LjQRh6Rk0oJWaCUUYde91YoesKMgTO3v10TUsimAz3Y”,“refreshToken”: null}

Part 2: Add validations, custom exceptions

Part 3: Deploy it to ElasticBeanstalk

Git hub Repo

Buy me a tequila

Mexicano, emprendedor, director de Software y amante del arte, la fotografía y la cerveza. ¡Salud!