Authorize NodeJS APIs using Authorizer
Lakhan Samani

Lakhan Samani @lakhansamani

About: I'm Lakhan Samani, an indie software engineer from India. I build dev tools & products (Authorizer.dev, Deepup.ai) and write on software, open source, finance & life. Let's connect! 🚀

Location:
Vadodara, India
Joined:
Jan 11, 2019

Authorize NodeJS APIs using Authorizer

Publish Date: May 23 '23
5 1

In this blog post, we will learn how to authorize users for API calls, based on valid sessions and roles using Authorizer. Authorizer is an open-source database-independent auth solution. You can bring your database and have authentication and authorization service ready out of the box.

For the demo purpose, we will be using [Express](https://expressjs.com/) server and writing a middleware that will validate user sessions & roles based on the JWT (JSON Web Token) in the Authorization header.

Refer to the source code on github.

Step 1: Setup Authorizer Instance

Deploy production-ready Authorizer instance using one-click deployment options available below

Infra provider One-click link Additional information
Railway.app Deploy on Railway docs
Heroku Deploy to Heroku docs
Render render button docs

For more information & deployment options like docker / Kubernetes / helm charts refer to the docs

Configure Instance

  • Open the Authorizer instance endpoint in a browser

  • SignUp as an Admin with a secure password

  • Configure environment variables from the dashboard. Check env docs for more information.

    Note: DATABASE_URL , DATABASE_TYPE , REDIS_URL are the variables that can only be configured as the authorizer instance's system environment variable.

Step 2: Create Express App

Note: This step is optional if you already have a Nodejs application up and running

  • Setup project

    # Create directory
    mkdir my-apis
    
    # Change directory
    cd my-apis
    
    # Initialize nodejs APP
    npm init -y
    
    # Install express
    npm install express
    
    # Create index.js
    touch index.js
    
  • Add Start Command to package.json

    {
      "name": "my-apis",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "start": "node index.js",
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "keywords": [],
      "author": "Lakhan Samani",
      "license": "ISC",
      "dependencies": {
        "express": "^4.18.2"
      }
    }
    
  • Setup Express App and Create a basic API in index.js

    // index.js
    const express = require('express');
    
    const app = express();
    const port = `3000`;
    
    app.get('/', (req, res) => {
      res.send('Hello World');
    });
    
    app.listen(port, () => {
      console.log(`[server]: Server is running at http://localhost:${port}`);
    });
    

Step 3: Create Authorization Middleware

  • Install @authorizerdev/authorizer-js

    npm i --save @authorizerdev/authorizer-js
    
  • Create auth_middleware.js

    touch auth_middleware.js
    
  • Implement authorization middleware

    // auth_middleware.js
    
    const { Authorizer } = require("@authorizerdev/authorizer-js");
    
    const authRef = new Authorizer({  
      authorizerURL: "AUTHORIZER_URL_FROM_STEP 1",
      redirectURL: "FRONTEND_URL",
      clientID: "AUTHORIZER_CLIENT_ID FROM DASHBOARD"
    });
    
    const authMiddleware = async (req, res, next) => {
        const authHeader = req.headers.authorization;
      if (!authHeader) {
        return res.status(403).json({ error: "Authorization not found" });
      }
    
      const splitHeader = authHeader.split(" ");
      if (splitHeader.length != 2) {
        return res.status(403).json({ error: "Invalid auth header" });
      }
    
      if (splitHeader[0].toLowerCase() != "bearer") {
        return res.status(403).json({ error: "Bearer token not found" });
      }
    
      const token = splitHeader[1];
      // Validate jwt token via authorizer sdk
      try {
        const res = await authRef.validateJWTToken({
          token,
          token_type: "id_token", // This can be access_token, refresh_token
           // roles: [user] // specify roles that you want to validate jwt for, by default it will just verify jwt.
        });
        req.user = res.claims;
      } catch (err) {
        console.error(err);
        return res.status(403).json({ error: "Invalid JWT token" });
      }
    
      next();
    }
    
    module.exports = authMiddleware
    

Step 4: Add auth middleware to APIs

Update index.js with following content

// index.js
const express = require('express');
const authMiddleware = require('./auth_middleware')

const app = express();
const port = `3000`;

app.get('/', authMiddleware, (req, res) => {
  res.send('Hello World');
});

app.listen(port, () => {
  console.log(`[server]: Server is running at http://localhost:${port}`);
});
Enter fullscreen mode Exit fullscreen mode

Step 5: Test the API

  • Start API Server

    npm start
    
  • Make a curl request

    curl http://localhost:3000
    

Note: This will return an error, as we have not specified the Authorization header with a valid JWT token

  • For this test to pass we need to have a valid JWT token, so let's generate a valid JWT by making a login call to the authorizer server

    # Replace Authorizer URL from step 1
    # Replace credentials with right credentials in --data-raw (demo@yopmail.com, Test@123#)
    # If you have no user on your instance, first signup using AUTHORIZER_URL_FROM_STEP_1/app?redirect_uri=AUTHORIZER_URL_FROM_STEP_1/app
    
    curl --location --request POST 'AUTHORIZER_URL_FROM_STEP_1/graphql' \
    --header 'Content-Type: application/json' \
    --data-raw '{"query":"mutation login {\n  login(params: {\n    email: \"demo@yopmail.com\",\n    password: \"Test@123#\"\n  }) {\n    id_token\n  }\n}","variables":{}}'
    

    This should return an id_token in response, as shown in the screenshot below. Copy the id_token from the response and pass it to our nodeJS API server

  • Test the API

    curl --header 'Authorization: Bearer TOKEN_COPIED_FROM_ABOVE_STEP' http://localhost:3000
    

That's all I hope this helps you authorize your APIs easily and make them secure based on the correct session and roles.

For more information check out the links below.

Comments 1 total

Add comment