Build a Modern Node.js API using Fastify and JSON Web Tokens

Build a Modern Node.js API using Fastify and JSON Web Tokens

Learn to build a modern Node.js API using Fastify and JSON web tokens! Fastify is a web framework for Node.js. Fastify is also TypeScript friendly, in this tutorial you will use JavaScript. You will use Okta as an authentication server which will produce a JSON Web Token (JWT) after authenticating the user. You will use Okta’s JWT verifier to quickly set up the authentication on your server.

Fastify is fast! Learn to build a modern Node.js API using Fastify and JSON web tokens!

Fastify is just as the name implies, fast. Not just in terms of development speed—its low overhead means the server is fast as well. When writing APIs, speed on both sides is paramount. Fastify is a web framework for Node.js that was designed for efficiency. Fastify is fully extensible with hooks, plugins, and decorators. It is schema-based, meaning you can define your response and request objects in your routes and have Fastify do the data validation for you. This feature isn’t mandatory, but it is useful. On the request side, it adds easy data validation. On the response side, this means you can shape your data for even lower overhead by not pushing down extraneous data to the client. Fastify is also TypeScript friendly. However, in this tutorial you will use JavaScript.

For this tutorial, you will create a secure API that returns some information regarding employees. To authenticate users, you will use Okta as an authentication server which will produce a JSON Web Token (JWT) after authenticating the user. The client will then send that JWT as part of the request to the server which will handle the validation logic. You will use Okta’s JWT verifier to quickly set up the authentication on your server.

Create your Okta application

The first thing you will need to do is create an application in Okta to act as your authentication server. This highlights the simplicity and streamlined process Okta authentication provides. Navigate to your Okta Developer Console and click Applications. Next click Add Application. For application type, select Service Machine-to-Machine. Give your application a meaningful name and click Done. Once your application is set up you will be presented with a Client ID and a Client secret. Make note of these as you will need them in your web application.

Next click on API in the header and the navigate to Authorization Servers. Okta will add an authorization server for you named default. This server is fine to use for development or testing. Click on Default and then click on Scopes. Click the button that says Add Scope and name it api. Click on Settings and note your Issuer URL as this is the base endpoint for requesting tokens.

Create your web server

Open your favorite IDE and navigate to the folder where you wish to store your project. Run the command mkdir *folder* where folder is your desired folder name. Next, run the command cd *folder* to navigate to your newly created project folder. Finally, create a new application by running the command npm init. Follow the wizard to help set up your project.

Now you will want to install your dependencies. You will only need a few for this project. First, you will need Fastify.

npm i [email protected]

Next, you will need Okta’s JWT Verifier. As I mentioned, this will handle the internal logic of interpreting the JWT provided by Okta’s authentication server and determining if it is valid.

npm i @okta/[email protected]

Finally, you will want to get dotenv to store your sensitive data.

npm i [email protected]

Once you have installed these, you should add a new file called .env to your root directory. Add the following code to it.

OKTA_CLIENT_ID={yourClientID}
OKTA_ISSUER=https://{yourOktaOrgUrl}/oauth2/default
OKTA_AUDIENCE='api://default'
PORT=3000

Replace {yourClientId} with the Client ID from your Okta application’s settings page. Replace {yourOktaOrgUrl} with your Okta organization URL. This can be found on your Okta Developer Dashboard with the label Org URL.

To provide data to the client you will need data on your server. For this, add a new file called sample-data.json and add the following.

{
  "Employees": [
    {
      "userId": "rirani",
      "jobTitleName": "Developer",
      "firstName": "Romin",
      "lastName": "Irani",
      "preferredFullName": "Romin Irani",
      "employeeCode": "E1",
      "region": "CA",
      "phoneNumber": "408-1234567",
      "emailAddress": "[email protected]"
    },
    {
      "userId": "nirani",
      "jobTitleName": "Developer",
      "firstName": "Neil",
      "lastName": "Irani",
      "preferredFullName": "Neil Irani",
      "employeeCode": "E2",
      "region": "CA",
      "phoneNumber": "408-1111111",
      "emailAddress": "[email protected]"
    },
    {
      "userId": "thanks",
      "jobTitleName": "Program Directory",
      "firstName": "Tom",
      "lastName": "Hanks",
      "preferredFullName": "Tom Hanks",
      "employeeCode": "E3",
      "region": "CA",
      "phoneNumber": "408-2222222",
      "emailAddress": "[email protected]"
    }
  ]
}

There’s nothing special about this data, but it gives you something to work with.

Next, add a file called server.js. The code for this file follows.

"use strict";

require( "dotenv" ).config();
const jwtVerifier = require( "./jwtVerifier" );

const fastify = require( "fastify" )( { logger: true } );
const fs = require( "fs" );
const util = require( "util" );

const readFile = util.promisify( fs.readFile );

fastify.route( {
  method: "GET",
  url: "/employees",
  schema: {
    response: {
      200: {
        type: "array",
        properties: {
          userId: { type: "string" }
        }
      }
    }
  },
  preHandler: async ( request, reply ) => {
    return jwtVerifier( request, reply );
  },
  handler: async ( request, reply ) => {
    const obj = JSON.parse( await readFile( "sample-data.json", "utf8" ) );
    return obj.Employees;
  }
} );

fastify.route( {
  method: "GET",
  url: "/employees/:userId",
  schema: {
    querystring: {
      userId: { type: "string" }
    }
  },
  preHandler: async ( request, reply ) => {
    return jwtVerifier( request, reply );
  },
  handler: async ( request, reply ) => {
    const obj = JSON.parse( await readFile( "sample-data.json", "utf8" ) );
    const employee = obj.Employees.find( r => r.userId === request.params.userId );

    if ( !employee )
      return reply.code( 404 ).send();

    return employee;
  }
} );

const start = async () => {
  try {
    await fastify.listen( process.env.PORT );
    fastify.log.info( `server listening on ${ fastify.server.address().port }` );
  } catch ( err ) {
    fastify.log.error( err );
    process.exit( 1 );
  }
};

start();

node api javascript jwt web-development

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

Hire Node.JS Developers | Skenix Infotech

We are providing robust Node.JS Development Services with expert Node.js Developers. Get affordable Node.JS Web Development services from Skenix Infotech.

A Simple Guide to API Development Tools

APIs can be as simple as 1 endpoint for use by 100s of users or as complex as the AWS APIs with 1000s of endpoints and 100s of thousands of users. Building them can mean spending a couple of hours using a low-code platform or months of work using a multitude of tools. Hosting them can be as simple as using one platform that does everything we need or as complex as setting up and managing ingress control, security, caching, failover, metrics, scaling.

Why Web Development is Important for your Business

With the rapid development in technology, the old ways to do business have changed completely. A lot more advanced and developed ways are ...

Security Concerns for Peripheral APIs on the Web

Google has been promoting the inclusion of peripheral connectivity using Bluetooth and USB on web browsers for several years. Yet, it's meeting heavy resistance from other browser vendors such as Apple and Mozilla. While Chrome supports Web Bluetooth since 2016 and Web USB since 2017, no other vendor has concrete plans for supporting these technologies, putting the future of these Web APIs under question.

Working with Data and APIs in JavaScript - Geolocation Web API

Welcome to Working with Data and APIs in Javascript! Before diving into communication between client and server (GET and POST requests), let's look at the Geolocation Web API with navigator.geolocation. Learn how to work with data in web applications and the basics of server-side programming with Node.