Skip to content
Go back

Building a REST API with Fastify Plugins for Validation and Authentication

Building a REST API with Fastify Plugins for Validation and Authentication

Introduction

This guide shows how to create a secure REST API using Fastify with plugin-driven validation via fastify-sensible and fastify-jwt. You’ll learn to validate request payloads and protect routes with JSON Web Tokens.

Prerequisites

Step 1: Initialize the Project

mkdir fastify-auth-api
cd fastify-auth-api
npm init -y

Step 2: Install Dependencies

npm install fastify fastify-sensible fastify-jwt fastify-plugin @sinclair/typebox

Step 3: Configure Fastify Server

Create src/server.ts:

import Fastify from "fastify";
import sensible from "fastify-sensible";
import jwt from "fastify-jwt";
import authRoutes from "./routes/auth";

async function buildServer() {
  const app = Fastify({ logger: true });

  app.register(sensible); 
  app.register(jwt, {
    secret: process.env.JWT_SECRET || "supersecret",
  });

  app.register(authRoutes, { prefix: "/auth" });

  return app;
}

if (require.main === module) {
  buildServer().then(app => app.listen({ port: 3000 }));
}

export default buildServer;

Step 4: Create Validation Schemas

Create src/schemas/user.ts:

import { Static, Type } from "@sinclair/typebox";

export const UserSignUp = Type.Object({
  username: Type.String({ minLength: 3 }),
  password: Type.String({ minLength: 6 }),
});

export type UserSignUpType = Static<typeof UserSignUp>;

Step 5: Implement Authentication Routes

Create src/routes/auth.ts:

import { FastifyPluginAsync } from "fastify";
import fp from "fastify-plugin";
import { UserSignUp } from "../schemas/user";

const authRoutes: FastifyPluginAsync = async app => {
  app.post(
    "/signup",
    {
      schema: { body: UserSignUp },
    },
    async (request, reply) => {
      const { username } = request.body as any;
      // TODO: save user to DB
      const token = app.jwt.sign({ username });
      reply.send({ token });
    }
  );

  app.post("/login", async (request, reply) => {
    const { username } = request.body as any;
    // TODO: verify credentials
    const token = app.jwt.sign({ username });
    reply.send({ token });
  });

  app.get(
    "/profile",
    {
      preValidation: [app.jwt.verify],
    },
    async request => {
      return { user: request.user };
    }
  );
};

export default fp(authRoutes);

Step 6: Test the API

curl -X POST http://localhost:3000/auth/signup \
  -H "Content-Type: application/json" \
  -d '{"username":"alice","password":"secret123"}'

Summary

You now have a Fastify REST API with schema validation and JWT-based authentication. Extend this by integrating a database, refresh tokens, and role-based access control.


Share this post on:

Previous Post
Fastify TypeScript Setup: High-Performance Node.js API Framework
Next Post
Legal Tech Revolution: How Calgary Law Firms Are Going Digital