Home >Web Front-end >JS Tutorial >How to Create and Use a Decorator and Middleware in NestJS

How to Create and Use a Decorator and Middleware in NestJS

Mary-Kate Olsen
Mary-Kate OlsenOriginal
2025-01-13 06:05:43206browse

Decorators and middleware are the bread and butter of NestJS—tools that can make your life either incredibly easy or slightly overwhelming, depending on how you approach them.

Today, let’s walk through creating a custom decorator and middleware for user authentication, all while keeping things light and straightforward. Grab your coffee, and let’s dive in!

1. The Interface

First, let’s define an interface for our user object.

This will ensure type safety and keep our IDE happy (and who doesn’t love a happy IDE?).

export interface IUser {
  id: string;
  name: string;
  primaryEmail: string;
  phoneNumber: string | null;
  countryCode: string | null;
  dob: Date | null;
  createdAt: Date;
  updatedAt?: Date;
  deletedAt?: Date | null;
}

2. Creating a Custom Decorator

Custom decorators are like the cool kids in a NestJS application.

Here, we’re making one to fetch user metadata from the request object.

import { createParamDecorator, ExecutionContext } from '@nestjs/common';
import { IUser } from '../interface/user.interface';

export const UserMetadata = createParamDecorator(
  (_data: unknown, ctx: ExecutionContext) => {
    const request = ctx.switchToHttp().getRequest();
    return request.user as IUser;
  },
);

That’s it! This decorator can now be used to pull user info directly in your controller methods.

How to Create and Use a Decorator and Middleware in NestJS

3. Creating the Auth Middleware

Now, let’s create an AuthGuard to protect our endpoints like a virtual bouncer.

import {
  CanActivate,
  ExecutionContext,
  ForbiddenException,
  Injectable
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { verify } from 'jsonwebtoken';
import { Observable } from 'rxjs';
import { IS_PUBLIC_KEY } from '../constant/core';
import { IUser } from '../interface/user.interface';

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(
    private reflector: Reflector,
  ) { }

  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
      context.getHandler(),
      context.getClass(),
    ]);
    if (isPublic) {
      return true;
    }

    const request = context.switchToHttp().getRequest();
    const headers = request.headers;

    const token = (headers['authorization'] || '').split(' ')[1];
    if (!token) {
      throw new ForbiddenException('Not Authenticated');
    }

    const jwtOpts = {
      expiresIn: '1h', // Replace with env vars in real use
      audience: 'your-audience',
      algorithm: 'HS256',
      issuer: 'your-issuer',
    };

    try {
      const decoded = verify(token, "my-jwt-secret-token", {
        audience: jwtOpts.audience,
        issuer: jwtOpts.issuer,
      }) as { user: IUser };

      request.user = decoded.user;
      return true;
    } catch (err) {
      throw new ForbiddenException('Session Expired or Invalid');
    }
  }
}

4. Adding Metadata for Public and Internal Routes

Some routes should be public (like login), and some might be internal.

Let’s add two simple decorators for that.

import { SetMetadata } from '@nestjs/common';

export const IS_PUBLIC_KEY = 'isPublic';
export const IS_INTERNAL = 'isInternal';

export const Public = () => SetMetadata(IS_PUBLIC_KEY, true);
export const Internal = () => SetMetadata(IS_INTERNAL, true);

5. Using Them in a Controller

Finally, here’s how you can use all of these in your controller.

import { Controller, Get, UseGuards } from '@nestjs/common';
import { UserMetadata } from '../decorators/user.decorator';
import { AuthGuard } from '../guards/auth.guard';
import { Public } from '../decorators/public.decorator';

@Controller('users')
export class UserController {

  @Public()
  @Get('login')
  login() {
    return { message: 'Login endpoint (public)' };
  }

  @UseGuards(AuthGuard)
  @Get('profile')
  getProfile(@UserMetadata() user: IUser) {
    return {
      message: 'User Profile',
      user,
    };
  }
}

Wrapping Up

And there you have it! You’ve created a custom decorator, middleware, and metadata decorators to manage public routes.

Using these tools, you can build secure and organized APIs in NestJS.

If this felt like too much, remember—even Rome wasn’t built in a day, but your APIs can definitely scale faster!

How to Create and Use a Decorator and Middleware in NestJS

Feel free to tweak and experiment with these snippets.

The sky’s the limit with NestJS! ?


I’ve been working on a super-convenient tool called LiveAPI.

It’s designed to make API documentation effortless for developers.

With LiveAPI, you can quickly generate interactive API documentation that allows users to execute APIs directly from the browser.

How to Create and Use a Decorator and Middleware in NestJS

If you’re tired of manually creating docs for your APIs, this tool might just make your life easier.

How to Create and Use a Decorator and Middleware in NestJS
How to Create and Use a Decorator and Middleware in NestJS

From Lama2 to LiveAPI: Building Super-Convenient API Documentation (Part II)

Athreya aka Maneshwar for Hexmos ・ Dec 14 '24

#webdev #javascript #programming #beginners

The above is the detailed content of How to Create and Use a Decorator and Middleware in NestJS. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Previous article:Hoof ItNext article:Hoof It