0.0.19 • Published 3 months ago

@petbee/nestjs-petbee-auth v0.0.19

Weekly downloads
-
License
Apache-2.0
Repository
github
Last release
3 months ago

Petbee Authentication Module for NestJS

This authentication module provides a flexible and configurable approach to integrating JWT-based authentication into your NestJS applications. It supports both static and dynamic configuration and allows for the optional integration of a custom user data fetching service.

Features

  • JWT Strategy integration
  • Custom user data fetching
  • Static and dynamic module configuration
  • Extendable to various authentication scenarios

Installation

npm install @petbee/nestjs-petbee-auth
# or
yarn add @petbee/nestjs-petbee-auth

Make sure you have NestJS installed in your project. If not, install them:

npm install @nestjs/common @nestjs/core
# or
yarn add @nestjs/common @nestjs/core

Usage

Static Configuration

Import the AuthModule into your application module and use the register method for static configuration:

// app.module.ts
import { Module } from '@nestjs/common'
import { AuthModule } from '@petbee/nestjs-petbee-auth'

@Module({
  imports: [
    AuthModule.register({
      authConfig: {
        domain: 'AUTH_PROVIDER_ISSUER_URL',
      },
    }),
    // ... other imports
  ],
})
export class AppModule {}

Dynamic/Asynchronous Configuration

For more complex scenarios where configuration might depend on asynchronous operations, use the registerAsync method:

// app.module.ts
import { Module } from '@nestjs/common'
import { AuthModule } from '@petbee/nestjs-petbee-auth'
import { ConfigService } from './config/config.service' // Assuming you have a ConfigService

@Module({
  imports: [
    AuthModule.registerAsync({
      imports: [ConfigModule], // Import the module that provides ConfigService
      useFactory: async (configService: ConfigService) => ({
        authConfig: {
          domain: configService.get<string>('auth.issuerUrl'),
        },
      }),
      userDataFetcher: {
        useClass: MockUserDataFetcher,
      }, // optional
      inject: [ConfigService], // Inject ConfigService
    }),
    // ... other imports
  ],
})
export class AppModule {}

You could also use as a factory:

// app.module.ts
import { Module } from '@nestjs/common'
import { AuthModule } from '@petbee/nestjs-petbee-auth'
import { ConfigService } from './config/config.service' // Assuming you have a ConfigService
import { UserService } from './user/user.service' // Assuming you have a UserService
import { UserModule } from './user/user.module' // Assuming you have a UserModule and it's not global

@Module({
  controllers: [AppController],
  imports: [
    AuthModule.registerAsync({
      imports: [UserModule],
      useFactory: () => ({
        authConfig: {
          domain: 'example.auth.com',
        },
      }),
      userDataFetcher: {
        useFactory: (userService: UserService) => new MockInjectUserDataFetcher(userService),
        inject: [UserService],
      },
    }),
  ],
  providers: [AppService],
})
export class AppModuleAsyncWithDataFetcherInject {}

Custom UserDataFetcher

To add additional user data to the JWT payload, implement a custom UserDataFetcher:

// custom-user-data-fetcher.service.ts
import { Injectable } from '@nestjs/common'
import { UserDataFetcher, UserDataFetcherInput } from '@petbee/nestjs-petbee-auth'

@Injectable()
export class CustomUserDataFetcher implements UserDataFetcher {
  async fetchAdditionalData(input: UserDataFetcherInput): Promise<User> {
    // Implement your logic to fetch additional user data
    return additionalUserData as User
  }
}

Configuration Options

Configure the AuthModule with the following options defined in the IAuthModuleOptions interface:

  • defaultStrategy (string | string[]): Specifies the default strategy or strategies to be used. Default is 'jwt'.
  • session (boolean): Determines whether to use sessions. Defaults to false.
  • authConfig (IAuthConfig): Configuration specific to authentication. It includes:
    • domain (string): The domain against which authentication will be performed.
    • algorithms (string | string[]): The algorithms to be used for authentication. Default is 'RS256'.

The IAuthConfig interface is used to specify detailed authentication-related configurations, and IAuthModuleOptions interface allows for broader module configuration, including the option to add any additional key-value pairs as needed.

Dynamic/Asynchronous Configuration

You can configure the AuthModule asynchronously using the AuthModuleAsyncOptions interface, which extends from ModuleMetadata and allows for the following:

  • useExisting (Type<AuthOptionsFactory>): Reuse an existing factory for creating auth options.
  • useClass (Type<AuthOptionsFactory>): Specify a class that will provide the auth options.
  • useFactory (Function): A factory function that returns the auth options (either synchronously or asynchronously).
  • inject (any[]): Dependencies that the factory function requires.
  • userDataFetcher (UserDataFetcher): Optional service to fetch additional user data.
  • enhanceUserCtx (Boolean): Optional option to enhace the user context with data from default external API. Only works if no userDataFetcher service was provided.

Guards

AuthenticationGuard

AuthenticationGuard is an extension of NestJS's built-in AuthGuard that uses the 'jwt' strategy. It incorporates additional logic to handle public routes in an application that uses JWT authentication globally.

Usage

To use AuthenticationGuard globally in your NestJS application:

import { Reflector } from '@nestjs/core'
import { AuthenticationGuard } from '@petbee/nestjs-petbee-auth'

// In your main.ts or a similar entry file
const reflector = new Reflector()
app.useGlobalGuards(new AuthenticationGuard(reflector))

This will apply JWT authentication to all routes in your application, except those explicitly marked as public.

Decorators

@Authentication Decorator

The @Authentication decorator applies the AuthenticationGuard to a specific controller or route. It's used to enforce JWT authentication on private routes when the guard is not set globally.

Usage

To make a particular route or entire controller require authentication:

import { Authentication } from '@petbee/nestjs-petbee-auth'

@Controller()
@Authentication() // Apply to all routes in the controller
export class SomeController {
  @Get()
  findSomething() {
    // This route requires authentication
  }

  @Post()
  @Authentication() // Apply to a specific route
  createSomething() {
    // This route also requires authentication
  }
}

@Public Decorator

The @IsPublic decorator is used to mark specific routes or entire controllers as public, bypassing the JWT authentication even if it's set globally.

Usage

To make a particular route or entire controller public:

import { Public } from '@petbee/nestjs-petbee-auth'

@Controller()
@Public() // Apply to all routes in the controller
export class PublicController {
  @Get()
  findSomething() {
    // This route is public
  }

  @Post()
  @Public() // Apply to a specific route
  createSomething() {
    // This route is also public
  }
}

@Roles

The @Roles decorator is used to mark specific routes or entire controllers as allowed only to users with specific roles passed as argument. The argument can be an string or array of strings.

Usage

To make a particular route or entire controller restricted to specic role:

  • Remember to set the @Authentication decorator if you don't have configured the global authentication guard.
  • It's important to say that Class and Method decorators roles will be merged, so if the Class allow access to clinics and then the method decorator allows access to some-other-role to that specific method both clinics and some-other-role will be allowed.
import { Public } from '@petbee/nestjs-petbee-auth'

@Controller()
@Roles(['clinics']) // Apply to all routes in the controller
@Authentication() // Only if you not set authentication guard globally
export class PublicController {
  @Get()
  findSomething() {
    // This route is public
  }

  @Post()
  @Roles(['some-other-role', 'some-another-role']) // Apply to a specific route
  @Authentication() // Only if you not set authentication guard globally
  createSomething() {
    // This route is also public
  }
}

@OnlyAdmin Decorator

The @OnlyAdmin decorator is used to mark specific routes or entire controllers as allowed only to users with admin role. We check for isAdmin prop on user ctx or if the roles prop has admin string.

Usage

To make a particular route or entire controller admin only:

  • Remember to set the @Authentication decorator if you don't have configured the global authentication guard.
  • The @OnlyAdmin adds a Roles['admin] behind the scenes, so the merge with Class and Method will happen as explained in @Roles decorator.
import { Public } from '@petbee/nestjs-petbee-auth'

@Controller()
@OnlyAdmin() // Apply to all routes in the controller
@Authentication() // Only if you not set authentication guard globally
export class PublicController {
  @Get()
  findSomething() {
    // This route is public
  }

  @Post()
  @OnlyAdmin() // Apply to a specific route
  @Authentication() // Only if you not set authentication guard globally
  createSomething() {
    // This route is also public
  }
}

@Clinics Decorator

The @Clinics decorator is used to mark specific routes or entire controllers as allowed only to users with clinics or admin role. We check if the roles has clinics on user ctx.

Usage

To make a particular route or entire controller admin only:

  • Remember to set the @Authentication decorator if you don't have configured the global authentication guard.
  • The @Clinics adds a Roles['clinics', 'clinic'] behind the scenes, so the merge with Class and Method will happen as explained in @Roles decorator.
import { Public } from '@petbee/nestjs-petbee-auth'

@Controller()
@Clinics() // Apply to all routes in the controller
@Authentication() // Only if you not set authentication guard globally
export class PublicController {
  @Get()
  findSomething() {
    // This route is public
  }

  @Post()
  @Clinics() // Apply to a specific route
  @Authentication() // Only if you not set authentication guard globally
  createSomething() {
    // This route is also public
  }
}
0.0.18

3 months ago

0.0.19

3 months ago

0.0.17

3 months ago

0.0.15

3 months ago

0.0.12

4 months ago

0.0.14

4 months ago

0.0.10

4 months ago

0.0.11

4 months ago

0.0.9

4 months ago

0.0.8

4 months ago

0.0.7

4 months ago

0.0.6

4 months ago

0.0.5

4 months ago

0.0.4

4 months ago

0.0.3

4 months ago

0.0.2

4 months ago

0.0.1

4 months ago