### Install and Run Project Source: https://github.com/thallesp/nestjs-better-auth/blob/master/examples/nestjs-better-auth-example/README.md Commands to install dependencies and start the development server. ```bash pnpm install pnpm start:dev ``` -------------------------------- ### Install NestJS Better Auth with bun Source: https://github.com/thallesp/nestjs-better-auth/blob/master/README.md Install the library in your NestJS project using bun. ```bash bun add @thallesp/nestjs-better-auth ``` -------------------------------- ### Complete NestJS Better Auth Configuration Example Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/configuration.md This example demonstrates a full configuration for Better Auth within a NestJS application, including imports, environment variable usage, plugins, and module setup. ```typescript import { Module } from "@nestjs/common"; import { ConfigModule, ConfigService } from "@nestjs/config"; import { AuthModule } from "@thallesp/nestjs-better-auth"; import { betterAuth } from "better-auth"; import { admin } from "better-auth/plugins/admin"; import { organization } from "better-auth/plugins/organization"; const createAuthInstance = (configService: ConfigService) => { return betterAuth({ basePath: "/api/auth", database: { type: "postgres", url: configService.get("DATABASE_URL"), }, plugins: [ admin(), organization(), ], trustedOrigins: configService.get("TRUSTED_ORIGINS").split(","), hooks: {}, databaseHooks: {}, }); }; @Module({ imports: [ ConfigModule.forRoot(), AuthModule.forRootAsync({ imports: [ConfigModule], inject: [ConfigService], useFactory: (configService: ConfigService) => ({ auth: createAuthInstance(configService), bodyParser: { json: { limit: configService.get("BODY_LIMIT", "2mb"), }, urlencoded: { limit: configService.get("BODY_LIMIT", "2mb"), extended: true, }, rawBody: true, }, disableTrustedOriginsCors: false, disableGlobalAuthGuard: false, disableControllers: false, middleware: undefined, }), }), ], }) export class AppModule {} ``` -------------------------------- ### Get Admin Users (Plugin Example) Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/auth-service.md This example shows how to access plugin-specific methods, such as `listUsers` from the admin plugin, by providing a more specific type to the AuthService constructor. ```APIDOC ## GET /admin/users ### Description Retrieves a list of admin users using the `listUsers` method from the admin plugin. ### Method GET ### Endpoint /admin/users ### Parameters #### Request Body - **headers** (object) - Required - Request headers, typically obtained from the incoming request. ### Request Example ```typescript // Inside a NestJS Service @Injectable() export class AdminService { constructor( private readonly authService: AuthService>>, ) {} async getAdminUsers() { const result = await this.authService.api.listUsers({ headers: new Headers(), // Example: Use actual headers }); return result; } } ``` ### Response #### Success Response (200) - **(type depends on implementation)** - The list of admin users. ``` -------------------------------- ### AuthModule Body Parser Configuration Example Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/types.md Example demonstrating how to configure the bodyParser for AuthModule.forRoot(). This includes enabling JSON, URL-encoded parsing with specific limits and options, and enabling raw body capture. ```typescript AuthModule.forRoot({ auth, bodyParser: { json: { enabled: true, limit: "5mb", reviver: (key, value) => value, }, urlencoded: { enabled: true, extended: true, limit: "2mb", parameterLimit: 50, }, rawBody: true, }, }) ``` -------------------------------- ### Install Dependencies with Bun Source: https://github.com/thallesp/nestjs-better-auth/blob/master/CONTRIBUTING.md Install project dependencies using Bun. This command ensures that the bun.lock file is respected, which is crucial for maintaining a consistent development environment. ```bash bun install ``` -------------------------------- ### AuthModule Setup Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/INDEX.md Demonstrates how to import and configure the AuthModule for NestJS applications. ```APIDOC ## Module Entry Point ### Description Import and set up the `AuthModule` in your NestJS application. ### Import ```typescript import { AuthModule } from "@thallesp/nestjs-better-auth"; ``` ### Setup ```typescript AuthModule.forRoot({ auth, // Required: Better Auth instance bodyParser: { /* ... */ }, // Optional: Body parser config middleware: (req, res, next) => {}, // Optional: Custom middleware disableTrustedOriginsCors: false, // Optional: Disable auto CORS disableGlobalAuthGuard: false, // Optional: Disable global guard disableControllers: false, // Optional: Disable route controllers }) ``` ``` -------------------------------- ### Install NestJS Better Auth with pnpm Source: https://github.com/thallesp/nestjs-better-auth/blob/master/README.md Install the library in your NestJS project using pnpm. ```bash pnpm add @thallesp/nestjs-better-auth ``` -------------------------------- ### Auth Instance Configuration Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/configuration.md Example of creating a Better Auth instance with plugins and database configuration. Required if using @Hook() or @DatabaseHook() decorators. ```typescript import { betterAuth, } from "better-auth"; import { admin } from "better-auth/plugins/admin"; const auth = betterAuth({ basePath: "/api/auth", database: { type: "postgres", url: process.env.DATABASE_URL, }, plugins: [admin()], hooks: {}, databaseHooks: {}, }); AuthModule.forRoot({ auth }) ``` -------------------------------- ### Install NestJS Better Auth with npm Source: https://github.com/thallesp/nestjs-better-auth/blob/master/README.md Install the library in your NestJS project using npm. ```bash npm install @thallesp/nestjs-better-auth ``` -------------------------------- ### Install NestJS Better Auth with yarn Source: https://github.com/thallesp/nestjs-better-auth/blob/master/README.md Install the library in your NestJS project using yarn. ```bash yarn add @thallesp/nestjs-better-auth ``` -------------------------------- ### AuthModule.forRoot Synchronous Configuration Example Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/auth-module.md Demonstrates synchronous configuration of AuthModule using forRoot, showing how to pass the auth instance and options like disabling CORS. ```typescript // Synchronous configuration AuthModule.forRoot({ auth: myBetterAuthInstance, bodyParser: { json: { limit: "5mb" }, urlencoded: { enabled: true, extended: true }, rawBody: true, }, }) // Or with auth as first argument (deprecated but supported) AuthModule.forRoot(myBetterAuthInstance, { disableTrustedOriginsCors: true, }) ``` -------------------------------- ### Install 'qs' for Fastify Extended URL-Encoded Parsing Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/errors.md When using the Fastify adapter with 'bodyParser.urlencoded.extended: true', install the 'qs' package to enable nested URL-encoded parsing. This resolves errors related to missing peer dependencies. ```bash npm install qs ``` -------------------------------- ### Get Current User Session Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/auth-service.md This example demonstrates how to retrieve the current user's session information using the `getSession` method. It highlights the necessity of passing request headers for session validation. ```APIDOC ## GET /profile/me ### Description Fetches the session information for the currently authenticated user. ### Method GET ### Endpoint /profile/me ### Parameters #### Request Body - **headers** (object) - Required - Request headers, typically obtained from the incoming request. ### Request Example ```typescript // Inside a NestJS Controller @Get("me") async getCurrentUser(@Request() req: ExpressRequest) { const session = await this.authService.api.getSession({ headers: fromNodeHeaders(req.headers), }); return session?.user; } ``` ### Response #### Success Response (200) - **user** (object) - The user object if the session is valid, otherwise null or undefined. - **(other session properties)** - Additional session details. ``` -------------------------------- ### PermissionCheck Usage Examples Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/types.md Provides examples of PermissionCheck objects for different scenarios, including project permissions, multiple resources, and single actions. ```typescript // User project permissions { project: ["create", "update", "delete"] } // Multiple resources { project: ["create"], sale: ["read", "update"] } // Single action { project: ["delete"] } ``` -------------------------------- ### PermissionCheck Format Example Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/types.md Illustrates the structure of a PermissionCheck object, showing how to define permissions for multiple resources and actions. ```typescript { resource: ["action1", "action2"], anotherResource: ["actionA", "actionB"] } ``` -------------------------------- ### AuthModule.forRootAsync Asynchronous Configuration Example Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/auth-module.md Illustrates asynchronous configuration of AuthModule using forRootAsync, enabling dependency injection for auth instance creation and configuration values. ```typescript import { AuthModule } from "@thallesp/nestjs-better-auth"; import { ConfigModule, ConfigService } from "@nestjs/config"; @Module({ imports: [ AuthModule.forRootAsync({ imports: [ConfigModule], inject: [ConfigService], useFactory: (configService: ConfigService) => ({ auth: createAuthInstance(configService), bodyParser: { json: { limit: configService.get("BODY_LIMIT") }, }, }), }), ], }) export class AppModule {} ``` -------------------------------- ### BodyParserLimit Configuration Examples Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/types.md Demonstrates how to configure body parser limits using numbers for bytes or strings with unit suffixes like 'mb' or 'gb'. Case-insensitive suffixes are supported. ```typescript bodyParser: { json: { limit: 1048576, // 1MB in bytes // or limit: "1mb", // 1MB as string // or limit: "0.5gb", // 0.5GB } } ``` -------------------------------- ### BeforeCreate() Hook Example Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/decorators.md Registers a hook to run before a record is created. Can modify data or abort creation by returning false. ```typescript @DatabaseHook() @Injectable() export class UserHooks { @BeforeCreate("user") async beforeCreate(user: any) { // Modify data before creation return { data: { ...user, createdAt: new Date(), }, }; } } ``` -------------------------------- ### Install WebSocket Dependencies Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/errors.md Install the necessary packages for WebSocket support in your NestJS application. This is required when using @nestjs/websockets. ```bash npm install @nestjs/websockets @nestjs/platform-socket.io ``` -------------------------------- ### NestJS AuthModule Setup Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/INDEX.md Demonstrates how to configure the AuthModule in a NestJS application using better-auth. Ensure to provide necessary configurations for auth, bodyParser, hooks, and databaseHooks. ```typescript import { Module } from "@nestjs/common"; import { AuthModule } from "@thallesp/nestjs-better-auth"; import { betterAuth } from "better-auth"; import { admin } from "better-auth/plugins/admin"; const auth = betterAuth({ basePath: "/api/auth", database: { /* ... */ }, plugins: [admin()], hooks: {}, databaseHooks: {}, }); @Module({ imports: [ AuthModule.forRoot({ auth, bodyParser: { json: { limit: "2mb" }, urlencoded: { extended: true }, rawBody: true, }, }), ], }) export class AppModule {} ``` -------------------------------- ### Custom Auth Controller Example Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/endpoints.md Demonstrates how to inject and use AuthService in a custom NestJS controller to access user accounts and sign out. ```APIDOC ## GET /auth-custom/public-info ### Description An example of a public endpoint that does not require authentication. ### Method GET ### Endpoint /auth-custom/public-info ## GET /auth-custom/accounts ### Description Retrieves a list of user accounts associated with the authenticated user. ### Method GET ### Endpoint /auth-custom/accounts ### Parameters #### Request Body None ### Response #### Success Response (200) - **accounts** (array) - A list of user accounts. ## POST /auth-custom/sign-out-custom ### Description Signs the current user out. ### Method POST ### Endpoint /auth-custom/sign-out-custom ### Parameters #### Request Body None ### Response #### Success Response (200) - **message** (string) - Confirmation of sign-out. ``` -------------------------------- ### BeforeDelete() Hook Example Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/decorators.md Registers a hook to run before a record is deleted. Can abort the deletion by returning false. ```typescript @DatabaseHook() @Injectable() export class UserHooks { @BeforeDelete("user") async beforeDelete(user: any) { // Can abort by returning false return true; // or false to abort } } ``` -------------------------------- ### UserSession Usage Example Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/types.md Demonstrates how to use the UserSession type, both with and without plugin type inference. Import Session and UserSession from the library and use the @Session() decorator. ```typescript import { Session, UserSession } from "@thallesp/nestjs-better-auth"; import { betterAuth } from "better-auth"; import { admin } from "better-auth/plugins/admin"; const auth = betterAuth({ plugins: [admin()], }); // Without plugin type inference @Get("me") getMe(@Session() session: UserSession) { session.user.role; // typed as string | string[] | undefined } // With plugin type inference @Get("me") getMe(@Session() session: UserSession) { // Full type safety for admin plugin fields } ``` -------------------------------- ### Run Baseline Checks Source: https://github.com/thallesp/nestjs-better-auth/blob/master/CONTRIBUTING.md Execute the baseline checks, including linting, formatting, building, and testing, to ensure the project is in a green state before making changes. These commands should pass before starting development. ```bash bun run check bun run build bun run test ``` -------------------------------- ### Applying AuthGuard Per-Route Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/auth-guard.md Example of applying the AuthGuard to a specific route using the @UseGuards decorator. It demonstrates accessing the user session. ```typescript import { Controller, Get, UseGuards } from "@nestjs/common"; import { AuthGuard, Session, UserSession } from "@thallesp/nestjs-better-auth"; // Apply AuthGuard per-route @Controller("protected") export class ProtectedController { @Get("profile") @UseGuards(AuthGuard) async getProfile(@Session() session: UserSession) { return session.user; } } ``` -------------------------------- ### UserHasPermission Decorator Examples Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/types.md Shows how to use the @UserHasPermission decorator with different option configurations, including single permission checks, multiple checks, and role-based checks. ```typescript @UserHasPermission({ permission: { project: ["create", "update"] } }) @UserHasPermission({ permissions: { project: ["create"], sale: ["delete"] } }) @UserHasPermission({ role: "editor", permission: { project: ["create"] } }) ``` -------------------------------- ### BeforeUpdate() Hook Example Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/decorators.md Registers a hook to run before a record is updated. Can modify data or abort the update by returning false. ```typescript @DatabaseHook() @Injectable() export class UserHooks { @BeforeUpdate("user") async beforeUpdate(user: any) { return { data: { ...user, updatedAt: new Date(), }, }; } } ``` -------------------------------- ### Applying AuthGuard to Controller Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/auth-guard.md Example of applying the AuthGuard to an entire controller using the @UseGuards decorator. All routes within this controller will be protected. ```typescript // Apply AuthGuard to entire controller @UseGuards(AuthGuard) @Controller("admin") export class AdminController { @Get("dashboard") async getDashboard() { return { message: "Admin only" }; } } ``` -------------------------------- ### AfterCreate() Hook Example Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/decorators.md Registers a hook to run after a record is created. Useful for performing side effects. Errors in after hooks do not abort the operation. ```typescript @DatabaseHook() @Injectable() export class UserHooks { @AfterCreate("user") async afterCreate(user: any) { // Side effects after creation console.log("User created:", user.id); } } ``` -------------------------------- ### Sign Out User Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/auth-service.md This example demonstrates how to use the `signOut` method from the AuthService API to sign out a user. It requires passing request headers, which can be converted from Node.js headers using `fromNodeHeaders`. ```APIDOC ## POST /users/sign-out ### Description Signs out the current user. ### Method POST ### Endpoint /users/sign-out ### Parameters #### Request Body - **headers** (object) - Required - Request headers, typically obtained from the incoming request. ### Request Example ```typescript // Inside a NestJS Controller @Post("sign-out") async signOut(@Request() req: ExpressRequest) { return this.authService.api.signOut({ headers: fromNodeHeaders(req.headers), }); } ``` ### Response #### Success Response (200) - **(type depends on implementation)** - The result of the sign-out operation. ``` -------------------------------- ### DatabaseHook() Decorator Example Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/decorators.md Marks a provider as containing database lifecycle hook methods. Must be applied to classes using hook method decorators like @BeforeCreate(). Requires databaseHooks configuration. ```typescript import { Injectable } from "@nestjs/common"; import { DatabaseHook, BeforeCreate, AfterCreate } from "@thallesp/nestjs-better-auth"; import { EmailService } from "./email.service"; @DatabaseHook() @Injectable() export class UserHooks { constructor(private emailService: EmailService) {} @BeforeCreate("user") async beforeUserCreate(user: any) { return { data: { ...user, firstName: user.name?.split(" ")[0], }, }; } @AfterCreate("user") async afterUserCreate(user: any) { await this.emailService.sendWelcome(user.email); } } ``` -------------------------------- ### AfterUpdate() Hook Example Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/decorators.md Registers a hook to run after a record is updated. Useful for performing side effects after an update. ```typescript @DatabaseHook() @Injectable() export class UserHooks { @AfterUpdate("user") async afterUpdate(user: any) { console.log("User updated:", user.id); } } ``` -------------------------------- ### Get Session Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/endpoints.md Endpoint to retrieve the current user's session information. ```APIDOC ## GET /api/auth/session ### Description Retrieves the details of the currently authenticated user session. ### Method GET ### Endpoint /api/auth/session ### Response #### Success Response (200) - **session** (object) - Contains session details, including user information. - **userId** (string) - The ID of the user. - **expiresAt** (string) - The expiration timestamp of the session. #### Response Example { "session": { "userId": "user-123", "expiresAt": "2023-10-27T10:00:00Z" } } ``` -------------------------------- ### AfterDelete() Hook Example Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/decorators.md Registers a hook to run after a record is deleted. Useful for performing side effects after deletion. ```typescript @DatabaseHook() @Injectable() export class UserHooks { @AfterDelete("user") async afterDelete(user: any) { console.log("User deleted:", user.id); } } ``` -------------------------------- ### Configure Middleware for Error Handling Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/configuration.md Implement custom error handling within the Better Auth middleware. This example shows basic error catching and response termination. ```typescript AuthModule.forRoot({ auth, middleware: (req, res, next) => { try { next(); } catch (error) { res.statusCode = 500; res.end("Internal Server Error"); } }, }) ``` -------------------------------- ### Sign Up User Source: https://github.com/thallesp/nestjs-better-auth/blob/master/examples/nestjs-better-auth-example/README.md Use this cURL command to sign up a new user with email and password. ```bash curl -X POST http://localhost:3000/api/auth/sign-up/email \ -H "Content-Type: application/json" \ -d '{"email": "test@example.com", "password": "password123", "name": "Test User"}' ``` -------------------------------- ### Build the Package Source: https://github.com/thallesp/nestjs-better-auth/blob/master/CONTRIBUTING.md Build the package using the unbuild tool. This command compiles the project's code for distribution. ```bash bun run build ``` -------------------------------- ### Run Fastify Adapter Tests Source: https://github.com/thallesp/nestjs-better-auth/blob/master/CONTRIBUTING.md Execute the test suite specifically for the Fastify adapter. Use this command to isolate and test Fastify-specific behavior. ```bash bun run test:fastify ``` -------------------------------- ### Run Full Test Suite Source: https://github.com/thallesp/nestjs-better-auth/blob/master/CONTRIBUTING.md Execute the complete test suite across both Express and Fastify adapters. This ensures compatibility and correctness on all supported HTTP adapters. ```bash bun run test ``` -------------------------------- ### MemberHasPermission Decorator Example Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/types.md Illustrates the usage of the @MemberHasPermission decorator, specifying the required 'permissions' object for an organization member. ```typescript @MemberHasPermission({ permissions: { project: ["create", "update"] } }) ``` -------------------------------- ### AuthModule.forRoot() Options Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/configuration.md Primary configuration interface for the authentication module. Accepts various options to customize its behavior. ```typescript AuthModule.forRoot({ auth, bodyParser, middleware, disableTrustedOriginsCors, disableGlobalAuthGuard, disableControllers, }) ``` -------------------------------- ### Body Parser Deprecated vs Recommended Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/configuration.md Illustrates the transition from deprecated body parser options to the recommended 'bodyParser' configuration object. ```typescript // Old way (deprecated) AuthModule.forRoot({ auth, disableBodyParser: true, enableRawBodyParser: true, }) // New way (recommended) AuthModule.forRoot({ auth, bodyParser: { json: { enabled: true }, urlencoded: { enabled: true }, rawBody: true, }, }) ``` -------------------------------- ### Configure AuthModule with Default Options Source: https://github.com/thallesp/nestjs-better-auth/blob/master/README.md Provides a basic configuration for AuthModule.forRoot() with common options like body parser settings. ```typescript AuthModule.forRoot({ auth, disableTrustedOriginsCors: false, bodyParser: { json: { enabled: true }, urlencoded: { enabled: true, extended: true }, rawBody: false, }, disableBodyParser: false, enableRawBodyParser: false, disableGlobalAuthGuard: false, disableControllers: false, }); ``` -------------------------------- ### Email Sign-up Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/endpoints.md Endpoint for user sign-up using email and password. ```APIDOC ## POST /api/auth/sign-up/email ### Description Handles user registration via email. ### Method POST ### Endpoint /api/auth/sign-up/email ### Request Body - **email** (string) - Required - User's email address. - **password** (string) - Required - User's chosen password. ### Response #### Success Response (201) - **message** (string) - Indicates successful sign-up. #### Response Example { "message": "User created successfully" } ``` -------------------------------- ### Configure System-Level Access Control Source: https://github.com/thallesp/nestjs-better-auth/blob/master/README.md Sets up access control for system-wide permissions using Better Auth's admin plugin. Requires configuration of statements, roles, and the admin plugin. ```typescript import { betterAuth } from "better-auth"; import { admin } from "better-auth/plugins/admin"; import { createAccessControl } from "better-auth/plugins/access"; const statement = { project: ["create", "share", "update", "delete"], sale: ["create", "read", "update", "delete"], } as const; const ac = createAccessControl(statement); const editor = ac.newRole({ project: ["create", "update"], }); const admin = ac.newRole({ project: ["create", "update", "delete"], sale: ["create", "read", "update", "delete"], }); export const auth = betterAuth({ plugins: [ admin({ ac, roles: { editor, admin, }, }), ], }); ``` -------------------------------- ### Run Express Adapter Tests Source: https://github.com/thallesp/nestjs-better-auth/blob/master/CONTRIBUTING.md Execute the test suite specifically for the Express adapter. Use this command to isolate and test Express-specific behavior. ```bash bun run test:express ``` -------------------------------- ### AuthModule.forRootAsync() Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/auth-module.md Asynchronously configures and registers the AuthModule, supporting dependency injection for the auth instance and other configuration options. ```APIDOC ## AuthModule.forRootAsync() ### Description Asynchronously configures and registers the AuthModule, supporting dependency injection for the auth instance and other configuration options. ### Method Signature ```typescript static forRootAsync(options: { imports?: any[]; inject?: any[]; useFactory: ( ...deps: unknown[] ) => Promise | AuthModuleOptions; isGlobal?: boolean; disableGlobalAuthGuard?: boolean; disableControllers?: boolean; }): DynamicModule ``` ### Parameters #### `options` Object - **imports** (any[]) - Optional - List of modules to import for dependency injection. - **inject** (any[]) - Optional - List of providers to inject into the `useFactory` function. - **useFactory** ((...deps: unknown[]) => Promise | AuthModuleOptions) - Required - Factory function that returns the `AuthModuleOptions`. - **isGlobal** (boolean) - Optional - Whether the module should be global. Defaults to `false`. - **disableGlobalAuthGuard** (boolean) - Optional - When true, does not register AuthGuard as a global guard. Manual per-controller registration with `@UseGuards(AuthGuard)` required. Defaults to `false`. - **disableControllers** (boolean) - Optional - When true, does not register any controllers. Use when handling routes manually. Defaults to `false`. ### Returns `DynamicModule` - A NestJS dynamic module with asynchronous configuration. ### Example ```typescript import { AuthModule } from "@thallesp/nestjs-better-auth"; import { ConfigModule, ConfigService } from "@nestjs/config"; @Module({ imports: [ AuthModule.forRootAsync({ imports: [ConfigModule], inject: [ConfigService], useFactory: (configService: ConfigService) => ({ auth: createAuthInstance(configService), bodyParser: { json: { limit: configService.get("BODY_LIMIT") }, }, }), }), ], }) export class AppModule {} ``` ``` -------------------------------- ### Sign In User and Save Cookie Source: https://github.com/thallesp/nestjs-better-auth/blob/master/examples/nestjs-better-auth-example/README.md Sign in a user and save the authentication cookie for subsequent requests. ```bash curl -X POST http://localhost:3000/api/auth/sign-in/email \ -H "Content-Type: application/json" \ -d '{"email": "test@example.com", "password": "password123"}' \ -c cookies.txt ``` -------------------------------- ### Accessing the Full Better Auth Instance via AuthService Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/auth-service.md Illustrates how to access the complete Better Auth instance, including any plugin extensions, through the `instance` property of the AuthService. This is useful for interacting with plugin-specific functionalities. ```typescript import { Injectable } from "@nestjs/common"; import { AuthService } from "@thallesp/nestjs-better-auth"; import type { Admin } from "better-auth/plugins/admin"; @Injectable() export class UserService { constructor( private readonly authService: AuthService<{ admin: Admin; }>, ) {} async getUser(userId: string) { // Access plugin-extended instance const auth = this.authService.instance; return auth; // Fully typed with plugins } } ``` -------------------------------- ### KnownBodyParserLimit Type Definition Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/types.md A string literal union for common body limit formats, including plain numbers or numbers with byte unit suffixes. Examples include '100', '2mb', and '0.5gb'. ```typescript export type KnownBodyParserLimit = | `${number}` | `${number}${BodyParserByteUnit}`; ``` -------------------------------- ### Disable Fastify Extended URL-Encoded Parsing Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/errors.md Alternatively, to avoid installing the 'qs' dependency, you can disable extended URL-encoded parsing by setting 'extended: false' in the bodyParser configuration. This uses simple form parsing. ```typescript AuthModule.forRoot({ auth, bodyParser: { urlencoded: { extended: false, // Use simple form parsing instead }, }, }) ``` -------------------------------- ### Configure AuthModule with forRoot Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/INDEX.md Initialize the AuthModule using the forRoot static method, providing necessary configuration options such as the Better Auth instance and optional middleware or body parser configurations. ```typescript AuthModule.forRoot({ auth, bodyParser: { /* ... */ }, middleware: (req, res, next) => {}, disableTrustedOriginsCors: false, disableGlobalAuthGuard: false, disableControllers: false, }) ``` -------------------------------- ### Verifying Webhook Signatures in NestJS Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/endpoints.md Implement webhook handlers to verify incoming request signatures using the raw request body and a secret. This example shows how to handle Stripe webhook signatures by comparing a generated HMAC hash with the provided signature header. ```typescript import { Controller, Post, Request, RawBodyRequest } from "@nestjs/common"; import type { Request as ExpressRequest } from "express"; import crypto from "crypto"; @Controller("webhooks") @AllowAnonymous() export class WebhookController { @Post("stripe") handleStripeWebhook(@Request() req: RawBodyRequest) { const sig = req.headers["stripe-signature"] as string; const body = req.rawBody; const hash = crypto .createHmac("sha256", process.env.STRIPE_WEBHOOK_SECRET) .update(body) .digest("hex"); if (hash !== sig) { throw new BadRequestException("Invalid signature"); } return { received: true }; } } ``` -------------------------------- ### Email Sign-in Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/endpoints.md Endpoint for user sign-in using email and password. ```APIDOC ## POST /api/auth/sign-in/email ### Description Authenticates a user using their email and password. ### Method POST ### Endpoint /api/auth/sign-in/email ### Request Body - **email** (string) - Required - User's email address. - **password** (string) - Required - User's password. ### Response #### Success Response (200) - **sessionToken** (string) - JWT token for the authenticated session. #### Response Example { "sessionToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } ``` -------------------------------- ### Run Lint and Format Checks Source: https://github.com/thallesp/nestjs-better-auth/blob/master/CONTRIBUTING.md Perform linting and formatting checks using Biome. This command should be run before submitting a pull request to ensure code quality and consistency. ```bash bun run check ``` -------------------------------- ### BeforeCreate() Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/decorators.md Method decorator for registering a hook that runs before a record is created. It can modify the data before creation or abort the operation. ```APIDOC ## BeforeCreate(model: DatabaseHookModel) ### Description Method decorator registering a hook to run before a record is created. ### Parameters #### Path Parameters - **model** (DatabaseHookModel) - Required - The model to hook: `"user"`, `"session"`, `"account"`, or `"verification"` ### Return Value - `false` — abort the creation - `{ data: ... }` — modify the data before creation - undefined — continue with original data ### Related `AfterCreate()`, `DatabaseHook()` ``` -------------------------------- ### Configuration Types Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/INDEX.md Provides types for module configuration, including main options, body parser settings, and middleware signatures. ```typescript AuthModuleOptions // Main config type AuthModuleBodyParserOptions // Body parser config AuthModuleJsonBodyParserOptions // JSON parser options AuthModuleUrlencodedBodyParserOptions // URL-encoded options AuthModuleMiddleware // Middleware signature ``` -------------------------------- ### Configure Middleware for MikroORM Integration Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/configuration.md Integrate Better Auth middleware with MikroORM's RequestContext for request-scoped ORM access. Ensure the ORM instance is available. ```typescript import { RequestContext } from "@mikro-orm/core"; AuthModule.forRoot({ auth, middleware: (req, res, next) => { RequestContext.create(orm.em, next); }, }) ``` -------------------------------- ### AuthModule.forRoot() Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/auth-module.md Synchronously configures and registers the AuthModule with NestJS. It accepts an options object to customize authentication behavior, body parsing, and middleware. ```APIDOC ## AuthModule.forRoot() ### Description Synchronously configures and registers the AuthModule with NestJS. It accepts an options object to customize authentication behavior, body parsing, and middleware. ### Method Signature ```typescript static forRoot(options: { auth: Auth; disableTrustedOriginsCors?: boolean; bodyParser?: AuthModuleBodyParserOptions; middleware?: AuthModuleMiddleware; disableGlobalAuthGuard?: boolean; disableControllers?: boolean; }): DynamicModule ``` ### Alternative Method Signature ```typescript static forRoot( auth: Auth, options?: Omit ): DynamicModule ``` ### Parameters #### `options` Object - **auth** (Auth) - Required - Better Auth instance created with `betterAuth()` - **disableTrustedOriginsCors** (boolean) - Optional - Disables automatic CORS configuration from Better Auth's `trustedOrigins` setting. On Fastify, function-based origins are not supported. Defaults to `false`. - **bodyParser** (AuthModuleBodyParserOptions) - Optional - Configures body parsing options. JSON and URL-encoded parsers accept standard Express options plus `enabled?: boolean`. Set `rawBody: true` for `req.rawBody` support. Defaults to default JSON/URL-encoded parsers. - **middleware** ((req, res, next) => void \| Promise) - Optional - Optional middleware function that wraps the Better Auth handler. Useful for request-scoped context like MikroORM's RequestContext. - **disableGlobalAuthGuard** (boolean) - Optional - When true, does not register AuthGuard as a global guard. Manual per-controller registration with `@UseGuards(AuthGuard)` required. Defaults to `false`. - **disableControllers** (boolean) - Optional - When true, does not register any controllers. Use when handling routes manually. Defaults to `false`. ### Returns `DynamicModule` - A NestJS dynamic module configured with authentication middleware and optionally a global guard. ### Throws - Error if `@Hook` providers are detected but Better Auth's `hooks: {}` is not configured - Error if `@DatabaseHook` providers are detected but Better Auth's `databaseHooks: {}` is not configured - Error if function-based `trustedOrigins` are used (not supported in NestJS) ### Example ```typescript // Synchronous configuration AuthModule.forRoot({ auth: myBetterAuthInstance, bodyParser: { json: { limit: "5mb" }, urlencoded: { enabled: true, extended: true }, rawBody: true, }, }) // Or with auth as first argument (deprecated but supported) AuthModule.forRoot(myBetterAuthInstance, { disableTrustedOriginsCors: true, }) ``` ``` -------------------------------- ### User Session Types Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/INDEX.md Defines types for user sessions, with `UserSession` being plugin-aware and recommended, while `BaseUserSession` is a simpler base session. ```typescript UserSession // Plugin-aware session (recommended) BaseUserSession // Base session without plugins ``` -------------------------------- ### Basic API Access with AuthService Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/auth-service.md Demonstrates basic API access to the Better Auth service within a NestJS controller. Requires importing `AuthService` and `fromNodeHeaders`. ```typescript import { Controller, Post, Body, Request } from "@nestjs/common"; import { AuthService } from "@thallesp/nestjs-better-auth"; import { fromNodeHeaders } from "better-auth/node"; import type { Request as ExpressRequest } from "express"; @Controller("users") export class UsersController { constructor(private authService: AuthService) {} @Post("sign-out") async signOut(@Request() req: ExpressRequest) { // Use the API to sign out return this.authService.api.signOut({ headers: fromNodeHeaders(req.headers), }); } } ``` -------------------------------- ### Request Header Integration for Session Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/auth-service.md Illustrates how to integrate request headers for session validation using `AuthService`. The `getSession` method requires headers to be passed, typically converted from Node.js request headers. ```typescript import { Controller, Get, Request } from "@nestjs/common"; import { AuthService } from "@thallesp/nestjs-better-auth"; import { fromNodeHeaders } from "better-auth/node"; import type { Request as ExpressRequest } from "express"; @Controller("profile") export class ProfileController { constructor(private authService: AuthService) {} @Get("me") async getCurrentUser(@Request() req: ExpressRequest) { const session = await this.authService.api.getSession({ headers: fromNodeHeaders(req.headers), }); return session?.user; } } ``` -------------------------------- ### Optional Auth Routes Source: https://github.com/thallesp/nestjs-better-auth/blob/master/examples/nestjs-better-auth-example/README.md These endpoints can be accessed by anyone, but provide a personalized experience if the user is logged in. ```APIDOC ## GET /pokemon/featured/random ### Description Fetches a random Pokemon. If the user is authenticated, the response may be personalized. ### Method GET ### Endpoint /pokemon/featured/random ### Response #### Success Response (200) - Returns a random Pokemon object, potentially personalized for the logged-in user. ``` -------------------------------- ### Hook Decorators Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/INDEX.md Decorators to define and apply authentication and database lifecycle hooks. ```APIDOC ## Hook Decorators ### `@Hook()` - **Purpose**: Marks a provider with custom authentication route hooks. - **Scope**: Class ### `@BeforeHook(path)` - **Purpose**: Defines a hook to be executed before authentication route processing. - **Scope**: Method ### `@AfterHook(path)` - **Purpose**: Defines a hook to be executed after authentication route processing. - **Scope**: Method ### `@DatabaseHook()` - **Purpose**: Marks a provider with database lifecycle hooks. - **Scope**: Class ### `@BeforeCreate(model)` - **Purpose**: Defines a hook to be executed before a record is created. - **Scope**: Method ### `@AfterCreate(model)` - **Purpose**: Defines a hook to be executed after a record is created. - **Scope**: Method ### `@BeforeUpdate(model)` - **Purpose**: Defines a hook to be executed before a record is updated. - **Scope**: Method ### `@AfterUpdate(model)` - **Purpose**: Defines a hook to be executed after a record is updated. - **Scope**: Method ### `@BeforeDelete(model)` - **Purpose**: Defines a hook to be executed before a record is deleted. - **Scope**: Method ### `@AfterDelete(model)` - **Purpose**: Defines a hook to be executed after a record is deleted. - **Scope**: Method ``` -------------------------------- ### Accessing User Accounts via AuthService API Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/auth-service.md Demonstrates how to use the AuthService to retrieve a list of user accounts by calling the `listUserAccounts` API endpoint. Ensure request headers are correctly formatted for Better Auth. ```typescript import { Controller, Get, Request } from "@nestjs/common"; import { AuthService } from "@thallesp/nestjs-better-auth"; import { fromNodeHeaders } from "better-auth/node"; import type { Request as ExpressRequest } from "express"; @Controller("auth") export class AuthController { constructor(private readonly authService: AuthService) {} @Get("accounts") async getAccounts(@Request() req: ExpressRequest) { const accounts = await this.authService.api.listUserAccounts({ headers: fromNodeHeaders(req.headers), }); return { accounts }; } } ``` -------------------------------- ### Configuring Better Auth with Access Control Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/errors.md Configure Better Auth with the admin plugin and access control to resolve the 'userHasPermission API not available' error. This involves creating an access control instance and passing it to the admin plugin. ```typescript import { admin } from "better-auth/plugins/admin"; import { createAccessControl } from "better-auth/plugins/access"; const ac = createAccessControl({ /* ... */ }); const auth = betterAuth({ plugins: [admin({ ac })], }); ``` -------------------------------- ### Configure Auth Module with Base Path Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/endpoints.md Configure the basePath for Better Auth endpoints when initializing the AuthModule. The default is '/api/auth'. ```typescript const auth = betterAuth({ basePath: "/api/auth", // Default // ... other config }); AuthModule.forRoot({ auth }) ``` -------------------------------- ### AfterCreate() Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/decorators.md Method decorator for registering a hook that runs after a record is created. This is useful for performing side effects after a successful creation. Errors in after hooks do not abort the operation. ```APIDOC ## AfterCreate(model: DatabaseHookModel) ### Description Method decorator registering a hook to run after a record is created. ### Parameters #### Path Parameters - **model** (DatabaseHookModel) - Required - The model to hook: `"user"`, `"session"`, `"account"`, or `"verification"` ### Note Errors in after hooks don't abort the operation. ### Related `BeforeCreate()`, `DatabaseHook()` ``` -------------------------------- ### Configure Organization-Level Access Control Source: https://github.com/thallesp/nestjs-better-auth/blob/master/README.md Sets up access control for organization-scoped permissions using Better Auth's organization plugin. Requires an active organization in the session. ```typescript import { betterAuth } from "better-auth"; import { organization } from "better-auth/plugins/organization"; import { createAccessControl } from "better-auth/plugins/access"; const statement = { project: ["create", "share", "update", "delete"], sale: ["create", "read", "update", "delete"], organization: ["update", "delete"], } as const; const ac = createAccessControl(statement); const editor = ac.newRole({ project: ["create", "update"], }); const admin = ac.newRole({ project: ["create", "update", "delete"], organization: ["update"], }); export const auth = betterAuth({ plugins: [ organization({ ac, roles: { editor, admin, }, }), ], }); ``` -------------------------------- ### Correct Usage of @UserHasPermission() Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/errors.md Demonstrates the correct way to use the @UserHasPermission decorator by providing the required 'permission' or 'permissions' option. ```typescript @UserHasPermission({ permission: { project: ["create"] } }) @Get("check") async check() { } ``` -------------------------------- ### Module Declaration with AuthModule.forRoot Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/auth-module.md Declares the AppModule and imports the AuthModule configured synchronously using forRoot. It specifies authentication options and body parsing limits. ```typescript import { Module } from "@nestjs/common"; import { AuthModule } from "@thallesp/nestjs-better-auth"; import { auth } from "./auth"; @Module({ imports: [ AuthModule.forRoot({ auth, bodyParser: { json: { limit: "2mb" }, urlencoded: { limit: "2mb", extended: true }, rawBody: true, }, }), ], }) export class AppModule {} ``` -------------------------------- ### BeforeDelete() Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/decorators.md Method decorator for registering a hook that runs before a record is deleted. It can be used to abort the deletion process. ```APIDOC ## BeforeDelete(model: DatabaseHookModel) ### Description Method decorator registering a hook to run before a record is deleted. ### Parameters #### Path Parameters - **model** (DatabaseHookModel) - Required - The model to hook: `"user"`, `"session"`, `"account"`, or `"verification"` ### Return Value - `false` — abort the deletion - undefined — proceed with deletion ### Related `AfterDelete()`, `DatabaseHook()` ``` -------------------------------- ### OAuth Callback Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/endpoints.md Endpoint for handling callbacks from OAuth providers. ```APIDOC ## GET /api/auth/callback/{provider} ### Description Handles the redirect callback from an OAuth provider after user authorization. ### Method GET ### Endpoint /api/auth/callback/{provider} ### Parameters #### Path Parameters - **provider** (string) - Required - The name of the OAuth provider (e.g., 'google', 'github'). ### Response #### Success Response (200) - **sessionToken** (string) - JWT token for the authenticated session upon successful OAuth flow. #### Response Example { "sessionToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } ``` -------------------------------- ### Body Parser Minimal Configuration Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/configuration.md Uses default body parser settings by omitting the bodyParser configuration. ```typescript AuthModule.forRoot({ auth }) ``` -------------------------------- ### Configure Database Hooks for @DatabaseHook Providers Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/errors.md If you are using the @DatabaseHook() decorator, configure Better Auth with 'databaseHooks: {}' to enable database hook support. This addresses 'Detected @DatabaseHook providers but Better Auth 'databaseHooks' is not configured.' errors. ```typescript const auth = betterAuth({ // ... other config databaseHooks: {}, // Enable database hooks support }); AuthModule.forRoot({ auth }) ``` -------------------------------- ### Public Routes Source: https://github.com/thallesp/nestjs-better-auth/blob/master/examples/nestjs-better-auth-example/README.md These endpoints do not require any authentication and are accessible to all users. ```APIDOC ## GET /pokemon ### Description Lists all available Pokemon. This endpoint fetches data from an external API (PokeAPI). ### Method GET ### Endpoint /pokemon ### Response #### Success Response (200) - Returns a list of Pokemon objects. ``` ```APIDOC ## GET /pokemon/:id ### Description Retrieves a specific Pokemon by its ID or name. This endpoint fetches data from an external API (PokeAPI). ### Method GET ### Endpoint /pokemon/:id ### Parameters #### Path Parameters - **id** (string | number) - Required - The ID or name of the Pokemon to retrieve. ### Response #### Success Response (200) - Returns a Pokemon object. ``` -------------------------------- ### Optional Authentication Route Configuration Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/errors.md Mark a route for optional authentication, allowing access with or without a valid session. The session object will be null if the user is not authenticated. ```typescript @OptionalAuth() @Get("optional") async optionalRoute(@Session() session: UserSession | null) { } ``` -------------------------------- ### Correct Usage of @MemberHasPermission() Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/errors.md Illustrates the proper implementation of the @MemberHasPermission decorator, ensuring the 'permissions' option is always supplied. ```typescript @MemberHasPermission({ permissions: { project: ["create"] } }) @Get("check") async check() { } ``` -------------------------------- ### DatabaseHook() Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/decorators.md Class decorator to mark a provider as containing database lifecycle hook methods. It must be applied to classes that use method decorators like @BeforeCreate(), @AfterCreate(), etc. Usage requires Better Auth to have `databaseHooks: {}` configured. ```APIDOC ## DatabaseHook() ### Description Class decorator marking a provider as containing database lifecycle hook methods. Must be applied to classes using database hook method decorators like `@BeforeCreate()`, `@AfterCreate()`, etc. ### Usage - Apply to class containing database hook methods - Requires Better Auth to have `databaseHooks: {}` configured ### Throws (at module init) - Error — if `@DatabaseHook()` providers detected but `databaseHooks: {}` not configured ### Related `BeforeCreate()`, `AfterCreate()`, `BeforeUpdate()`, `AfterUpdate()`, `BeforeDelete()`, `AfterDelete()` ``` -------------------------------- ### Request Object Extensions Source: https://github.com/thallesp/nestjs-better-auth/blob/master/_autodocs/api-reference/auth-guard.md After `canActivate()` succeeds, the request object is extended with session and user information. ```typescript type Request = ExpressRequest & { session: UserSession | null; user: User | null; } ```