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
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}`);
});
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 theid_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.
Website: https://authorizer.dev
React SDK: https://github.com/authorizerdev/authorizer-react
Javascript SDK: https://github.com/authorizerdev/authorizer-js
Youtube: https://youtube.com/playlist?list=PLSQGbUjHc6bpaAgCiQPzNxiUPr7SkDAFR
Discord: https://discord.gg/Zv2D5h6kkK
Github Sponsorship: https://github.com/sponsors/authorizerdev/
Buy me Coffee: https://www.buymeacoffee.com/lakhansamani
Top comments (1)
Nice, I was also checking different ways to secure an api, but without using specialized libraries: Securing a Node.js API: A Simple Guide to Authentication. I using a specialized library, if it's well maintained, is beneficial