npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@moveaxlab/nestjs-security

v10.1.2

Published

A NestJS library to handle JWT authentication for web and mobile apps.

Downloads

356

Readme

NestJS Security

NPM npm

This package contains security utilities for NestJS projects, for both REST and GraphQL API gateways. It supports both express and fastify.

Installation

yarn add @moveaxlab/nestjs-security

Setup with cookies

For web applications you can rely on cookies.

Include the SecurityModule inside your application:

import { SecurityModule } from '@moveaxlab/nestjs-security';

@Module({
    imports: [
        SecurityModule.forRoot({
            type: "cookie",
            cookieDomain: "localhost",  // the domain of your app
            cookieExpirationMilliseconds: 15 * 60 * 1000,
            jwtSecret: "secret",
            // the name of your cookies
            accessTokenCookieName: "access_token",
            opaqueTokenCookieName: "opaque_token",
            refreshTokenCookieName: "refresh_token",
        })
    ]
})
export class AppModule;

Remember to enable cookie support for your application.

When using cookies, you can replace the access token with an opaque token if your access token may be too big for HTTP headers.

To enable the opaque token, install ioredis as a dependency, and configure the redis option. The access token will be stored on the configured redis server, and will be replaced in the cookies with a randomly generated token.

Setup with headers

For mobile and desktop applications you can rely on authentication headers.

import { SecurityModule } from '@moveaxlab/nestjs-security';

@Module({
    imports: [
        SecurityModule.forRoot({
            type: "header",
            jwtSecret: "secret",
        })
    ]
})
export class AppModule;

Custom token conversion logic

All configurations accept a tokenConverter option to implement custom transformations on the parsed access token.

Authenticating users

You can authenticate users based on their role (or token type) or based on the permission. The library assumes that all access tokens contain a tokenType field or a permissions array. Authentication can be applied on the class level or on the method level.

@Authenticated

The library will check that the token type is equal with one of the roles declared in the decorator

import { Authenticated } from "@moveaxlab/nestjs-security";

@Authenticated("admin", "user")
class MyController {
  async firstMethod() {
    // accessible to both admins and users
  }

  @Authenticated("admin")
  async secondMethod() {
    // only accessible to admins
  }
}

In order check that the user has a valid accessToken, but without any required permission or roles you can use the @Authenticated decorator without any tokenType.

import { HasPermission } from "@moveaxlab/nestjs-security";
import { Authenticated } from "./authenticated.decorator";

@Authenticated()
class MyController {
  async getMyProfile() {
    // only accessibile to authenticated user
  }
}

@HasPermission

The library will search for the required permission in the permissions array.

import { HasPermission } from "@moveaxlab/nestjs-security";

@HasPermission("myResource.read")
class MyController {
  async firstMethod() {
    // accessible to token with permission myResource.read
  }

  @HasPermission("myResource.write")
  async secondMethod() {
    // only accessible to token with the permissions myResourse.write
  }
}

Setting cookies

Use the CookieService to set and unset the access token and refresh token.

When using express:

import { CookieService } from "@movexlab/nestjs-security";
import { Request, Response } from "express";

class Controller {
  constructor(private readonly cookieService: CookieService) {}

  async login(@Res({ passthrough: true }) res: Response) {
    await this.cookieService.setCookies(res, accessToken, refreshToken);
  }

  async logout(@Req() req: Request, @Res({ passthrough: true }) res: Response) {
    await this.cookieService.clearCookies(req, res);
  }
}

When using fastify:

import { CookieService } from "@movexlab/nestjs-security";
import { FastifyRequest, FastifyReply } from "fastify";

class Controller {
  constructor(private readonly cookieService: CookieService) {}

  async login(@Res({ passthrough: true }) res: FastifyReply) {
    await this.cookieService.setCookies(res, accessToken, refreshToken);
  }

  async logout(
    @Req() req: FastifyRequest,
    @Res({ passthrough: true }) res: FastifyReply,
  ) {
    await this.cookieService.clearCookies(req, res);
  }
}

Using GraphQL

If you are using GraphQL, the request and response must be retrieved from the GraphQL context.

For express, setup your GraphQL module like this:

import { GraphQLModule } from '@nestjs/graphql';
import { Request, Response } from 'express';

@Module({
    imports: [
        GraphQLModule.forRoot({
            // ...
            context: ({ req, res }: { req: Request, res: Response }) => ({ req, res }),
        })
    ]
})
export class AppModule;

With fastify, the setup should look like this:

import { GraphQLModule } from '@nestjs/graphql';
import { FastifyRequest, FastifyReply } from 'fastify';

@Module({
    imports: [
        GraphQLModule.forRoot({
            // ...
            context: (req: FastifyRequest, res: FastifyReply) => ({ req, res }),
        })
    ]
})
export class AppModule;

Inside your resolvers you can access the request and response objects using the @Context("req") and @Context("res") decorators.

If you are using fastify, you cannot access the response using @Context("res") due to a bug in @nestjs/core. Access it instead with @Context() { res }: { res: FastifyReply }.

Getting the tokens inside a controller or resolver

You can access the access token and refresh token inside your controllers and resolvers using decorators.

import { Authenticated, AccessToken } from "@moveaxlab/nestjs-security";

@Authenticated("admin")
class MyController {
  async myMethod(@AccessToken() token: string) {
    // use the token here
  }
}

The refresh token can be accessed via decorators when using cookies. Include the RefreshCookieInterceptor to retrieve it.

import {
  Authenticated,
  RefreshToken,
  RefreshCookieInterceptor,
} from "@moveaxlab/nestjs-security";

@Authenticated("admin")
@UseInterceptors(RefreshCookieInterceptor)
class MyController {
  async myMethod(@RefreshToken() token: string) {
    // use the token here
  }
}

You can access the parsed access token using the @User decorator.

import { Authenticated, HasPermission, User } from "@moveaxlab/nestjs-security";

interface UserType {
  tokenType: "admin" | "user";
  uid: string;
  permission: string[];
  // other information contained in the token
}

@Authenticated("admin")
class MyController {
  async myMethod(@User() token: UserType) {
    // use the token here
  }
}

@HasPermission("myPermission")
class MySecondController {
  async mySecondMethod(@User() token: UserType) {
    // use the token here
  }
}

Using different secrets based on the issuer

The jwtSecret options can accept an object mapping the iss key contained in the token with the secret or key used to sign the token.