@concepta/nestjs-jwt
TypeScript icon, indicating that this package has built-in type declarations

5.1.0 • Public • Published

Rockets NestJS JWT

A flexible JWT utilities module for signing and validating tokens.

This module extends/wraps the @nestjs/jwt module.

Project

NPM Latest NPM Downloads GH Last Commit GH Contrib NestJS Dep

Table of Contents

Tutorials

Introduction

Overview of the Library

This module is designed to manage JWT authentication processes within a NestJS application. It includes services for issuing JWTs, validating user credentials, and verifying tokens. The services handle the generation of access and refresh tokens, ensure users are active and meet authentication criteria, and perform token validity checks, including additional validations if necessary. This comprehensive approach ensures secure user authentication and efficient token management.

Purpose and Key Features

  • Secure Token Management: Provides robust mechanisms for issuing and managing access and refresh tokens, ensuring secure and efficient token lifecycle management.
  • Abstract User Validation Service: Offers an abstract service to validate user credentials and check user activity status, ensuring that only eligible users can authenticate. This abstract nature requires implementations to define specific validation logic, allowing flexibility across different user models and authentication requirements.
  • Token Verification: Includes capabilities to verify the authenticity and validity of tokens, with support for additional custom validations to meet specific security requirements.
  • Customizable and Extensible: Designed to be flexible, allowing customization of token generation, user validation, and token verification processes to suit different application needs.
  • Integration with NestJS Ecosystem: Seamlessly integrates with other NestJS modules and services, leveraging the framework's features for enhanced functionality and performance.

Installation

To get started, install the JwtModule package:

yarn add @concepta/nestjs-jwt

Basic Setup

To set up the JwtModule, follow the basic setup tutorial in the nestjs-authentication README.

Creating custom jwtIssueService

Here we will cover how to override the default services in JwtModule. For example, to override the JwtIssueTokenService, follow the steps below:

  1. Create a custom implementation of JwtIssueTokenService:
import { Injectable } from '@nestjs/common';
import {
  JwtService,
  JwtSignServiceInterface,
  JwtIssueTokenServiceInterface,
} from '@concepta/nest-jwt';

@Injectable()
export class CustomJwtIssueTokenService implements JwtIssueTokenServiceInterface {
  constructor(
    private readonly jwtAccessService: JwtSignServiceInterface,
    private readonly jwtRefreshService: JwtSignServiceInterface,
  ) {}

  async accessToken(...args: Parameters<JwtIssueTokenServiceInterface['accessToken']>) {
    return this.jwtAccessService.signAsync(...args);
  }

  async refreshToken(...args: Parameters<JwtIssueTokenServiceInterface['refreshToken']>) {
    return this.jwtRefreshService.signAsync(...args);
  }
}
  1. Provide the custom implementation in your module configuration:
import { Module } from '@nestjs/common';
import { JwtModule } from '@concepta/nestjs-jwt';
import { CustomJwtIssueTokenService } from './custom-jwt-issue-token.service';

@Module({
  imports: [
    JwtModule.forRoot({
      jwtIssueService: CustomJwtIssueTokenService,
      settings: {
        access: {
          secret: 'your-secret-key',
          signOptions: { expiresIn: '60s' },
        },
      },
    }),
  ],
  providers: [CustomJwtIssueTokenService],
})
export class AppModule {}

This example shows how to customize the JwtIssueTokenService with a custom implementation. Similar steps can be followed to override other services in JwtModule.

Environment Variables

Configurations available via environment.

Variable Type Default
JWT_MODULE_ACCESS_SECRET <string | Buffer> randomUUID() * see note Access token secret
JWT_MODULE_ACCESS_EXPIRES_IN <string | number> '1h' Access token expiration length
JWT_MODULE_REFRESH_SECRET <string | Buffer> copied from access secret Refresh token secret
JWT_MODULE_REFRESH_EXPIRES_IN <string | number> '1y' Refresh token expiration length

* For security reasons, a random UUID will only be generated for the default secret when NODE_ENV !== 'production'.

How to Guides

1. How to Set Up JwtModule with forRoot

To set up the JwtModule, follow these steps:

import { Module } from '@nestjs/common';
import { JwtModule } from '@concepta/nestjs-jwt';

@Module({
  imports: [
    JwtModule.forRoot({}),
  ],
})
export class AppModule {}

This setup configures the JwtModule with global settings and integrates the JwtModule for JWT-based authentication.

2. How to Configure JwtModule Settings

The JwtModule provides several configurable settings to customize its behavior. Each setting can be defined in the module configuration and will create default services to be used in other modules.

Settings Example

Here is an example of how to configure each property of the settings:

import { Module } from '@nestjs/common';
import { JwtModule } from '@concepta/nestjs-jwt';

@Module({
  imports: [
    JwtModule.forRoot({
      settings: {
        access: {
          secret: 'your-secret-key',
          signOptions: { expiresIn: '60s' },
        },
      },
    }),
  ],
})
export class AppModule {}

3. Overriding Defaults

To override the default services, you can provide custom implementations for any of the services.

JwtAccessService

@Injectable()
import { JwtService, JwtSignOptions } from '@concepta/nest-jwt';
class CustomJwtAccessService extends JwtService {
  sign(_payload: string, _options?: JwtSignOptions): string {
    return 'foo';
  }
}

JwtRefreshService

@Injectable()
import { JwtService, JwtSignOptions } from '@concepta/nest-jwt';
class CustomRefreshJwtAccessService extends JwtService {
  sign(_payload: string, _options?: JwtSignOptions): string {
    return 'foo';
  }
}

JwtIssueTokenService

import { Injectable } from '@nestjs/common';
import {
  JwtService,
  JwtSignServiceInterface,
  JwtIssueTokenServiceInterface,
} from '@concepta/nest-jwt';

@Injectable()
export class CustomJwtIssueTokenService implements JwtIssueTokenServiceInterface {
  constructor(
    private readonly jwtAccessService: JwtSignServiceInterface,
    private readonly jwtRefreshService: JwtSignServiceInterface,
  ) {}

  async accessToken(...args: Parameters<JwtIssueTokenServiceInterface['accessToken']>) {
    // Custom implementation
    return this.jwtAccessService.signAsync(...args);
  }

  async refreshToken(...args: Parameters<JwtIssueTokenServiceInterface['refreshToken']>)   {
    // Custom implementation
    return this.jwtRefreshService.signAsync(...args);
  }
}

JwtVerifyTokenService

import { Injectable } from '@nestjs/common';
import {
  JwtService,
  JwtVerifyServiceInterface,
  JwtVerifyTokenServiceInterface,
} from '@concepta/nest-jwt';

@Injectable()
export class CustomJwtVerifyTokenService implements JwtVerifyTokenServiceInterface {
  constructor(private readonly jwtVerifyService: JwtVerifyServiceInterface) {}

  async accessToken(...args: Parameters<JwtVerifyTokenServiceInterface['accessToken']>) {
    // Custom implementation
    return this.jwtVerifyService.verifyAsync('access', ...args);
  }

  async refreshToken(...args: Parameters<JwtVerifyTokenServiceInterface['refreshToken']>) {
    // Custom implementation
    return this.jwtVerifyService.verifyAsync('refresh', ...args);
  }
}

JwtService

import { Inject, Injectable } from '@nestjs/common';
import { JwtServiceInterface } from '@concepta/nest-jwt';

@Injectable()
export class CustomJwtService implements JwtServiceInterface {
  async signAsync(
    ...rest: Parameters<JwtService['signAsync']>
  ) {
    // custom logic
  }

  async verifyAsync(
    ...rest: Parameters<JwtService['verifyAsync']>
  ) {
    // custom logic
  }

  decode(tokenType: JwtTokenType, ...rest: Parameters<JwtService['decode']>) {
    // custom logic
  }
}
  1. Provide the custom implementations in your module configuration:
import { Module } from '@nestjs/common';
import { JwtModule } from '@concepta/nestjs-jwt';
import { CustomJwtIssueTokenService } from './custom-jwt-issue-token.service';
import { CustomJwtVerifyTokenService } from './custom-jwt-verify-token.service';

@Module({
  imports: [
    JwtModule.forRoot({
      jwtIssueService: CustomJwtIssueTokenService,
      jwtVerifyService: CustomJwtVerifyTokenService,
      settings: {
        access: {
          secret: 'your-secret-key',
          signOptions: { expiresIn: '60s' },
        },
      },
    }),
  ],
  providers: [CustomJwtIssueTokenService, CustomJwtVerifyTokenService],
})
export class AppModule {}

This example shows how to customize the JwtIssueTokenService and JwtVerifyTokenService with custom implementations. Similar steps can be followed to override other services in JwtModule.

Explanation

Conceptual Overview

What is This Library?

The nestjs-jwt library is a comprehensive solution for managing authentication processes within a NestJS application. It provides services for issuing JWTs, validating user credentials, and verifying tokens. The library integrates seamlessly with other modules in the nestjs-auth suite, making it a versatile choice for various authentication needs.

Benefits of Using This Library

  • Secure Token Management: Robust mechanisms for issuing and managing access and refresh tokens.
  • Abstract User Validation Service: Flexible user validation service that can be customized to meet specific requirements.
  • Token Verification: Capabilities to verify the authenticity and validity of tokens, with support for additional custom validations.
  • Customizable and Extensible: Designed to be flexible, allowing customization of token generation, user validation, and token verification processes.
  • Integration with NestJS Ecosystem: Seamlessly integrates with other NestJS modules and services, leveraging the framework's features for enhanced functionality and performance.

Design Choices

Global, Synchronous vs Asynchronous Registration

The nestjs-jwt module supports both synchronous and asynchronous registration:

  • Global Registration: Makes the module available throughout the entire application. This approach is useful when JWT authentication is required across all or most routes in the application.
  • Synchronous Registration: This method is used when the configuration options are static and available at application startup. It simplifies the setup process and is suitable for most use cases where configuration values do not depend on external services.
  • Asynchronous Registration: This method is beneficial when configuration options need to be retrieved from external sources, such as a database or an external API, at runtime. It allows for more flexible and dynamic configuration but requires an asynchronous factory function.

Integration Details

Integrating with Other Modules

The nestjs-jwt module integrates smoothly with other modules in the nestjs-auth suite. Here are some integration details:

  • @concepta/nestjs-auth-jwt: Use @concepta/nestjs-auth-jwt for JWT-based authentication. Configure it to handle the issuance and verification of JWT tokens.
  • @concepta/nestjs-auth-local: Use @concepta/nestjs-auth-local for local authentication strategies such as username and password.
  • @concepta/nestjs-auth-recovery: Use @concepta/nestjs-auth-recovery for account recovery processes like password reset.
  • @concepta/nestjs-auth-refresh: Use @concepta/nestjs-auth-refresh for handling token refresh mechanisms.

By combining these modules, you can create a comprehensive authentication system that meets various security requirements and user needs.

Readme

Keywords

none

Package Sidebar

Install

npm i @concepta/nestjs-jwt

Weekly Downloads

62

Version

5.1.0

License

BSD-3-Clause

Unpacked Size

56 kB

Total Files

55

Last publish

Collaborators

  • leoafarias
  • mrmaz