From bbfcab4741e28c4679316290a4f0351280f931e6 Mon Sep 17 00:00:00 2001 From: Thiago Ramalho Date: Tue, 11 Jun 2024 15:30:33 -0300 Subject: [PATCH 1/4] chore: update readme documentation for nestjs-auth-local --- packages/nestjs-auth-local/README.md | 567 ++++++++++++++++++++++++++- 1 file changed, 565 insertions(+), 2 deletions(-) diff --git a/packages/nestjs-auth-local/README.md b/packages/nestjs-auth-local/README.md index ba6f042bd..66eb48a8e 100644 --- a/packages/nestjs-auth-local/README.md +++ b/packages/nestjs-auth-local/README.md @@ -10,6 +10,569 @@ Authenticate requests using username/email and password against a local or remot [![GH Contrib](https://img.shields.io/github/contributors/conceptadev/rockets?logo=github)](https://github.com/conceptadev/rockets/graphs/contributors) [![NestJS Dep](https://img.shields.io/github/package-json/dependency-version/conceptadev/rockets/@nestjs/common?label=NestJS&logo=nestjs&filename=packages%2Fnestjs-core%2Fpackage.json)](https://www.npmjs.com/package/@nestjs/common) -## Installation +## Table of Contents + +- [Project](#project) +- [Tutorials](#tutorials) + - [1. Getting Started with AuthLocalModule](#1-getting-started-with-authlocalmodule) + - [1.1 Introduction](#11-introduction) + - [Overview of the Library](#overview-of-the-library) + - [Purpose and Key Features](#purpose-and-key-features) + - [1.2 Installation](#12-installation) + - [Install the AuthLocalModule package](#install-the-authlocalmodule-package) + - [Add the AuthLocalModule to Your NestJS Application](#add-the-authlocalmodule-to-your-nestjs-application) + - [1.3 Basic Setup in a NestJS Project](#13-basic-setup-in-a-nestjs-project) + - [Scenario: Users can log in using local authentication](#scenario-users-can-log-in-using-local-authentication) + - [Step 1: Create Entities](#step-1-create-entities) + - [Step 2: Create Services](#step-2-create-services) + - [Step 3: Create Controller](#step-3-create-controller) + - [Step 4: Configure the Module](#step-4-configure-the-module) + - [Validating the Setup](#validating-the-setup) +- [How-To Guides](#how-to-guides) + - [1. Registering AuthLocalModule Synchronously](#1-registering-authlocalmodule-synchronously) + - [2. Registering AuthLocalModule Asynchronously](#2-registering-authlocalmodule-asynchronously) + - [3. Global Registering AuthLocalModule Asynchronously](#3-global-registering-authlocalmodule-asynchronously) + - [4. Using Custom User Lookup Service](#4-using-custom-user-lookup-service) + - [5. Implementing and Using Custom Token Issuance Service](#5-implementing-and-using-custom-token-issuance-service) + - [6. Implementing and Using Custom User Validation Service](#6-implementing-and-using-custom-user-validation-service) + - [7. Implementing and Using Custom Password Validation Service](#7-implementing-and-using-custom-password-validation-service) + - [8. Overwriting the Settings](#8-overwriting-the-settings) + - [9. Integration with Other NestJS Modules](#9-integration-with-other-nestjs-modules) +- [Reference](#reference) + - [1. AuthLocalOptionsInterface](#1-authlocaloptionsinterface) + - [2. AuthLocalModule API Reference](#2-authlocalmodule-api-reference) +- [Explanation](#explanation) + - [Conceptual Overview of Local Authentication](#conceptual-overview-of-local-authentication) + - [What is Local Authentication?](#what-is-local-authentication) + - [Benefits of Using Local Authentication](#benefits-of-using-local-authentication) + - [Design Choices in AuthLocalModule](#design-choices-in-authlocalmodule) + - [Why Use Local Authentication?](#why-use-local-authentication) + - [Synchronous vs Asynchronous Registration](#synchronous-vs-asynchronous-registration) + - [Global vs Feature-Specific Registration](#global-vs-feature-specific-registration) + - [Integrating AuthLocalModule with Other Modules](#integrating-authlocalmodule-with-other-modules) + +## Tutorials + +### 1. Getting Started with AuthLocalModule + +#### 1.1 Introduction + +##### Overview of the Library + +The `AuthLocalModule` is a robust NestJS module designed for implementing local authentication using username and password. This module leverages the `passport-local` strategy to authenticate users locally within your application. + +##### Purpose and Key Features + +- **Local Authentication**: Provides a straightforward way to implement local authentication using username and password. +- **Synchronous and Asynchronous Registration**: Flexibly register the module either synchronously or asynchronously, depending on your application's needs. +- **Global and Feature-Specific Registration**: Use the module globally across your application or tailor it for specific features. +- **Customizable**: Easily customize various aspects such as user validation, token issuance, and password validation. + +#### 1.2 Installation + +##### Install the AuthLocalModule package: +```sh +npm install class-transformer +npm install class-validator +npm install @concepta/ts-core +npm install @concepta/nestjs-authentication +npm install @concepta/nestjs-password +npm install @concepta/nestjs-jwt +npm install @concepta/nestjs-auth-local + +or + +yarn add class-transformer +yarn add class-validator +yarn add @concepta/ts-core +yarn add @concepta/nestjs-authentication +yarn add @concepta/nestjs-password +yarn add @concepta/nestjs-jwt +yarn add @concepta/nestjs-auth-local + +``` + +##### Add the AuthLocalModule to Your NestJS Application: + +Import the `AuthLocalModule` and required services in your application module. Ensure to provide the necessary configuration options at `AuthLocalOptionsInterface`. + +The `AuthLocalOptionsInterface` defines the configuration options for the local authentication strategy within a NestJS application using the `nestjs-auth-local` package. This interface allows for the customization of `userLookupService`, `issueTokenService`, `validateUserService`, and `passwordValidationService`. Please see [Reference](#reference) for more details. + +optional fields utilize default implementations, enabling straightforward integration and flexibility to override with custom implementations as needed. This setup ensures that developers can tailor the authentication process to specific requirements while maintaining a robust and secure authentication framework. + +#### 1.3 Basic Setup in a NestJS Project + +##### Scenario: Users can log in using local authentication + +To test this scenario, we will set up an application where users can log in using a username and password. We will create the necessary entities, services, module configurations. + +## Step 1: Create Entities + +First, create the `User` entity. + +**Code:** +```ts +export class User { + id: number; + username: string; + password: string; +} +``` +## Step 2: Create Services + +Next, you need to create the `UserLookupService`. This +service is responsible for the business logic related to +retrieving user data. It should implement the +`AuthLocalUserLookupServiceInterface`. + +Within this service, implement the `byUsername` method to +fetch user details by their email. Ensure that the method +returns a `User` object containing `passwordHash` and +`passwordSalt`. + +These attributes are crucial as they are used by the +`validateUser` method in the `passwordValidationService` +to authenticate the user, which is a configurable option +in the `AuthLocalModule`. + +**Code:** +```ts +import { Injectable } from '@nestjs/common'; +import { ReferenceUsername } from '@concepta/ts-core'; +import { AuthLocalUserLookupServiceInterface } from '@concepta/nestjs-auth-local'; +import { AuthLocalCredentialsInterface } from '@concepta/nestjs-auth-local/dist/interfaces/auth-local-credentials.interface'; + +@Injectable() +export class UserLookupService implements AuthLocalUserLookupServiceInterface { + async byUsername( + username: ReferenceUsername, + ): Promise { + // make sure this method will return a valid user with + // correct passwordHash and passwordSalt + // let's user this mock data for the purposes of this tutorial + return { + id: '5b3f5fd3-9426-4c4d-a06d-b4d55079034d', + username: username, + passwordHash: + '$2b$12$9rQ4qZx8gpTaTR4ic3LQ.OkebyVBa48DP42jErL1zfqF17WeG4hHC', + passwordSalt: '$2b$12$9rQ4qZx8gpTaTR4ic3LQ.O', + active: true, + }; + } +} +``` +## Step 3: Configure the Module + +Configure the module to include the necessary services `userLookupService`. + +**Code:** +```ts +import { Module } from '@nestjs/common'; +import { AuthLocalModule } from '@concepta/nestjs-auth-local'; +import { UserLookupService } from './user-lookup.service'; +import { JwtModule } from '@concepta/nestjs-jwt'; + +@Module({ + imports: [ + JwtModule.forRoot({}), + AuthLocalModule.forRoot({ + userLookupService: new UserLookupService(), + }), + ], + controllers: [], + providers: [], +}) +export class AppModule {} +``` +## Validating the Setup + +To validate the setup, you can use `curl` commands to simulate frontend requests. Here are the steps to test the login endpoint: + +## Step 1: Obtain a JWT Token + +Assuming you have an endpoint to obtain a JWT token, use `curl` to get the token. Replace `auth-url` with your actual authentication URL, and `username` and `password` with valid credentials. +```sh +curl -X POST http://localhost:3000/auth/login \ + -H "Content-Type: application/json" \ + -d '{"username": "testuser", "password": "testpassword"}' +``` +This should return a response with a login message. + +## Example + +Here is an example sequence of `curl` commands to validate the login setup: + +1. **Login Request:** +```sh +curl -X POST http://localhost:3000/auth/login \ + -H "Content-Type: application/json" \ + -d '{"username": "username", "password": "Test1234"}' +``` +Example response: +```json +{ + "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0NjZkMTAyNS1iZGNkLTRiNWItYTYxMi0yYThiZTU2MDhlNjIiLCJpYXQiOjE3MTgwNDg1NDQsImV4cCI6MTcxODA1MjE0NH0.Zl2i59w89cgJxfI4lXn6VmOhC5GLEqMm2nWkiVKpEUs", + "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0NjZkMTAyNS1iZGNkLTRiNWItYTYxMi0yYThiZTU2MDhlNjIiLCJpYXQiOjE3MTgwNDg1NDQsImV4cCI6NDg0MjI1MDk0NH0.xEF7kObwkztrMF7J83S-xvDarABmjXYkqLFINPWbx6g" +} +``` + +2. **Invalid Credentials Request:** +```sh +curl -X POST http://localhost:3000/auth/login \ + -H "Content-Type: application/json" \ + -d '{"username": "testuser", "password": "wrongpassword"}' +``` +Example response: +```json +{ + "statusCode": 401, + "message": "Unauthorized" +} +``` +## How-To Guides + +### 1. Registering AuthLocalModule Synchronously + +**Code:** +```ts +//... + AuthLocalModule.register({ + userLookupService: new MyUserLookupService(), // required + }), +//... +``` +### 2. Registering AuthLocalModule Asynchronously + +**Code:** +```ts +//... +AuthLocalModule.forRootAsync({ + useFactory: async (userLookupService: MyUserLookupService) => ({ + userLookupService, // required + }), + inject: [MyUserLookupService], +}), +//... +``` +### 3. Global Registering AuthLocalModule Asynchronously + +**Code:** +```ts +//... +AuthLocalModule.forRootAsync({ + useFactory: async (userLookupService: MyUserLookupService) => ({ + userLookupService, + }), + inject: [MyUserLookupService], +}), +//... +``` +### 4. Using Custom User Lookup Service + +**Code:** +```ts +import { AuthLocalUserLookupServiceInterface } from '@concepta/nestjs-auth-local'; +import { AuthLocalCredentialsInterface } from '@concepta/nestjs-auth-local/dist/interfaces/auth-local-credentials.interface'; +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class MyUserLookupService + implements AuthLocalUserLookupServiceInterface { + async byUsername(username: string): Promise { + // implement custom logic to return the user's credentials + return null; + } +} +``` +### 5. Implementing custom token issuance service + +There are two ways to implementing the custom token issuer service. You can take advantage of the default service + +```ts +import { +JwtIssueService, +JwtIssueServiceInterface, +JwtSignService, +} from '@concepta/nestjs-jwt'; +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class MyJwtIssueService extends JwtIssueService { + constructor(protected readonly jwtSignService: JwtSignService) { + super(jwtSignService); + } + + async accessToken( + ...args: Parameters + ) { + // your custom code + return this.accessToken(...args); + } + + async refreshToken( + ...args: Parameters + ) { + // your custom code + return this.refreshToken(...args); + } +} +``` + +Or you can completely overwrite the default implementation. + +**Code:** +```ts +import { JwtIssueServiceInterface } from '@concepta/nestjs-jwt'; +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class MyJwtIssueService implements JwtIssueServiceInterface { + constructor() {} + + async accessToken( + ...args: Parameters + ) { + // your custom code + } + + async refreshToken( + ...args: Parameters + ) { + // your custom code + } +} +``` +### 6. Implementing a custom user validation service + +**Code:** + +The same approach can be done for `AuthLocalValidateUserService` you can either completely overwrite the default implementation or you can take advantage of the default implementation. + +```ts +@Injectable() +export class MyAuthLocalValidateUserService + implements AuthLocalValidateUserServiceInterface +{ + + async validateUser( + dto: AuthLocalValidateUserInterface, + ): Promise { + return this.validateUser(dto); + } + + async isActive( + user: ReferenceIdInterface & ReferenceActiveInterface, + ): Promise { + return true; + } +} + +``` + +```ts +import { AuthLocalValidateUserInterface, AuthLocalValidateUserServiceInterface } from "@concepta/nestjs-auth-local"; +import { ReferenceActiveInterface, ReferenceIdInterface } from "@concepta/ts-core"; +import { Injectable } from "@nestjs/common"; + +@Injectable() +export class MyAuthLocalValidateUserService + implements AuthLocalValidateUserServiceInterface +{ + + async validateUser( + dto: AuthLocalValidateUserInterface, + ): Promise { + return this.validateUser(dto); + } + + async isActive( + user: ReferenceIdInterface & ReferenceActiveInterface, + ): Promise { + return this.isActive(user); + } +} + +``` + +### 7. Implementing a Custom Password Validation Service + +The `PasswordValidationService` in the `nestjs-auth-local` module provides a +default implementation using bcrypt for hashing and verifying passwords. +However, depending on your application's requirements, you might need to use a +different method for password hashing or add additional validation logic. + +You can either extend the existing `PasswordValidationService` to leverage its +built-in functionalities while adding your enhancements, or completely +overwrite it with your custom implementation. + + +**Overwriting the Default Implementation:** + +If your application requires a different hashing algorithm , you can replace the default implementation with one that suits your needs. + +```ts +import { + PasswordStorageInterface, + PasswordValidationServiceInterface, +} from '@concepta/nestjs-password'; +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class MyPasswordValidationService + implements PasswordValidationServiceInterface +{ + async validate(options: { + password: string; + passwordHash: string; + passwordSalt: string; + }): Promise { + return true; + } + + async validateObject( + password: string, + object: T, + ): Promise { + return true; + } +} +``` +**Extending the Default Service:** + +If you want to add additional validation logic while keeping the current hashing and validation, you can extend the default service: + +```ts +import { + PasswordStorageInterface, + PasswordValidationService, +} from '@concepta/nestjs-password'; +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class MyPasswordValidationService extends PasswordValidationService { + constructor() { + super(); + } + + async validate(options: { + password: string; + passwordHash: string; + passwordSalt: string; + }): Promise { + return this.validate(options); + } + + async validateObject( + password: string, + object: T, + ): Promise { + return this.validateObject(password, object); + } +} +``` + +### 8. Overwriting the Settings + +**Code:** +```ts +import { Type } from '@nestjs/common'; + +export class CustomLoginDto { + email: string; + password: string; +} + +export const localSettings = { + loginDto: CustomLoginDto, + usernameField: 'email', + passwordField: 'password' +}; + +``` + +```ts +AuthLocalModule.forRoot({ + userLookupService: new UserLookupService(), + settings: localSettings +}), +``` +### 9. Integration with Other NestJS Modules + +Integrate `nestjs-auth-local` with other NestJS modules like, `nestjs-authentication`, `nestjs-auth-jwt`, `nestjs-auth-refresh` for a comprehensive authentication system. + +## Reference + +### Explanation of Properties in `AuthLocalOptionsInterface` + +#### 1. **userLookupService** (required) +- **Purpose**: Essential for retrieving user details based on the username to initiate the authentication process. +- **Method**: + - `byUsername(username: string): Promise`: Queries user data storage to find a user by their username. Returns a user object if found, or `null` if no user exists with that username. + +#### 2. **issueTokenService** (optional) +- **Purpose**: Handles the generation of access and refresh tokens after user authentication. +- **Class**: `IssueTokenService` + - `accessToken(...)`: Generates an access token using the `JwtIssueService`. + - `refreshToken(...)`: Generates a refresh token using the `JwtIssueService`. + +#### 3. **validateUserService** (optional) +- **Purpose**: Validates if a user can be authenticated with the provided credentials. +- **Class**: `AuthLocalValidateUserService` + - `validateUser(dto: AuthLocalValidateUserInterface)`: Uses `userLookupService` to fetch the user, checks user activity, and validates the password using `passwordValidationService`. + +#### 4. **passwordValidationService** (optional) +- **Purpose**: Validates the user's password against the stored hash to ensure the login attempt is legitimate. +- **Class**: `PasswordValidationService` + - `validate(options: { password: string; passwordHash: string; passwordSalt: string; })`: Compares the provided password with the stored hash and salt using cryptographic functions. + - `validateObject(password: string, object: T)`: Validates the password on an object that includes password hash and salt. + +#### 5. **settings** (optional) +- **Purpose**: Allows customization of the authentication process, specifying how the login data should be structured and which fields are used for username and password. +- **Details**: + - `loginDto`: Customizable data transfer object for login requests. + - `usernameField` and `passwordField`: Specify the field names in the `loginDto` that represent the username and password. + +### 2. AuthLocalModule API Reference + +- **register(options: AuthLocalOptions):** + - Registers the module with synchronous options. + +- **registerAsync(options: AuthLocalAsyncOptions):** + - Registers the module with asynchronous options. + +- **forRoot(options: AuthLocalOptions):** + - Registers the module globally with synchronous options. + +- **forRootAsync(options: AuthLocalAsyncOptions):** + - Registers the module globally with asynchronous options. + +## Explanation + +### Conceptual Overview of Local Authentication + +#### What is Local Authentication? + +Local Authentication is a method of verifying user identity based on credentials (username and password) stored locally within the application or in a connected database. + +#### Benefits of Using Local Authentication + +- **Simplicity**: Easy to implement and manage. +- **Control**: Full control over user authentication and data. +- **Security**: When properly implemented, provides a secure way to authenticate users. + +### Design Choices in AuthLocalModule + +#### Why Use Local Authentication? + +Local Authentication is ideal for applications that need to manage user authentication directly within the application without relying on external identity providers. + +#### Synchronous vs Asynchronous Registration + +- **Synchronous Registration**: Used when configuration options are static and available at startup. +- **Asynchronous Registration**: Used when configuration options need to be retrieved from external sources at runtime. + +#### Global vs Feature-Specific Registration + +- **Global Registration**: Makes the module available throughout the entire application. +- **Feature-Specific Registration**: Allows the module to be registered only for specific features or modules within the application. -`yarn add @concepta/nestjs-auth-local` From 7ec78058aaea15dffdeb41ca528d10a2a0cff338 Mon Sep 17 00:00:00 2001 From: Thiago Ramalho Date: Tue, 11 Jun 2024 16:50:48 -0300 Subject: [PATCH 2/4] chore:adjust on readme --- packages/nestjs-auth-local/README.md | 124 +++++++++++++++++++-------- 1 file changed, 90 insertions(+), 34 deletions(-) diff --git a/packages/nestjs-auth-local/README.md b/packages/nestjs-auth-local/README.md index 66eb48a8e..2c9743b9a 100644 --- a/packages/nestjs-auth-local/README.md +++ b/packages/nestjs-auth-local/README.md @@ -1,6 +1,7 @@ # Rockets NestJS Local Authentication -Authenticate requests using username/email and password against a local or remote data source. +Authenticate requests using username/email and password against a local or +remote data source. ## Project @@ -59,14 +60,21 @@ Authenticate requests using username/email and password against a local or remot ##### Overview of the Library -The `AuthLocalModule` is a robust NestJS module designed for implementing local authentication using username and password. This module leverages the `passport-local` strategy to authenticate users locally within your application. +The `AuthLocalModule` is a robust NestJS module designed for implementing +local authentication using username and password. This module leverages the +`passport-local` strategy to authenticate users locally within your +application. ##### Purpose and Key Features -- **Local Authentication**: Provides a straightforward way to implement local authentication using username and password. -- **Synchronous and Asynchronous Registration**: Flexibly register the module either synchronously or asynchronously, depending on your application's needs. -- **Global and Feature-Specific Registration**: Use the module globally across your application or tailor it for specific features. -- **Customizable**: Easily customize various aspects such as user validation, token issuance, and password validation. +- **Local Authentication**: Provides a straightforward way to implement local +authentication using username and password. +- **Synchronous and Asynchronous Registration**: Flexibly register the module +either synchronously or asynchronously, depending on your application's needs. +- **Global and Feature-Specific Registration**: Use the module globally across +your application or tailor it for specific features. +- **Customizable**: Easily customize various aspects such as user validation, +token issuance, and password validation. #### 1.2 Installation @@ -94,17 +102,29 @@ yarn add @concepta/nestjs-auth-local ##### Add the AuthLocalModule to Your NestJS Application: -Import the `AuthLocalModule` and required services in your application module. Ensure to provide the necessary configuration options at `AuthLocalOptionsInterface`. +Import the `AuthLocalModule` and required services in your application module. +Ensure to provide the necessary configuration options at +`AuthLocalOptionsInterface`. -The `AuthLocalOptionsInterface` defines the configuration options for the local authentication strategy within a NestJS application using the `nestjs-auth-local` package. This interface allows for the customization of `userLookupService`, `issueTokenService`, `validateUserService`, and `passwordValidationService`. Please see [Reference](#reference) for more details. +The `AuthLocalOptionsInterface` defines the configuration options for the +local authentication strategy within a NestJS application using the +`nestjs-auth-local` package. This interface allows for the customization +of `userLookupService`, `issueTokenService`, `validateUserService`, and +`passwordValidationService`. Please see [Reference](#reference) for more +details. -optional fields utilize default implementations, enabling straightforward integration and flexibility to override with custom implementations as needed. This setup ensures that developers can tailor the authentication process to specific requirements while maintaining a robust and secure authentication framework. +optional fields utilize default implementations, enabling straightforward +integration and flexibility to override with custom implementations as needed. +This setup ensures that developers can tailor the authentication process to +specific requirements while maintaining a robust and secure authentication +framework. #### 1.3 Basic Setup in a NestJS Project ##### Scenario: Users can log in using local authentication -To test this scenario, we will set up an application where users can log in using a username and password. We will create the necessary entities, services, module configurations. +To test this scenario, we will set up an application where users can log +in using a username and password. We will create the necessary entities, services, module configurations. ## Step 1: Create Entities @@ -186,11 +206,15 @@ export class AppModule {} ``` ## Validating the Setup -To validate the setup, you can use `curl` commands to simulate frontend requests. Here are the steps to test the login endpoint: +To validate the setup, you can use `curl` commands to simulate frontend +requests. Here are the +steps to test the login endpoint: ## Step 1: Obtain a JWT Token -Assuming you have an endpoint to obtain a JWT token, use `curl` to get the token. Replace `auth-url` with your actual authentication URL, and `username` and `password` with valid credentials. +Assuming you have an endpoint to obtain a JWT token, use `curl` to get +the token. Replace `auth-url` with your actual authentication URL, and +`username` and `password` with valid credentials. ```sh curl -X POST http://localhost:3000/auth/login \ -H "Content-Type: application/json" \ @@ -286,7 +310,8 @@ export class MyUserLookupService ``` ### 5. Implementing custom token issuance service -There are two ways to implementing the custom token issuer service. You can take advantage of the default service +There are two ways to implementing the custom token issuer service. You can +take advantage of the default service ```ts import { @@ -346,7 +371,9 @@ export class MyJwtIssueService implements JwtIssueServiceInterface { **Code:** -The same approach can be done for `AuthLocalValidateUserService` you can either completely overwrite the default implementation or you can take advantage of the default implementation. +The same approach can be done for `AuthLocalValidateUserService` you can +either completely overwrite the default implementation or you can take +advantage of the default implementation. ```ts @Injectable() @@ -408,7 +435,8 @@ overwrite it with your custom implementation. **Overwriting the Default Implementation:** -If your application requires a different hashing algorithm , you can replace the default implementation with one that suits your needs. +If your application requires a different hashing algorithm , you can replace +the default implementation with one that suits your needs. ```ts import { @@ -439,7 +467,8 @@ export class MyPasswordValidationService ``` **Extending the Default Service:** -If you want to add additional validation logic while keeping the current hashing and validation, you can extend the default service: +If you want to add additional validation logic while keeping the current +hashing and validation, you can extend the default service: ```ts import { @@ -498,39 +527,57 @@ AuthLocalModule.forRoot({ ``` ### 9. Integration with Other NestJS Modules -Integrate `nestjs-auth-local` with other NestJS modules like, `nestjs-authentication`, `nestjs-auth-jwt`, `nestjs-auth-refresh` for a comprehensive authentication system. +Integrate `nestjs-auth-local` with other NestJS modules like, +`nestjs-authentication`, `nestjs-auth-jwt`, `nestjs-auth-refresh` for + a comprehensive authentication system. ## Reference ### Explanation of Properties in `AuthLocalOptionsInterface` #### 1. **userLookupService** (required) -- **Purpose**: Essential for retrieving user details based on the username to initiate the authentication process. +- **Purpose**: Essential for retrieving user details based on the username to +initiate the authentication process. - **Method**: - - `byUsername(username: string): Promise`: Queries user data storage to find a user by their username. Returns a user object if found, or `null` if no user exists with that username. + - `byUsername(username: string): Promise`: + Queries user data storage to find a user by their username. Returns a user + object if found, or `null` if no user exists with that username. #### 2. **issueTokenService** (optional) -- **Purpose**: Handles the generation of access and refresh tokens after user authentication. +- **Purpose**: Handles the generation of access and refresh tokens after user +authentication. - **Class**: `IssueTokenService` - `accessToken(...)`: Generates an access token using the `JwtIssueService`. - `refreshToken(...)`: Generates a refresh token using the `JwtIssueService`. #### 3. **validateUserService** (optional) -- **Purpose**: Validates if a user can be authenticated with the provided credentials. +- **Purpose**: Validates if a user can be authenticated with the provided +credentials. - **Class**: `AuthLocalValidateUserService` - - `validateUser(dto: AuthLocalValidateUserInterface)`: Uses `userLookupService` to fetch the user, checks user activity, and validates the password using `passwordValidationService`. + - `validateUser(dto: AuthLocalValidateUserInterface)`: Uses + `userLookupService` to fetch the user, checks user activity, and + validates the password using `passwordValidationService`. #### 4. **passwordValidationService** (optional) -- **Purpose**: Validates the user's password against the stored hash to ensure the login attempt is legitimate. +- **Purpose**: Validates the user's password against the stored hash +to ensure the login attempt is legitimate. - **Class**: `PasswordValidationService` - - `validate(options: { password: string; passwordHash: string; passwordSalt: string; })`: Compares the provided password with the stored hash and salt using cryptographic functions. - - `validateObject(password: string, object: T)`: Validates the password on an object that includes password hash and salt. + - `validate(options: { password: string; passwordHash: string; passwordSalt: string; })`: + Compares the provided password with the stored hash and salt using + cryptographic functions. + + - `validateObject(password: string, object: T)`: + Validates the password on an object that includes password hash + and salt. #### 5. **settings** (optional) -- **Purpose**: Allows customization of the authentication process, specifying how the login data should be structured and which fields are used for username and password. +- **Purpose**: Allows customization of the authentication process, + specifying how the login data should be structured and which fields + are used for username and password. - **Details**: - `loginDto`: Customizable data transfer object for login requests. - - `usernameField` and `passwordField`: Specify the field names in the `loginDto` that represent the username and password. + - `usernameField` and `passwordField`: Specify the field names in the + `loginDto` that represent the username and password. ### 2. AuthLocalModule API Reference @@ -552,27 +599,36 @@ Integrate `nestjs-auth-local` with other NestJS modules like, `nestjs-authentica #### What is Local Authentication? -Local Authentication is a method of verifying user identity based on credentials (username and password) stored locally within the application or in a connected database. +Local Authentication is a method of verifying user identity based on credentials +(username and password) stored locally within the application or in a connected +database. #### Benefits of Using Local Authentication - **Simplicity**: Easy to implement and manage. - **Control**: Full control over user authentication and data. -- **Security**: When properly implemented, provides a secure way to authenticate users. +- **Security**: When properly implemented, provides a secure way to authenticate + users. ### Design Choices in AuthLocalModule #### Why Use Local Authentication? -Local Authentication is ideal for applications that need to manage user authentication directly within the application without relying on external identity providers. +Local Authentication is ideal for applications that need to manage user +authentication directly within the application without relying on external +identity providers. #### Synchronous vs Asynchronous Registration -- **Synchronous Registration**: Used when configuration options are static and available at startup. -- **Asynchronous Registration**: Used when configuration options need to be retrieved from external sources at runtime. +- **Synchronous Registration**: Used when configuration options are static and +available at startup. +- **Asynchronous Registration**: Used when configuration options need to be +retrieved from external sources at runtime. #### Global vs Feature-Specific Registration -- **Global Registration**: Makes the module available throughout the entire application. -- **Feature-Specific Registration**: Allows the module to be registered only for specific features or modules within the application. +- **Global Registration**: Makes the module available throughout the entire +application. +- **Feature-Specific Registration**: Allows the module to be registered only +for specific features or modules within the application. From 0b435d1d21225c9b8b94a47d6e8d636d6d6d178f Mon Sep 17 00:00:00 2001 From: Marshall Sorenson Date: Wed, 12 Jun 2024 10:35:11 -0400 Subject: [PATCH 3/4] feat: local-auth doc improvements --- packages/nestjs-auth-local/README.md | 239 +++++++++++++++--------- packages/nestjs-auth-local/src/index.ts | 13 +- 2 files changed, 156 insertions(+), 96 deletions(-) diff --git a/packages/nestjs-auth-local/README.md b/packages/nestjs-auth-local/README.md index 2c9743b9a..1e50d2b5d 100644 --- a/packages/nestjs-auth-local/README.md +++ b/packages/nestjs-auth-local/README.md @@ -6,14 +6,13 @@ remote data source. ## Project [![NPM Latest](https://img.shields.io/npm/v/@concepta/nestjs-auth-local)](https://www.npmjs.com/package/@concepta/nestjs-auth-local) -[![NPM Downloads](https://img.shields.io/npm/dw/@conceptadev/nestjs-auth-local)](https://www.npmjs.com/package/@concepta/nestjs-auth-local) +[![NPM Downloads](https://img.shields.io/npm/dw/@concepta/nestjs-auth-local)](https://www.npmjs.com/package/@concepta/nestjs-auth-local) [![GH Last Commit](https://img.shields.io/github/last-commit/conceptadev/rockets?logo=github)](https://github.com/conceptadev/rockets) [![GH Contrib](https://img.shields.io/github/contributors/conceptadev/rockets?logo=github)](https://github.com/conceptadev/rockets/graphs/contributors) [![NestJS Dep](https://img.shields.io/github/package-json/dependency-version/conceptadev/rockets/@nestjs/common?label=NestJS&logo=nestjs&filename=packages%2Fnestjs-core%2Fpackage.json)](https://www.npmjs.com/package/@nestjs/common) ## Table of Contents -- [Project](#project) - [Tutorials](#tutorials) - [1. Getting Started with AuthLocalModule](#1-getting-started-with-authlocalmodule) - [1.1 Introduction](#11-introduction) @@ -37,7 +36,7 @@ remote data source. - [5. Implementing and Using Custom Token Issuance Service](#5-implementing-and-using-custom-token-issuance-service) - [6. Implementing and Using Custom User Validation Service](#6-implementing-and-using-custom-user-validation-service) - [7. Implementing and Using Custom Password Validation Service](#7-implementing-and-using-custom-password-validation-service) - - [8. Overwriting the Settings](#8-overwriting-the-settings) + - [8. Overriding the Settings](#8-overriding-the-settings) - [9. Integration with Other NestJS Modules](#9-integration-with-other-nestjs-modules) - [Reference](#reference) - [1. AuthLocalOptionsInterface](#1-authlocaloptionsinterface) @@ -62,17 +61,20 @@ remote data source. The `AuthLocalModule` is a robust NestJS module designed for implementing local authentication using username and password. This module leverages the -`passport-local` strategy to authenticate users locally within your -application. +[`passport-local`](https://www.passportjs.org/packages/passport-local) strategy +to authenticate users locally within your application. ##### Purpose and Key Features - **Local Authentication**: Provides a straightforward way to implement local authentication using username and password. + - **Synchronous and Asynchronous Registration**: Flexibly register the module either synchronously or asynchronously, depending on your application's needs. + - **Global and Feature-Specific Registration**: Use the module globally across your application or tailor it for specific features. + - **Customizable**: Easily customize various aspects such as user validation, token issuance, and password validation. @@ -108,12 +110,12 @@ Ensure to provide the necessary configuration options at The `AuthLocalOptionsInterface` defines the configuration options for the local authentication strategy within a NestJS application using the -`nestjs-auth-local` package. This interface allows for the customization +`@concepta/nestjs-auth-local` package. This interface allows for the customization of `userLookupService`, `issueTokenService`, `validateUserService`, and `passwordValidationService`. Please see [Reference](#reference) for more details. -optional fields utilize default implementations, enabling straightforward +Optional fields utilize default implementations, enabling straightforward integration and flexibility to override with custom implementations as needed. This setup ensures that developers can tailor the authentication process to specific requirements while maintaining a robust and secure authentication @@ -126,18 +128,21 @@ framework. To test this scenario, we will set up an application where users can log in using a username and password. We will create the necessary entities, services, module configurations. +> Note: The `@concepta/nestjs-user` module can be used in place of our example `User` related prerequisites. + ## Step 1: Create Entities First, create the `User` entity. -**Code:** ```ts +// user.entity.ts export class User { id: number; username: string; password: string; } ``` + ## Step 2: Create Services Next, you need to create the `UserLookupService`. This @@ -146,8 +151,8 @@ retrieving user data. It should implement the `AuthLocalUserLookupServiceInterface`. Within this service, implement the `byUsername` method to -fetch user details by their email. Ensure that the method -returns a `User` object containing `passwordHash` and +fetch user details by their username (or email). Ensure that +the method returns a `User` object containing `passwordHash` and `passwordSalt`. These attributes are crucial as they are used by the @@ -155,8 +160,8 @@ These attributes are crucial as they are used by the to authenticate the user, which is a configurable option in the `AuthLocalModule`. -**Code:** ```ts +// user-lookup.service.ts import { Injectable } from '@nestjs/common'; import { ReferenceUsername } from '@concepta/ts-core'; import { AuthLocalUserLookupServiceInterface } from '@concepta/nestjs-auth-local'; @@ -181,16 +186,17 @@ export class UserLookupService implements AuthLocalUserLookupServiceInterface { } } ``` + ## Step 3: Configure the Module Configure the module to include the necessary services `userLookupService`. -**Code:** ```ts +// app.module.ts import { Module } from '@nestjs/common'; import { AuthLocalModule } from '@concepta/nestjs-auth-local'; -import { UserLookupService } from './user-lookup.service'; import { JwtModule } from '@concepta/nestjs-jwt'; +import { UserLookupService } from './user-lookup.service'; @Module({ imports: [ @@ -204,11 +210,11 @@ import { JwtModule } from '@concepta/nestjs-jwt'; }) export class AppModule {} ``` + ## Validating the Setup To validate the setup, you can use `curl` commands to simulate frontend -requests. Here are the -steps to test the login endpoint: +requests. Here are the steps to test the login endpoint: ## Step 1: Obtain a JWT Token @@ -220,6 +226,7 @@ curl -X POST http://localhost:3000/auth/login \ -H "Content-Type: application/json" \ -d '{"username": "testuser", "password": "testpassword"}' ``` + This should return a response with a login message. ## Example @@ -227,12 +234,15 @@ This should return a response with a login message. Here is an example sequence of `curl` commands to validate the login setup: 1. **Login Request:** + +Command: ```sh curl -X POST http://localhost:3000/auth/login \ -H "Content-Type: application/json" \ -d '{"username": "username", "password": "Test1234"}' ``` -Example response: + +Response (example): ```json { "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0NjZkMTAyNS1iZGNkLTRiNWItYTYxMi0yYThiZTU2MDhlNjIiLCJpYXQiOjE3MTgwNDg1NDQsImV4cCI6MTcxODA1MjE0NH0.Zl2i59w89cgJxfI4lXn6VmOhC5GLEqMm2nWkiVKpEUs", @@ -241,36 +251,44 @@ Example response: ``` 2. **Invalid Credentials Request:** + +Command: ```sh curl -X POST http://localhost:3000/auth/login \ -H "Content-Type: application/json" \ -d '{"username": "testuser", "password": "wrongpassword"}' ``` -Example response: + +Response (example): ```json { "statusCode": 401, "message": "Unauthorized" } ``` + ## How-To Guides ### 1. Registering AuthLocalModule Synchronously -**Code:** ```ts +// app.module.ts + //... AuthLocalModule.register({ userLookupService: new MyUserLookupService(), // required }), //... ``` + ### 2. Registering AuthLocalModule Asynchronously -**Code:** ```ts +// app.module.ts +import { MyUserLookupService } from './services/my-user-lookup.service.ts'; + //... -AuthLocalModule.forRootAsync({ +AuthLocalModule.registerAsync({ useFactory: async (userLookupService: MyUserLookupService) => ({ userLookupService, // required }), @@ -278,10 +296,12 @@ AuthLocalModule.forRootAsync({ }), //... ``` + ### 3. Global Registering AuthLocalModule Asynchronously -**Code:** ```ts +// app.module.ts + //... AuthLocalModule.forRootAsync({ useFactory: async (userLookupService: MyUserLookupService) => ({ @@ -291,13 +311,16 @@ AuthLocalModule.forRootAsync({ }), //... ``` -### 4. Using Custom User Lookup Service -**Code:** +### 4. Implementing User Lookup Service + ```ts -import { AuthLocalUserLookupServiceInterface } from '@concepta/nestjs-auth-local'; -import { AuthLocalCredentialsInterface } from '@concepta/nestjs-auth-local/dist/interfaces/auth-local-credentials.interface'; +// my-user-lookup.service.ts import { Injectable } from '@nestjs/common'; +import { + AuthLocalUserLookupServiceInterface, + AuthLocalCredentialsInterface +} from '@concepta/nestjs-auth-local'; @Injectable() export class MyUserLookupService @@ -308,18 +331,20 @@ export class MyUserLookupService } } ``` + ### 5. Implementing custom token issuance service -There are two ways to implementing the custom token issuer service. You can -take advantage of the default service +There are two ways to implementing the custom token issue service. You can +take advantage of the default service, as seen here: ```ts +// my-jwt-issue.service.ts +import { Injectable } from '@nestjs/common'; import { -JwtIssueService, -JwtIssueServiceInterface, -JwtSignService, + JwtIssueService, + JwtIssueServiceInterface, + JwtSignService, } from '@concepta/nestjs-jwt'; -import { Injectable } from '@nestjs/common'; @Injectable() export class MyJwtIssueService extends JwtIssueService { @@ -331,24 +356,24 @@ export class MyJwtIssueService extends JwtIssueService { ...args: Parameters ) { // your custom code - return this.accessToken(...args); + return super.accessToken(...args); } async refreshToken( ...args: Parameters ) { // your custom code - return this.refreshToken(...args); + return super.refreshToken(...args); } } ``` -Or you can completely overwrite the default implementation. +Or you can completely replace the default implementation: -**Code:** ```ts -import { JwtIssueServiceInterface } from '@concepta/nestjs-jwt'; +// my-jwt-issue.service.ts import { Injectable } from '@nestjs/common'; +import { JwtIssueServiceInterface } from '@concepta/nestjs-jwt'; @Injectable() export class MyJwtIssueService implements JwtIssueServiceInterface { @@ -367,83 +392,98 @@ export class MyJwtIssueService implements JwtIssueServiceInterface { } } ``` -### 6. Implementing a custom user validation service -**Code:** +### 6. Implementing a custom user validation service The same approach can be done for `AuthLocalValidateUserService` you can -either completely overwrite the default implementation or you can take +either completely override the default implementation or you can take advantage of the default implementation. ```ts +// my-auth-local-validate-user.service.ts +import { Injectable } from '@nestjs/common'; +import { ReferenceActiveInterface, ReferenceIdInterface } from '@concepta/ts-core'; +import { + AuthLocalValidateUserInterface, + AuthLocalValidateUserService +} from '@concepta/nestjs-auth-local'; + @Injectable() export class MyAuthLocalValidateUserService - implements AuthLocalValidateUserServiceInterface + extends AuthLocalValidateUserService { - + async validateUser( dto: AuthLocalValidateUserInterface, ): Promise { - return this.validateUser(dto); + // customize as needed + return super.validateUser(dto); } async isActive( user: ReferenceIdInterface & ReferenceActiveInterface, ): Promise { - return true; + // customize as needed + return super.isActive(user); } } - ``` ```ts -import { AuthLocalValidateUserInterface, AuthLocalValidateUserServiceInterface } from "@concepta/nestjs-auth-local"; -import { ReferenceActiveInterface, ReferenceIdInterface } from "@concepta/ts-core"; -import { Injectable } from "@nestjs/common"; +// my-auth-local-validate-user.service.ts +import { Injectable } from '@nestjs/common'; +import { ReferenceActiveInterface, ReferenceIdInterface } from '@concepta/ts-core'; +import { + AuthLocalValidateUserInterface, + AuthLocalValidateUserServiceInterface +} from '@concepta/nestjs-auth-local'; @Injectable() export class MyAuthLocalValidateUserService implements AuthLocalValidateUserServiceInterface { - async validateUser( dto: AuthLocalValidateUserInterface, ): Promise { - return this.validateUser(dto); + // your custom code + return { + id: '[userId]', + //... + } } async isActive( user: ReferenceIdInterface & ReferenceActiveInterface, ): Promise { - return this.isActive(user); + // customize as needed + return true; } } - ``` ### 7. Implementing a Custom Password Validation Service -The `PasswordValidationService` in the `nestjs-auth-local` module provides a -default implementation using bcrypt for hashing and verifying passwords. +The `PasswordValidationService` in the `@concepta/nestjs-password` module +provides a default implementation using bcrypt for hashing and verifying passwords. However, depending on your application's requirements, you might need to use a different method for password hashing or add additional validation logic. You can either extend the existing `PasswordValidationService` to leverage its built-in functionalities while adding your enhancements, or completely -overwrite it with your custom implementation. - +override it with your custom implementation. -**Overwriting the Default Implementation:** +**Overriding the Default Implementation:** If your application requires a different hashing algorithm , you can replace the default implementation with one that suits your needs. ```ts +// my-password-validation.service.ts +import { Injectable } from '@nestjs/common'; import { PasswordStorageInterface, PasswordValidationServiceInterface, } from '@concepta/nestjs-password'; -import { Injectable } from '@nestjs/common'; @Injectable() export class MyPasswordValidationService @@ -454,6 +494,7 @@ export class MyPasswordValidationService passwordHash: string; passwordSalt: string; }): Promise { + // customize as needed return true; } @@ -461,16 +502,19 @@ export class MyPasswordValidationService password: string, object: T, ): Promise { + // customize as needed return true; } } ``` + **Extending the Default Service:** If you want to add additional validation logic while keeping the current hashing and validation, you can extend the default service: ```ts +// my-password-validation.service.ts import { PasswordStorageInterface, PasswordValidationService, @@ -479,30 +523,27 @@ import { Injectable } from '@nestjs/common'; @Injectable() export class MyPasswordValidationService extends PasswordValidationService { - constructor() { - super(); - } - async validate(options: { password: string; passwordHash: string; passwordSalt: string; }): Promise { - return this.validate(options); + // customize as neeeded + return super.validate(options); } async validateObject( password: string, object: T, ): Promise { - return this.validateObject(password, object); + // customize as neeeded + return super.validateObject(password, object); } } ``` -### 8. Overwriting the Settings +### 8. Overriding the Settings -**Code:** ```ts import { Type } from '@nestjs/common'; @@ -516,68 +557,78 @@ export const localSettings = { usernameField: 'email', passwordField: 'password' }; - ``` ```ts AuthLocalModule.forRoot({ userLookupService: new UserLookupService(), + issueTokenService: new MyIssueTokenService(), // <- optional + passwordValidationService: new PasswordValidationService(), // <- optional settings: localSettings }), ``` + ### 9. Integration with Other NestJS Modules Integrate `nestjs-auth-local` with other NestJS modules like, -`nestjs-authentication`, `nestjs-auth-jwt`, `nestjs-auth-refresh` for - a comprehensive authentication system. +`@concepta/nestjs-authentication`, `@concepta/nestjs-auth-jwt`, +`@concepta/nestjs-auth-refresh` for a comprehensive authentication system. ## Reference ### Explanation of Properties in `AuthLocalOptionsInterface` -#### 1. **userLookupService** (required) +#### 1. userLookupService (required) + - **Purpose**: Essential for retrieving user details based on the username to initiate the authentication process. + - **Method**: - `byUsername(username: string): Promise`: Queries user data storage to find a user by their username. Returns a user object if found, or `null` if no user exists with that username. -#### 2. **issueTokenService** (optional) +#### 2. issueTokenService (optional) + - **Purpose**: Handles the generation of access and refresh tokens after user authentication. + - **Class**: `IssueTokenService` - `accessToken(...)`: Generates an access token using the `JwtIssueService`. - `refreshToken(...)`: Generates a refresh token using the `JwtIssueService`. -#### 3. **validateUserService** (optional) -- **Purpose**: Validates if a user can be authenticated with the provided -credentials. -- **Class**: `AuthLocalValidateUserService` - - `validateUser(dto: AuthLocalValidateUserInterface)`: Uses - `userLookupService` to fetch the user, checks user activity, and - validates the password using `passwordValidationService`. +#### 3. validateUserService (optional) + + - **Purpose**: Validates if a user can be authenticated with the provided + credentials. + + - **Class**: `AuthLocalValidateUserService` + - `validateUser(dto: AuthLocalValidateUserInterface)`: Uses + `userLookupService` to fetch the user, checks user activity, and + validates the password using `passwordValidationService`. #### 4. **passwordValidationService** (optional) -- **Purpose**: Validates the user's password against the stored hash -to ensure the login attempt is legitimate. -- **Class**: `PasswordValidationService` - - `validate(options: { password: string; passwordHash: string; passwordSalt: string; })`: - Compares the provided password with the stored hash and salt using - cryptographic functions. - - `validateObject(password: string, object: T)`: - Validates the password on an object that includes password hash - and salt. + - **Purpose**: Validates the user's password against the stored hash + to ensure the login attempt is legitimate. + + - **Class**: `PasswordValidationService` + - `validate(options: { password: string; passwordHash: string; passwordSalt: string; })`: + Compares the provided password with the stored hash and salt using + cryptographic functions. + - `validateObject(password: string, object: T)`: + Validates the password on an object that includes password hash + and salt. #### 5. **settings** (optional) -- **Purpose**: Allows customization of the authentication process, - specifying how the login data should be structured and which fields - are used for username and password. -- **Details**: - - `loginDto`: Customizable data transfer object for login requests. - - `usernameField` and `passwordField`: Specify the field names in the - `loginDto` that represent the username and password. + - **Purpose**: Allows customization of the authentication process, + specifying how the login data should be structured and which fields + are used for username and password. + + - **Details**: + - `loginDto`: Customizable data transfer object for login requests. + - `usernameField` and `passwordField`: Specify the field names in the + `loginDto` that represent the username and password. ### 2. AuthLocalModule API Reference @@ -622,6 +673,7 @@ identity providers. - **Synchronous Registration**: Used when configuration options are static and available at startup. + - **Asynchronous Registration**: Used when configuration options need to be retrieved from external sources at runtime. @@ -629,6 +681,7 @@ retrieved from external sources at runtime. - **Global Registration**: Makes the module available throughout the entire application. + - **Feature-Specific Registration**: Allows the module to be registered only for specific features or modules within the application. diff --git a/packages/nestjs-auth-local/src/index.ts b/packages/nestjs-auth-local/src/index.ts index e19fa7d66..b2cd55474 100644 --- a/packages/nestjs-auth-local/src/index.ts +++ b/packages/nestjs-auth-local/src/index.ts @@ -1,10 +1,17 @@ +// interfaces export { AuthLocalValidateUserInterface } from './interfaces/auth-local-validate-user.interface'; export { AuthLocalUserLookupServiceInterface } from './interfaces/auth-local-user-lookup-service.interface'; export { AuthLocalValidateUserServiceInterface } from './interfaces/auth-local-validate-user-service.interface'; +export { AuthLocalCredentialsInterface } from './interfaces/auth-local-credentials.interface'; + +// DTOs +export { AuthLocalLoginDto } from './dto/auth-local-login.dto'; + +// module +export { AuthLocalModule } from './auth-local.module'; +export { AuthLocalController } from './auth-local.controller'; +export { AuthLocalValidateUserService } from './services/auth-local-validate-user.service'; -export * from './auth-local.module'; -export * from './auth-local.controller'; -export * from './dto/auth-local-login.dto'; export { AuthLocalGuard, AuthLocalGuard as LocalAuthGuard, From 69e847aff7e9dd276a2b129a88ee166774fcb634 Mon Sep 17 00:00:00 2001 From: Thiago Ramalho Date: Wed, 12 Jun 2024 12:44:54 -0300 Subject: [PATCH 4/4] chore: improve doc --- packages/nestjs-auth-local/README.md | 93 +++++----------------------- 1 file changed, 15 insertions(+), 78 deletions(-) diff --git a/packages/nestjs-auth-local/README.md b/packages/nestjs-auth-local/README.md index 1e50d2b5d..6de4e85aa 100644 --- a/packages/nestjs-auth-local/README.md +++ b/packages/nestjs-auth-local/README.md @@ -25,21 +25,20 @@ remote data source. - [Scenario: Users can log in using local authentication](#scenario-users-can-log-in-using-local-authentication) - [Step 1: Create Entities](#step-1-create-entities) - [Step 2: Create Services](#step-2-create-services) - - [Step 3: Create Controller](#step-3-create-controller) - - [Step 4: Configure the Module](#step-4-configure-the-module) + - [Step 3: Configure the Module](#step-3-configure-the-module) - [Validating the Setup](#validating-the-setup) - [How-To Guides](#how-to-guides) - [1. Registering AuthLocalModule Synchronously](#1-registering-authlocalmodule-synchronously) - [2. Registering AuthLocalModule Asynchronously](#2-registering-authlocalmodule-asynchronously) - [3. Global Registering AuthLocalModule Asynchronously](#3-global-registering-authlocalmodule-asynchronously) - - [4. Using Custom User Lookup Service](#4-using-custom-user-lookup-service) - - [5. Implementing and Using Custom Token Issuance Service](#5-implementing-and-using-custom-token-issuance-service) - - [6. Implementing and Using Custom User Validation Service](#6-implementing-and-using-custom-user-validation-service) - - [7. Implementing and Using Custom Password Validation Service](#7-implementing-and-using-custom-password-validation-service) + - [4. Implementing User Lookup Service](#4-implementing-user-lookup-service) + - [5. Implementing custom token issuance service](#5-implementing-custom-token-issuance-service) + - [6. Implementing a custom user validation service](#6-implementing-a-custom-user-validation-service) + - [7. Implementing a custom password validation service](#7-implementing-a-custom-password-validation-service) - [8. Overriding the Settings](#8-overriding-the-settings) - [9. Integration with Other NestJS Modules](#9-integration-with-other-nestjs-modules) - [Reference](#reference) - - [1. AuthLocalOptionsInterface](#1-authlocaloptionsinterface) + - [1. Explanation of Properties in AuthLocalOptionsInterface](#1-explanation-of-properties-in-authlocaloptionsinterface) - [2. AuthLocalModule API Reference](#2-authlocalmodule-api-reference) - [Explanation](#explanation) - [Conceptual Overview of Local Authentication](#conceptual-overview-of-local-authentication) @@ -49,7 +48,6 @@ remote data source. - [Why Use Local Authentication?](#why-use-local-authentication) - [Synchronous vs Asynchronous Registration](#synchronous-vs-asynchronous-registration) - [Global vs Feature-Specific Registration](#global-vs-feature-specific-registration) - - [Integrating AuthLocalModule with Other Modules](#integrating-authlocalmodule-with-other-modules) ## Tutorials @@ -216,7 +214,7 @@ export class AppModule {} To validate the setup, you can use `curl` commands to simulate frontend requests. Here are the steps to test the login endpoint: -## Step 1: Obtain a JWT Token +### Step 1: Obtain a JWT Token Assuming you have an endpoint to obtain a JWT token, use `curl` to get the token. Replace `auth-url` with your actual authentication URL, and @@ -229,7 +227,7 @@ curl -X POST http://localhost:3000/auth/login \ This should return a response with a login message. -## Example +### Example Here is an example sequence of `curl` commands to validate the login setup: @@ -461,7 +459,7 @@ export class MyAuthLocalValidateUserService } ``` -### 7. Implementing a Custom Password Validation Service +### 7. Implementing a custom password validation service The `PasswordValidationService` in the `@concepta/nestjs-password` module provides a default implementation using bcrypt for hashing and verifying passwords. @@ -576,73 +574,12 @@ Integrate `nestjs-auth-local` with other NestJS modules like, ## Reference -### Explanation of Properties in `AuthLocalOptionsInterface` - -#### 1. userLookupService (required) - -- **Purpose**: Essential for retrieving user details based on the username to -initiate the authentication process. - -- **Method**: - - `byUsername(username: string): Promise`: - Queries user data storage to find a user by their username. Returns a user - object if found, or `null` if no user exists with that username. - -#### 2. issueTokenService (optional) - -- **Purpose**: Handles the generation of access and refresh tokens after user -authentication. - -- **Class**: `IssueTokenService` - - `accessToken(...)`: Generates an access token using the `JwtIssueService`. - - `refreshToken(...)`: Generates a refresh token using the `JwtIssueService`. - -#### 3. validateUserService (optional) - - - **Purpose**: Validates if a user can be authenticated with the provided - credentials. - - - **Class**: `AuthLocalValidateUserService` - - `validateUser(dto: AuthLocalValidateUserInterface)`: Uses - `userLookupService` to fetch the user, checks user activity, and - validates the password using `passwordValidationService`. - -#### 4. **passwordValidationService** (optional) - - - **Purpose**: Validates the user's password against the stored hash - to ensure the login attempt is legitimate. - - - **Class**: `PasswordValidationService` - - `validate(options: { password: string; passwordHash: string; passwordSalt: string; })`: - Compares the provided password with the stored hash and salt using - cryptographic functions. - - `validateObject(password: string, object: T)`: - Validates the password on an object that includes password hash - and salt. - -#### 5. **settings** (optional) - - **Purpose**: Allows customization of the authentication process, - specifying how the login data should be structured and which fields - are used for username and password. - - - **Details**: - - `loginDto`: Customizable data transfer object for login requests. - - `usernameField` and `passwordField`: Specify the field names in the - `loginDto` that represent the username and password. - -### 2. AuthLocalModule API Reference - -- **register(options: AuthLocalOptions):** - - Registers the module with synchronous options. - -- **registerAsync(options: AuthLocalAsyncOptions):** - - Registers the module with asynchronous options. - -- **forRoot(options: AuthLocalOptions):** - - Registers the module globally with synchronous options. - -- **forRootAsync(options: AuthLocalAsyncOptions):** - - Registers the module globally with asynchronous options. +For detailed information on the properties, methods, and classes used in the +`@concepta/nestjs-auth-local`, please refer to the API documentation +available at [AuthLocalModule API Documentation](). This documentation provides +comprehensive details on the interfaces and services that you can utilize to +customize and extend the authentication functionality within your NestJS +application. ## Explanation