@vynelix/nestjs-multi-auth 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +760 -0
- package/bin/cli.js +152 -0
- package/dist/auth/auth-type.enum.d.ts +22 -0
- package/dist/auth/auth-type.enum.js +32 -0
- package/dist/auth/auth-type.enum.js.map +1 -0
- package/dist/auth/auth.controller.d.ts +70 -0
- package/dist/auth/auth.controller.js +434 -0
- package/dist/auth/auth.controller.js.map +1 -0
- package/dist/auth/auth.module.d.ts +9 -0
- package/dist/auth/auth.module.js +193 -0
- package/dist/auth/auth.module.js.map +1 -0
- package/dist/auth/auth.service.d.ts +180 -0
- package/dist/auth/auth.service.js +695 -0
- package/dist/auth/auth.service.js.map +1 -0
- package/dist/auth/core/auth-mapper.d.ts +6 -0
- package/dist/auth/core/auth-mapper.js +17 -0
- package/dist/auth/core/auth-mapper.js.map +1 -0
- package/dist/auth/core/jwt.strategy.d.ts +13 -0
- package/dist/auth/core/jwt.strategy.js +59 -0
- package/dist/auth/core/jwt.strategy.js.map +1 -0
- package/dist/auth/core/registration.d.ts +3 -0
- package/dist/auth/core/registration.js +60 -0
- package/dist/auth/core/registration.js.map +1 -0
- package/dist/auth/current-user-interface.d.ts +4 -0
- package/dist/auth/current-user-interface.js +4 -0
- package/dist/auth/current-user-interface.js.map +1 -0
- package/dist/auth/current-user.decorator.d.ts +2 -0
- package/dist/auth/current-user.decorator.js +16 -0
- package/dist/auth/current-user.decorator.js.map +1 -0
- package/dist/auth/decorator/current-user.decorator.d.ts +2 -0
- package/dist/auth/decorator/current-user.decorator.js +13 -0
- package/dist/auth/decorator/current-user.decorator.js.map +1 -0
- package/dist/auth/decorator/email-or-phone.decorator.d.ts +2 -0
- package/dist/auth/decorator/email-or-phone.decorator.js +26 -0
- package/dist/auth/decorator/email-or-phone.decorator.js.map +1 -0
- package/dist/auth/decorator/optional.decorator.d.ts +2 -0
- package/dist/auth/decorator/optional.decorator.js +9 -0
- package/dist/auth/decorator/optional.decorator.js.map +1 -0
- package/dist/auth/decorator/public.decorator.d.ts +2 -0
- package/dist/auth/decorator/public.decorator.js +9 -0
- package/dist/auth/decorator/public.decorator.js.map +1 -0
- package/dist/auth/dto/auth-response.dto.d.ts +17 -0
- package/dist/auth/dto/auth-response.dto.js +83 -0
- package/dist/auth/dto/auth-response.dto.js.map +1 -0
- package/dist/auth/dto/identifier-response.dto.d.ts +8 -0
- package/dist/auth/dto/identifier-response.dto.js +46 -0
- package/dist/auth/dto/identifier-response.dto.js.map +1 -0
- package/dist/auth/dto/login.dto.d.ts +11 -0
- package/dist/auth/dto/login.dto.js +68 -0
- package/dist/auth/dto/login.dto.js.map +1 -0
- package/dist/auth/dto/mfa.dto.d.ts +8 -0
- package/dist/auth/dto/mfa.dto.js +51 -0
- package/dist/auth/dto/mfa.dto.js.map +1 -0
- package/dist/auth/dto/oauth-provider-response.dto.d.ts +5 -0
- package/dist/auth/dto/oauth-provider-response.dto.js +30 -0
- package/dist/auth/dto/oauth-provider-response.dto.js.map +1 -0
- package/dist/auth/dto/refresh-token.dto.d.ts +3 -0
- package/dist/auth/dto/refresh-token.dto.js +28 -0
- package/dist/auth/dto/refresh-token.dto.js.map +1 -0
- package/dist/auth/dto/requests/forgot-password.dto.d.ts +5 -0
- package/dist/auth/dto/requests/forgot-password.dto.js +36 -0
- package/dist/auth/dto/requests/forgot-password.dto.js.map +1 -0
- package/dist/auth/dto/requests/login.dto.d.ts +11 -0
- package/dist/auth/dto/requests/login.dto.js +68 -0
- package/dist/auth/dto/requests/login.dto.js.map +1 -0
- package/dist/auth/dto/requests/magic-link.dto.d.ts +6 -0
- package/dist/auth/dto/requests/magic-link.dto.js +33 -0
- package/dist/auth/dto/requests/magic-link.dto.js.map +1 -0
- package/dist/auth/dto/requests/mfa.dto.d.ts +8 -0
- package/dist/auth/dto/requests/mfa.dto.js +51 -0
- package/dist/auth/dto/requests/mfa.dto.js.map +1 -0
- package/dist/auth/dto/requests/refresh-token.dto.d.ts +3 -0
- package/dist/auth/dto/requests/refresh-token.dto.js +29 -0
- package/dist/auth/dto/requests/refresh-token.dto.js.map +1 -0
- package/dist/auth/dto/requests/reset-password.dto.d.ts +5 -0
- package/dist/auth/dto/requests/reset-password.dto.js +36 -0
- package/dist/auth/dto/requests/reset-password.dto.js.map +1 -0
- package/dist/auth/dto/requests/secure-account.dto.d.ts +3 -0
- package/dist/auth/dto/requests/secure-account.dto.js +24 -0
- package/dist/auth/dto/requests/secure-account.dto.js.map +1 -0
- package/dist/auth/dto/requests/signup.dto.d.ts +13 -0
- package/dist/auth/dto/requests/signup.dto.js +70 -0
- package/dist/auth/dto/requests/signup.dto.js.map +1 -0
- package/dist/auth/dto/requests/update-password.dto.d.ts +4 -0
- package/dist/auth/dto/requests/update-password.dto.js +30 -0
- package/dist/auth/dto/requests/update-password.dto.js.map +1 -0
- package/dist/auth/dto/requests/verify.dto.d.ts +7 -0
- package/dist/auth/dto/requests/verify.dto.js +48 -0
- package/dist/auth/dto/requests/verify.dto.js.map +1 -0
- package/dist/auth/dto/responses/auth-response.dto.d.ts +17 -0
- package/dist/auth/dto/responses/auth-response.dto.js +83 -0
- package/dist/auth/dto/responses/auth-response.dto.js.map +1 -0
- package/dist/auth/dto/responses/identifier-response.dto.d.ts +10 -0
- package/dist/auth/dto/responses/identifier-response.dto.js +56 -0
- package/dist/auth/dto/responses/identifier-response.dto.js.map +1 -0
- package/dist/auth/dto/responses/oauth-provider-response.dto.d.ts +10 -0
- package/dist/auth/dto/responses/oauth-provider-response.dto.js +55 -0
- package/dist/auth/dto/responses/oauth-provider-response.dto.js.map +1 -0
- package/dist/auth/dto/signup.dto.d.ts +13 -0
- package/dist/auth/dto/signup.dto.js +70 -0
- package/dist/auth/dto/signup.dto.js.map +1 -0
- package/dist/auth/dto/verify.dto.d.ts +7 -0
- package/dist/auth/dto/verify.dto.js +48 -0
- package/dist/auth/dto/verify.dto.js.map +1 -0
- package/dist/auth/entities/auth-identify.entity.d.ts +33 -0
- package/dist/auth/entities/auth-identify.entity.js +73 -0
- package/dist/auth/entities/auth-identify.entity.js.map +1 -0
- package/dist/auth/entities/auth.entity.d.ts +45 -0
- package/dist/auth/entities/auth.entity.js +129 -0
- package/dist/auth/entities/auth.entity.js.map +1 -0
- package/dist/auth/entities/base.entity.d.ts +6 -0
- package/dist/auth/entities/base.entity.js +41 -0
- package/dist/auth/entities/base.entity.js.map +1 -0
- package/dist/auth/entities/mfa-method.entity.d.ts +23 -0
- package/dist/auth/entities/mfa-method.entity.js +69 -0
- package/dist/auth/entities/mfa-method.entity.js.map +1 -0
- package/dist/auth/entities/oauth-provider.entity.d.ts +38 -0
- package/dist/auth/entities/oauth-provider.entity.js +88 -0
- package/dist/auth/entities/oauth-provider.entity.js.map +1 -0
- package/dist/auth/entities/otp-token.entity.d.ts +22 -0
- package/dist/auth/entities/otp-token.entity.js +61 -0
- package/dist/auth/entities/otp-token.entity.js.map +1 -0
- package/dist/auth/entities/session.entity.d.ts +19 -0
- package/dist/auth/entities/session.entity.js +65 -0
- package/dist/auth/entities/session.entity.js.map +1 -0
- package/dist/auth/enums/auth-type.enum.d.ts +23 -0
- package/dist/auth/enums/auth-type.enum.js +34 -0
- package/dist/auth/enums/auth-type.enum.js.map +1 -0
- package/dist/auth/guards/jwt-auth.guard.d.ts +10 -0
- package/dist/auth/guards/jwt-auth.guard.js +68 -0
- package/dist/auth/guards/jwt-auth.guard.js.map +1 -0
- package/dist/auth/guards/optional-auth.guard.d.ts +8 -0
- package/dist/auth/guards/optional-auth.guard.js +45 -0
- package/dist/auth/guards/optional-auth.guard.js.map +1 -0
- package/dist/auth/guards/ws-jwt-auth.guard.d.ts +0 -0
- package/dist/auth/guards/ws-jwt-auth.guard.js +31 -0
- package/dist/auth/guards/ws-jwt-auth.guard.js.map +1 -0
- package/dist/auth/interfaces/auth-module-async-options.interface.d.ts +7 -0
- package/dist/auth/interfaces/auth-module-async-options.interface.js +3 -0
- package/dist/auth/interfaces/auth-module-async-options.interface.js.map +1 -0
- package/dist/auth/interfaces/auth-module-options.interface.d.ts +132 -0
- package/dist/auth/interfaces/auth-module-options.interface.js +5 -0
- package/dist/auth/interfaces/auth-module-options.interface.js.map +1 -0
- package/dist/auth/interfaces/auth-notification-provider.interface.d.ts +29 -0
- package/dist/auth/interfaces/auth-notification-provider.interface.js +5 -0
- package/dist/auth/interfaces/auth-notification-provider.interface.js.map +1 -0
- package/dist/auth/interfaces/auth-user-service.interface.d.ts +13 -0
- package/dist/auth/interfaces/auth-user-service.interface.js +7 -0
- package/dist/auth/interfaces/auth-user-service.interface.js.map +1 -0
- package/dist/auth/interfaces/current-user-interface.d.ts +4 -0
- package/dist/auth/interfaces/current-user-interface.js +4 -0
- package/dist/auth/interfaces/current-user-interface.js.map +1 -0
- package/dist/auth/interfaces/current-user.decorator.d.ts +2 -0
- package/dist/auth/interfaces/current-user.decorator.js +16 -0
- package/dist/auth/interfaces/current-user.decorator.js.map +1 -0
- package/dist/auth/interfaces/jwt-payload-interface.d.ts +4 -0
- package/dist/auth/interfaces/jwt-payload-interface.js +3 -0
- package/dist/auth/interfaces/jwt-payload-interface.js.map +1 -0
- package/dist/auth/interfaces/oauth-strategy.interface.d.ts +14 -0
- package/dist/auth/interfaces/oauth-strategy.interface.js +3 -0
- package/dist/auth/interfaces/oauth-strategy.interface.js.map +1 -0
- package/dist/auth/jwt-payload-interface.d.ts +4 -0
- package/dist/auth/jwt-payload-interface.js +3 -0
- package/dist/auth/jwt-payload-interface.js.map +1 -0
- package/dist/auth/jwt.strategy.d.ts +13 -0
- package/dist/auth/jwt.strategy.js +60 -0
- package/dist/auth/jwt.strategy.js.map +1 -0
- package/dist/auth/strategies/company.strategy.d.ts +0 -0
- package/dist/auth/strategies/company.strategy.js +1 -0
- package/dist/auth/strategies/company.strategy.js.map +1 -0
- package/dist/auth/strategies/google.strategy.d.ts +7 -0
- package/dist/auth/strategies/google.strategy.js +23 -0
- package/dist/auth/strategies/google.strategy.js.map +1 -0
- package/dist/auth/strategies/local-auth.strategy.d.ts +24 -0
- package/dist/auth/strategies/local-auth.strategy.js +244 -0
- package/dist/auth/strategies/local-auth.strategy.js.map +1 -0
- package/dist/auth/strategies/oauth/apple.strategy.d.ts +27 -0
- package/dist/auth/strategies/oauth/apple.strategy.js +176 -0
- package/dist/auth/strategies/oauth/apple.strategy.js.map +1 -0
- package/dist/auth/strategies/oauth/facebook.strategy.d.ts +24 -0
- package/dist/auth/strategies/oauth/facebook.strategy.js +150 -0
- package/dist/auth/strategies/oauth/facebook.strategy.js.map +1 -0
- package/dist/auth/strategies/oauth/google.strategy.d.ts +25 -0
- package/dist/auth/strategies/oauth/google.strategy.js +225 -0
- package/dist/auth/strategies/oauth/google.strategy.js.map +1 -0
- package/dist/auth/strategies/oauth/oauth-strategy.interface.d.ts +14 -0
- package/dist/auth/strategies/oauth/oauth-strategy.interface.js +3 -0
- package/dist/auth/strategies/oauth/oauth-strategy.interface.js.map +1 -0
- package/dist/auth/strategies/oauth/oauth.strategy.d.ts +25 -0
- package/dist/auth/strategies/oauth/oauth.strategy.js +70 -0
- package/dist/auth/strategies/oauth/oauth.strategy.js.map +1 -0
- package/dist/auth/strategies/otp.strategy.d.ts +7 -0
- package/dist/auth/strategies/otp.strategy.js +23 -0
- package/dist/auth/strategies/otp.strategy.js.map +1 -0
- package/dist/auth/strategies/password.strategy.d.ts +14 -0
- package/dist/auth/strategies/password.strategy.js +130 -0
- package/dist/auth/strategies/password.strategy.js.map +1 -0
- package/dist/auth/utils/duration.util.d.ts +8 -0
- package/dist/auth/utils/duration.util.js +29 -0
- package/dist/auth/utils/duration.util.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/migrations/auth-entities.d.ts +7 -0
- package/dist/migrations/auth-entities.js +18 -0
- package/dist/migrations/auth-entities.js.map +1 -0
- package/dist/migrations/auth-schema.initializer.d.ts +9 -0
- package/dist/migrations/auth-schema.initializer.js +36 -0
- package/dist/migrations/auth-schema.initializer.js.map +1 -0
- package/dist/migrations/auth.migration.v1.d.ts +12 -0
- package/dist/migrations/auth.migration.v1.js +157 -0
- package/dist/migrations/auth.migration.v1.js.map +1 -0
- package/dist/migrations/auth.migration.v2.d.ts +8 -0
- package/dist/migrations/auth.migration.v2.js +39 -0
- package/dist/migrations/auth.migration.v2.js.map +1 -0
- package/dist/migrations/auth.migrations.d.ts +2 -0
- package/dist/migrations/auth.migrations.js +8 -0
- package/dist/migrations/auth.migrations.js.map +1 -0
- package/dist/migrations/migration.runner.d.ts +9 -0
- package/dist/migrations/migration.runner.js +67 -0
- package/dist/migrations/migration.runner.js.map +1 -0
- package/dist/migrations/migration.service.d.ts +9 -0
- package/dist/migrations/migration.service.js +71 -0
- package/dist/migrations/migration.service.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +82 -0
package/README.md
ADDED
|
@@ -0,0 +1,760 @@
|
|
|
1
|
+
# NestJS Multi-Auth
|
|
2
|
+
|
|
3
|
+
A flexible, decoupled, and production-ready authentication library for NestJS applications. `nestjs-multi-auth` supports JWT/Refresh token rotation, dynamic configuration, and multiple authentication transports (Cookies and Bearer tokens), while remaining completely agnostic of your application's specific `User` entity or ORM structure.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Identity-Only (Firebase Style)**: Pure authentication and session management. Agnostic of your application's user profiles and database structure.
|
|
8
|
+
- **Grouped Identities**: Multiple login methods (Google, Password, etc.) are consolidated under a single, opaque `uid`.
|
|
9
|
+
- **Account Linking**: Link additional auth methods (e.g., Google, Email, Phone) to an existing account under the same `uid`.
|
|
10
|
+
- **Multiple OAuth Providers**: Link multiple social accounts (e.g., Google AND Facebook) to a single identity simultaneously.
|
|
11
|
+
- **MFA/2FA Ready**: Built-in support for TOTP-based Multi-Factor Authentication (e.g., Google Authenticator).
|
|
12
|
+
- **Magic Links**: Passwordless email login via a signed, time-limited magic link — no passwords required.
|
|
13
|
+
- **Password Management**: Built-in flows for forgot password (email/phone/username), reset via OTP, in-session password update, and a security lock endpoint.
|
|
14
|
+
- **Security Alerts**: Sends a "Secure My Account" link via email when a password change is detected from an unfamiliar device.
|
|
15
|
+
- **Secure by Default**: Automatically registers a global authentication guard.
|
|
16
|
+
- **Dynamic Configuration**: Configure JWT secrets, expiration times, and transport preferences both synchronously and asynchronously.
|
|
17
|
+
- **Granular Strategy Selection**: Enable individual authentication methods (Email, Phone, Username, Google, Facebook, Apple).
|
|
18
|
+
- **Flexible Phone Auth**: Choose whether phone-based authentication requires a password or is password-less by default.
|
|
19
|
+
- **Phone Number Prefix Validation**: Restrict authentication to specific country codes or phone formats (e.g., `['+234', '+44']`).
|
|
20
|
+
- **Multiple Auth Transports**: Supports HTTP-only Cookies, JSON body (Bearer token), or both.
|
|
21
|
+
- **Token Rotation**: Built-in `/refresh` and `/logout` endpoints with automatic token rotation.
|
|
22
|
+
- **Session Tracking**: Tracks IP and User Agent for basic session security.
|
|
23
|
+
- **Built-in Rate Limiting**: Configurable throttling on all auth endpoints via `@nestjs/throttler`.
|
|
24
|
+
- **Account Management**: Built-in endpoints for viewing and deleting auth methods or entire accounts.
|
|
25
|
+
- **Production Ready**: 10/10 code quality rating with standardized security patterns (e.g., Node.js built-in `crypto` for secure UUID generation).
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Testing & Quality
|
|
30
|
+
|
|
31
|
+
`nestjs-multi-auth` is built with a focus on reliability and code quality.
|
|
32
|
+
|
|
33
|
+
- **100% Passing Tests**: Comprehensive suite of unit and integration tests covering all strategies, MFA logic, and module compilation.
|
|
34
|
+
- **Robust Infrastructure**: Integration tests use standardized mocking for `DataSource` and `ThrottlerGuard`, ensuring stable and predictable verification.
|
|
35
|
+
- **Standardized Security**: Follows modern security best practices, including secure random value generation using Node.js's native `crypto` module.
|
|
36
|
+
|
|
37
|
+
To run the tests locally:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm test
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
Install the library using npm:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npm install nestjs-multi-auth
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Ensure you have the required peer dependencies installed in your NestJS project:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npm install @nestjs/passport @nestjs/jwt passport passport-jwt class-validator bcrypt typeorm
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Quick Start
|
|
62
|
+
|
|
63
|
+
### 1. Register the `AuthModule`
|
|
64
|
+
|
|
65
|
+
#### Synchronous Registration
|
|
66
|
+
|
|
67
|
+
Import and configure the `AuthModule` in your root `AppModule`. No external service implementation is required!
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
// src/app.module.ts
|
|
71
|
+
import { Module } from '@nestjs/common';
|
|
72
|
+
import { AuthModule, AuthTransport, AuthStrategy } from 'nestjs-multi-auth';
|
|
73
|
+
|
|
74
|
+
@Module({
|
|
75
|
+
imports: [
|
|
76
|
+
AuthModule.register({
|
|
77
|
+
jwtSecret: process.env.JWT_SECRET,
|
|
78
|
+
jwtRefreshSecret: process.env.JWT_REFRESH_SECRET,
|
|
79
|
+
|
|
80
|
+
// Optional: defaults to [AuthTransport.BEARER]
|
|
81
|
+
transport: [AuthTransport.COOKIE, AuthTransport.BEARER],
|
|
82
|
+
|
|
83
|
+
// Optional: Enable individual strategies
|
|
84
|
+
enabledStrategies: [
|
|
85
|
+
AuthStrategy.EMAIL,
|
|
86
|
+
AuthStrategy.GOOGLE,
|
|
87
|
+
AuthStrategy.PHONE
|
|
88
|
+
],
|
|
89
|
+
|
|
90
|
+
// Required for Google strategy
|
|
91
|
+
googleClientId: process.env.GOOGLE_CLIENT_ID,
|
|
92
|
+
|
|
93
|
+
// Required for Facebook strategy
|
|
94
|
+
facebookAppId: process.env.FACEBOOK_APP_ID,
|
|
95
|
+
facebookAppSecret: process.env.FACEBOOK_APP_SECRET,
|
|
96
|
+
|
|
97
|
+
// Required for Apple strategy
|
|
98
|
+
appleClientId: process.env.APPLE_CLIENT_ID,
|
|
99
|
+
appleTeamId: process.env.APPLE_TEAM_ID,
|
|
100
|
+
|
|
101
|
+
// Optional: If strategy PHONE is enabled, defaults to false
|
|
102
|
+
phoneRequiresPassword: true,
|
|
103
|
+
|
|
104
|
+
// Optional: List of allowed phone number prefixes (e.g. ['+234', '+44']).
|
|
105
|
+
allowedPhonePrefixes: ['+234', '+44'],
|
|
106
|
+
|
|
107
|
+
// Optional: App name shown in TOTP authenticator apps
|
|
108
|
+
appName: 'MyApp',
|
|
109
|
+
|
|
110
|
+
// Optional: Rate limiting (defaults: limit=10, ttl=60s)
|
|
111
|
+
throttlerLimit: 10,
|
|
112
|
+
throttlerTtl: 60,
|
|
113
|
+
|
|
114
|
+
// Optional: defaults to false.
|
|
115
|
+
// disableController: true,
|
|
116
|
+
// disableGlobalGuard: true,
|
|
117
|
+
// disableThrottler: true,
|
|
118
|
+
|
|
119
|
+
// Optional: Durations and Intervals
|
|
120
|
+
otpExpiresIn: 15, // 15 minutes
|
|
121
|
+
otpResendInterval: 60, // 60 seconds
|
|
122
|
+
accessTokenExpiresIn: '15m', // Access token
|
|
123
|
+
refreshTokenExpiresIn: '7d', // Refresh token & Session
|
|
124
|
+
|
|
125
|
+
// Required for Magic Links and Security Alert emails
|
|
126
|
+
frontendUrl: 'https://myapp.com',
|
|
127
|
+
|
|
128
|
+
// Optional: Run DB migrations automatically on startup
|
|
129
|
+
autoMigrate: true,
|
|
130
|
+
}),
|
|
131
|
+
],
|
|
132
|
+
})
|
|
133
|
+
export class AppModule {}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
#### Asynchronous Registration (`forRootAsync`)
|
|
137
|
+
|
|
138
|
+
Use `AuthModule.forRootAsync()` when your configuration depends on other providers (e.g., a `ConfigService`):
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
import { Module } from '@nestjs/common';
|
|
142
|
+
import { ConfigModule, ConfigService } from '@nestjs/config';
|
|
143
|
+
import { AuthModule } from 'nestjs-multi-auth';
|
|
144
|
+
|
|
145
|
+
@Module({
|
|
146
|
+
imports: [
|
|
147
|
+
ConfigModule.forRoot(),
|
|
148
|
+
AuthModule.forRootAsync({
|
|
149
|
+
imports: [ConfigModule],
|
|
150
|
+
inject: [ConfigService],
|
|
151
|
+
useFactory: async (config: ConfigService) => ({
|
|
152
|
+
jwtSecret: config.get('JWT_SECRET'),
|
|
153
|
+
jwtRefreshSecret: config.get('JWT_REFRESH_SECRET'),
|
|
154
|
+
appName: config.get('APP_NAME'),
|
|
155
|
+
}),
|
|
156
|
+
}),
|
|
157
|
+
],
|
|
158
|
+
})
|
|
159
|
+
export class AppModule {}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Identity Provider (Firebase Style)
|
|
165
|
+
|
|
166
|
+
The library is a pure **Identity Provider**. It manages credentials and sessions but knows nothing about your application's user profiles.
|
|
167
|
+
|
|
168
|
+
1. **Identity (UID)**: Every person has a unique `uid` managed by the library.
|
|
169
|
+
2. **Multiple Auth Methods**: One `uid` can be linked to multiple authentication methods (Google, Password, etc.).
|
|
170
|
+
3. **Application Users**: Your application creates its own `User` table and links it to the library's `uid`.
|
|
171
|
+
|
|
172
|
+
### Example Integration
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
@Controller('users')
|
|
176
|
+
export class UserController {
|
|
177
|
+
@Post('profile')
|
|
178
|
+
@UseGuards(JwtAuthGuard)
|
|
179
|
+
async createProfile(@Req() req, @Body() dto) {
|
|
180
|
+
// req.user contains { uid: string, sessionId: string }
|
|
181
|
+
const { uid } = req.user;
|
|
182
|
+
|
|
183
|
+
return this.userService.create({
|
|
184
|
+
authUid: uid,
|
|
185
|
+
...dto
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
// Basic Registration
|
|
193
|
+
AuthModule.register({
|
|
194
|
+
jwtSecret: process.env.JWT_SECRET,
|
|
195
|
+
jwtRefreshSecret: process.env.JWT_REFRESH_SECRET,
|
|
196
|
+
// No user service required!
|
|
197
|
+
})
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### The `AuthCredential` Type
|
|
201
|
+
|
|
202
|
+
When a request is authenticated, `request.user` is populated with the following shape, exported as `AuthCredential`:
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
import type { AuthCredential } from 'nestjs-multi-auth';
|
|
206
|
+
|
|
207
|
+
// AuthCredential = { uid: string; sessionId: string }
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Identity Verification (OTPs) & MFA
|
|
213
|
+
|
|
214
|
+
The library includes a pluggable verification system to confirm identities via Email or Phone. OTPs are triggered in the following scenarios:
|
|
215
|
+
|
|
216
|
+
1. **Multi-Factor Authentication (2FA)**: If a user has any enabled MFA methods (TOTP, Email, SMS), verification is **always** required during login and signup.
|
|
217
|
+
2. **Passwordless Authentication**: When using a local method (`EMAIL`, `PHONE`, `USERNAME`) **without a password**, an OTP is always sent as the primary credential.
|
|
218
|
+
3. **Mandatory Verification**: If `verificationRequired: true` is configured, verification is enforced for any **unverified** identity.
|
|
219
|
+
- **OAuth Note**: Verified OAuth providers (e.g., Google with `email_verified: true`) automatically bypass this unless 2FA is enabled.
|
|
220
|
+
- **Identifier-Level**: Verification is tracked per-identifier. Successful verification marks the specific method and all its identifiers as verified.
|
|
221
|
+
|
|
222
|
+
#### Smart Delivery (Cross-Auth)
|
|
223
|
+
If a user authenticates via a non-verifiable method (like a **USERNAME**), the system automatically:
|
|
224
|
+
- Searches all linked identifiers across **all** authentication methods for that user.
|
|
225
|
+
- Prioritizes verified **EMAIL** or **PHONE** numbers for delivery.
|
|
226
|
+
- Marks all identifiers for the current auth method as verified once the OTP is confirmed.
|
|
227
|
+
|
|
228
|
+
### 1. Implement `AuthNotificationProvider`
|
|
229
|
+
|
|
230
|
+
Create a service to deliver the verification codes (SMS or Email). You can use any service, such as [notifyc-nestjs](https://github.com/IsaiahTek/notifyc-nestjs):
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
import { AuthNotificationProvider } from 'nestjs-multi-auth';
|
|
234
|
+
import { NotifycService } from 'notifyc-nestjs';
|
|
235
|
+
|
|
236
|
+
@Injectable()
|
|
237
|
+
export class MyNotificationProvider implements AuthNotificationProvider {
|
|
238
|
+
constructor(private notifyc: NotifycService) {}
|
|
239
|
+
|
|
240
|
+
async sendVerificationCode(to: string, code: string, type: 'email' | 'phone') {
|
|
241
|
+
await this.notifyc.send({
|
|
242
|
+
to,
|
|
243
|
+
subject: 'Your Verification Code',
|
|
244
|
+
message: `Your code is: ${code}`,
|
|
245
|
+
transport: type === 'email' ? 'SMTP' : 'SMS',
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### 2. Configure the Module
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
AuthModule.register({
|
|
255
|
+
// ... other options
|
|
256
|
+
notificationProvider: MyNotificationProvider,
|
|
257
|
+
verificationRequired: true, // If true, login is blocked until verified
|
|
258
|
+
|
|
259
|
+
// Pass the module that provides NotifycService
|
|
260
|
+
imports: [NotifycModule],
|
|
261
|
+
})
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### 3. Verification Endpoints
|
|
265
|
+
|
|
266
|
+
- `POST /auth/verify`: Accepts `{ uid, code }`. Upon success, it sets `isVerified: true` and **issues the final Access and Refresh tokens** (completing the login/signup flow).
|
|
267
|
+
- `POST /auth/resend-verification`: Accepts `{ uid }`. Triggers a new code via the provider.
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## Magic Links
|
|
272
|
+
|
|
273
|
+
Magic links provide a fully **passwordless login experience** via email. The library generates a short-lived, cryptographically signed token, constructs a callback URL, and delivers it to the user via your `notificationProvider`. No password is ever exchanged.
|
|
274
|
+
|
|
275
|
+
### How It Works
|
|
276
|
+
|
|
277
|
+
1. **Request**: The client sends the user's email to `POST /auth/magic-link`. The library generates a signed token (valid for 15 minutes), saves a hashed copy, and calls `notificationProvider.sendMagicLink(email, link)` with the full callback URL.
|
|
278
|
+
2. **Click**: The user clicks the link in their inbox, which navigates them to `frontendUrl + /auth/magic-callback?token=<token>&email=<email>`.
|
|
279
|
+
3. **Verify**: Your frontend (or a redirect handler) calls `GET /auth/magic-callback?token=<token>`. The library validates the token, logs the user in, and returns the standard access + refresh tokens.
|
|
280
|
+
|
|
281
|
+
### 1. Implement `sendMagicLink` in your Provider
|
|
282
|
+
|
|
283
|
+
Add the optional `sendMagicLink` method to your existing `AuthNotificationProvider`:
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
import { AuthNotificationProvider } from 'nestjs-multi-auth';
|
|
287
|
+
|
|
288
|
+
@Injectable()
|
|
289
|
+
export class MyNotificationProvider implements AuthNotificationProvider {
|
|
290
|
+
constructor(private mailer: MailerService) {}
|
|
291
|
+
|
|
292
|
+
// Required for OTP / verification codes
|
|
293
|
+
async sendVerificationCode(to: string, code: string, type: 'email' | 'phone') {
|
|
294
|
+
await this.mailer.send({ to, subject: 'Your Code', text: `Code: ${code}` });
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Optional — enables Magic Link login
|
|
298
|
+
async sendMagicLink(to: string, link: string) {
|
|
299
|
+
await this.mailer.send({
|
|
300
|
+
to,
|
|
301
|
+
subject: 'Your Magic Login Link',
|
|
302
|
+
html: `<p>Click <a href="${link}">here</a> to log in. This link expires in 15 minutes.</p>`,
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### 2. Configure `frontendUrl`
|
|
309
|
+
|
|
310
|
+
The library constructs the magic link as:
|
|
311
|
+
|
|
312
|
+
```
|
|
313
|
+
{frontendUrl}/auth/magic-callback?token={token}&email={email}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
Set this in your module configuration:
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
AuthModule.register({
|
|
320
|
+
// ...
|
|
321
|
+
frontendUrl: 'https://myapp.com',
|
|
322
|
+
notificationProvider: MyNotificationProvider,
|
|
323
|
+
})
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### 3. Magic Link Endpoints
|
|
327
|
+
|
|
328
|
+
| Method | Endpoint | Description |
|
|
329
|
+
|--------|----------|-------------|
|
|
330
|
+
| `POST` | `/auth/magic-link` | Request a magic login link for an email address. |
|
|
331
|
+
| `GET` | `/auth/magic-callback?token=<token>` | Validate the token and issue access + refresh tokens. |
|
|
332
|
+
|
|
333
|
+
> [!NOTE]
|
|
334
|
+
> Only email addresses that already have an account in the system can receive a magic link. If the email is not recognized, a `400 Bad Request` is returned.
|
|
335
|
+
|
|
336
|
+
> [!TIP]
|
|
337
|
+
> Magic links are **single-use** and expire after 15 minutes (controlled by `otpExpiresIn`). The callback endpoint respects your configured `transport` (cookie or bearer), just like `signin`.
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
## Password Management
|
|
342
|
+
|
|
343
|
+
The library provides a complete, secure password lifecycle — from forgotten passwords to in-session updates and emergency account lockdowns.
|
|
344
|
+
|
|
345
|
+
### Forgot Password
|
|
346
|
+
|
|
347
|
+
Initiate a password reset by supplying one identifying field (email, phone, or username). A 6-digit OTP is sent via your `notificationProvider`.
|
|
348
|
+
|
|
349
|
+
```
|
|
350
|
+
POST /auth/forgot-password
|
|
351
|
+
```
|
|
352
|
+
```json
|
|
353
|
+
{ "email": "user@example.com" }
|
|
354
|
+
// OR
|
|
355
|
+
{ "phone": "+2348011223344" }
|
|
356
|
+
// OR
|
|
357
|
+
{ "username": "johndoe" }
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
> [!NOTE]
|
|
361
|
+
> The response is always `{ "message": "If an account exists, a reset code has been sent." }` regardless of whether the account was found, preventing user enumeration.
|
|
362
|
+
|
|
363
|
+
### Reset Password
|
|
364
|
+
|
|
365
|
+
Submit the OTP received via email/SMS together with the new password.
|
|
366
|
+
|
|
367
|
+
```
|
|
368
|
+
POST /auth/reset-password
|
|
369
|
+
```
|
|
370
|
+
```json
|
|
371
|
+
{
|
|
372
|
+
"uid": "<uid-from-forgot-password-response>",
|
|
373
|
+
"code": "123456",
|
|
374
|
+
"newPassword": "newSecurePassword!"
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
On success, **all active sessions are invalidated** as a security measure.
|
|
379
|
+
|
|
380
|
+
### Update Password (Authenticated)
|
|
381
|
+
|
|
382
|
+
Change the password for a currently logged-in user. Requires the current password.
|
|
383
|
+
|
|
384
|
+
```
|
|
385
|
+
PATCH /auth/password
|
|
386
|
+
Authorization: Bearer <access_token>
|
|
387
|
+
```
|
|
388
|
+
```json
|
|
389
|
+
{
|
|
390
|
+
"currentPassword": "oldPassword123",
|
|
391
|
+
"newPassword": "newPassword456"
|
|
392
|
+
}
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
If `sendPasswordChangedNotification` is implemented in your provider, the library will automatically send a security alert email containing the request IP, user agent, and a one-click "Secure My Account" link.
|
|
396
|
+
|
|
397
|
+
### Secure Account (Emergency Lock)
|
|
398
|
+
|
|
399
|
+
When a user clicks the "Secure My Account" link in a security alert email, it calls this endpoint to immediately lock all auth methods and invalidate all sessions.
|
|
400
|
+
|
|
401
|
+
```
|
|
402
|
+
POST /auth/secure-account?uid=<uid>
|
|
403
|
+
```
|
|
404
|
+
```json
|
|
405
|
+
{ "token": "<token-from-email-link>" }
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
After locking, the user must reset their password to regain access.
|
|
409
|
+
|
|
410
|
+
### Implement `sendPasswordChangedNotification` in your Provider
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
@Injectable()
|
|
414
|
+
export class MyNotificationProvider implements AuthNotificationProvider {
|
|
415
|
+
async sendVerificationCode(to: string, code: string, type: 'email' | 'phone') { /* ... */ }
|
|
416
|
+
|
|
417
|
+
// Optional — triggers on PATCH /auth/password
|
|
418
|
+
async sendPasswordChangedNotification(to: string, context: {
|
|
419
|
+
ip: string;
|
|
420
|
+
userAgent: string;
|
|
421
|
+
secureAccountLink: string;
|
|
422
|
+
}) {
|
|
423
|
+
await this.mailer.send({
|
|
424
|
+
to,
|
|
425
|
+
subject: 'Your password was changed',
|
|
426
|
+
html: `
|
|
427
|
+
<p>Your password was recently changed from IP <strong>${context.ip}</strong>.</p>
|
|
428
|
+
<p>If this wasn't you, <a href="${context.secureAccountLink}">secure your account immediately</a>.</p>
|
|
429
|
+
`,
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
437
|
+
## Multi-Factor Authentication (TOTP)
|
|
438
|
+
|
|
439
|
+
The library has built-in support for TOTP-based 2FA (e.g., Google Authenticator, Authy). Configure the display name shown in authenticator apps with the `appName` option.
|
|
440
|
+
|
|
441
|
+
### Enrollment Flow
|
|
442
|
+
|
|
443
|
+
1. **Enroll**: Call `POST /auth/mfa/enroll` with `{ type: "TOTP" }`. Returns a `secret` and an `otpauth` URI that you render as a QR code for the user to scan.
|
|
444
|
+
2. **Activate**: Call `POST /auth/mfa/activate` with `{ type: "TOTP", code: "<6-digit-code>" }` to verify a successful scan and enable 2FA.
|
|
445
|
+
|
|
446
|
+
Once activated, subsequent logins will return `{ mfaRequired: true }` instead of tokens. The client should then prompt the user for their TOTP code and complete the flow.
|
|
447
|
+
|
|
448
|
+
---
|
|
449
|
+
|
|
450
|
+
## Account Linking & Multi-OAuth
|
|
451
|
+
|
|
452
|
+
A logged-in user can link additional authentication methods to their existing account (same `uid`). This includes both local methods (Email/Password, Phone) and multiple social accounts simultaneously (e.g., linking both Google AND Facebook to the same user).
|
|
453
|
+
|
|
454
|
+
```
|
|
455
|
+
POST /auth/link
|
|
456
|
+
Authorization: Bearer <access_token>
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
The request body follows the same shape as `POST /auth/signup`. The new credential will be linked to the same identity as the current session.
|
|
460
|
+
|
|
461
|
+
- **Unified Identity**: All linked methods share the same `uid`, but have their own `authId`.
|
|
462
|
+
- **Social Linking**: Connect multiple OAuth providers to a single account without creating separate identities.
|
|
463
|
+
- **Verification**: If verification is required, linked methods must be verified independently before they can be used for login.
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
|
|
467
|
+
## Guards and Decorators
|
|
468
|
+
|
|
469
|
+
This library is **Secure by Default**. Once registered, every endpoint in your application will require a valid JWT unless you specify otherwise.
|
|
470
|
+
|
|
471
|
+
### 1. `@Public()`
|
|
472
|
+
Use the `@Public()` decorator to bypass authentication for specific controllers or individual routes.
|
|
473
|
+
|
|
474
|
+
```typescript
|
|
475
|
+
import { Public } from 'nestjs-multi-auth';
|
|
476
|
+
|
|
477
|
+
@Public()
|
|
478
|
+
@Controller('status')
|
|
479
|
+
export class StatusController {}
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
### 2. `@OptionalAuth()`
|
|
483
|
+
Use the `@OptionalAuth()` decorator when you want a route to attempt authentication but still allow guest access. If a valid token is provided, `request.user` will be populated; otherwise, it will be `null` and the request will proceed.
|
|
484
|
+
|
|
485
|
+
```typescript
|
|
486
|
+
import { OptionalAuth, CurrentAuth } from 'nestjs-multi-auth';
|
|
487
|
+
|
|
488
|
+
@OptionalAuth()
|
|
489
|
+
@Get('feed')
|
|
490
|
+
getFeed(@CurrentAuth() user: AuthCredential | null) {
|
|
491
|
+
return user ? this.getPersonalizedFeed(user) : this.getGuestFeed();
|
|
492
|
+
}
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
### 3. `@CurrentAuth()`
|
|
496
|
+
Use the `@CurrentAuth()` decorator to conveniently inject the authenticated user's credential into your route handler.
|
|
497
|
+
|
|
498
|
+
```typescript
|
|
499
|
+
import { CurrentAuth } from 'nestjs-multi-auth';
|
|
500
|
+
import type { AuthCredential } from 'nestjs-multi-auth';
|
|
501
|
+
|
|
502
|
+
@Get('profile')
|
|
503
|
+
getProfile(@CurrentAuth() user: AuthCredential) {
|
|
504
|
+
return this.userService.findByUid(user.uid);
|
|
505
|
+
}
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
### 4. Manual Guards
|
|
509
|
+
If you've disabled the global guard via `disableGlobalGuard: true`, you can apply the guards manually:
|
|
510
|
+
|
|
511
|
+
```typescript
|
|
512
|
+
import { UseGuards } from '@nestjs/common';
|
|
513
|
+
import { JwtAuthGuard } from 'nestjs-multi-auth';
|
|
514
|
+
|
|
515
|
+
@UseGuards(JwtAuthGuard)
|
|
516
|
+
@Controller('profile')
|
|
517
|
+
export class ProfileController {}
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
> [!WARNING]
|
|
521
|
+
> If `disableGlobalGuard: true` is configured and no manual guard is applied, decorators like `@CurrentAuth()` will return `undefined` because the authentication logic never runs for that request.
|
|
522
|
+
|
|
523
|
+
---
|
|
524
|
+
|
|
525
|
+
## Auth Transports (Cookie vs Bearer)
|
|
526
|
+
|
|
527
|
+
The library provides extreme flexibility for how your front-end interacts with tokens. You must specify your `transport` array in the `AuthModule.register()` configuration.
|
|
528
|
+
|
|
529
|
+
- `AuthTransport.COOKIE`: Tokens are automatically set as secure, HTTP-only `Set-Cookie` headers upon Login/Signup. The `/refresh` endpoint automatically reads the cookie (`refresh_token`) and issues new cookies. The `/logout` endpoint automatically clears these cookies. **Zero manual token management is required on your frontend client.**
|
|
530
|
+
- `AuthTransport.BEARER`: Tokens are returned in the JSON response body (`tokens: { accessToken, refreshToken }`). The `/refresh` and `/logout` endpoints seamlessly accept a JSON payload containing `{"refreshToken": "..."}`, or gracefully fallback to checking the `Authorization: Bearer <token>` header.
|
|
531
|
+
- Combine both by passing `transport: [AuthTransport.COOKIE, AuthTransport.BEARER]` to set cookies **and** return tokens in the JSON body simultaneously.
|
|
532
|
+
|
|
533
|
+
---
|
|
534
|
+
|
|
535
|
+
## Provided Endpoints
|
|
536
|
+
|
|
537
|
+
The library automatically mounts the following endpoints under the `/auth` prefix:
|
|
538
|
+
|
|
539
|
+
| Method | Endpoint | Auth Required | Payload | Description |
|
|
540
|
+
|--------|----------|:---:|:---|-------------|
|
|
541
|
+
| `POST` | `/auth/signup` | ❌ | `SignupDto` | Register a new identity. |
|
|
542
|
+
| `POST` | `/auth/signin` | ❌ | `LoginDto` | Authenticate and receive tokens. |
|
|
543
|
+
| `POST` | `/auth/verify` | ❌ | `VerifyDto` | Submit an OTP to complete verification. |
|
|
544
|
+
| `POST` | `/auth/resend-verification` | ❌ | `ResendVerificationDto` | Resend the OTP code. |
|
|
545
|
+
| `POST` | `/auth/forgot-password` | ❌ | `ForgotPasswordDto` | Request a password reset OTP via email/phone/username. |
|
|
546
|
+
| `POST` | `/auth/reset-password` | ❌ | `ResetPasswordDto` | Reset password using the OTP code. |
|
|
547
|
+
| `PATCH` | `/auth/password` | ✅ | `UpdatePasswordDto` | Update password for the current authenticated session. |
|
|
548
|
+
| `POST` | `/auth/secure-account?uid=` | ❌ | `SecureAccountDto` | Lock account via a one-click security email link. |
|
|
549
|
+
| `POST` | `/auth/magic-link` | ❌ | `MagicLinkRequestDto` | Request a magic login link for an email address. |
|
|
550
|
+
| `GET` | `/auth/magic-callback?token=` | ❌ | — | Verify the magic link token and issue session tokens. |
|
|
551
|
+
| `POST` | `/auth/refresh` | ❌ | `RefreshTokenDto` | Rotate the access token using a refresh token. |
|
|
552
|
+
| `POST` | `/auth/logout` | ❌ | `RefreshTokenDto` | Invalidate the current session. |
|
|
553
|
+
| `POST` | `/auth/link` | ✅ | `SignupDto` | Link a new auth method to the current account. |
|
|
554
|
+
| `POST` | `/auth/mfa/enroll` | ✅ | `EnrollMfaDto` | Begin TOTP MFA enrollment. |
|
|
555
|
+
| `POST` | `/auth/mfa/activate` | ✅ | `ActivateMfaDto` | Confirm TOTP setup with a live code. |
|
|
556
|
+
| `GET` | `/auth` | Optional | — | List all auth identities (admin/debug). |
|
|
557
|
+
| `GET` | `/auth/me` | ✅ | — | View current identity details. |
|
|
558
|
+
| `GET` | `/auth/me/methods` | ✅ | — | View all auth methods for the current user. |
|
|
559
|
+
| `DELETE` | `/auth/account` | ✅ | — | Delete the user's account and all data. |
|
|
560
|
+
| `DELETE` | `/auth/method/:id` | ✅ | — | Delete a specific auth method by ID. |
|
|
561
|
+
|
|
562
|
+
---
|
|
563
|
+
|
|
564
|
+
## Payload Definitions (DTOs)
|
|
565
|
+
|
|
566
|
+
These DTOs define the expected request body for each endpoint.
|
|
567
|
+
|
|
568
|
+
### `SignupDto` / `LoginDto`
|
|
569
|
+
Used for both registration (`/auth/signup`) and authentication (`/auth/signin`).
|
|
570
|
+
|
|
571
|
+
| Field | Type | Required | Description |
|
|
572
|
+
|---|---|---|---|
|
|
573
|
+
| `method` | `AuthStrategy` | ✅ | The authentication strategy (e.g., `EMAIL`, `PHONE`, `GOOGLE`). |
|
|
574
|
+
| `provider` | `OAuthProviderType` | ❌ | Required if `method` is `OAUTH` or a social strategy. |
|
|
575
|
+
| `email` | `string` | ❌ | Required if `method` is `EMAIL`. |
|
|
576
|
+
| `phone` | `string` | ❌ | Required if `method` is `PHONE`. |
|
|
577
|
+
| `username` | `string` | ❌ | Required if `method` is `USERNAME`. |
|
|
578
|
+
| `password` | `string` | ❌ | User's password (min 6 chars). |
|
|
579
|
+
| `token` | `string` | ❌ | OAuth token or verification token for automated flows. |
|
|
580
|
+
|
|
581
|
+
### `VerifyDto`
|
|
582
|
+
Used to verify an identity with a one-time code (`/auth/verify`).
|
|
583
|
+
|
|
584
|
+
| Field | Type | Required | Description |
|
|
585
|
+
|---|---|---|---|
|
|
586
|
+
| `uid` | `string` | ✅ | The unique identity ID (UUID) being verified. |
|
|
587
|
+
| `code` | `string` | ✅ | The 6-digit verification code sent via Email or SMS. |
|
|
588
|
+
|
|
589
|
+
### `ResendVerificationDto`
|
|
590
|
+
Used to request a new verification code (`/auth/resend-verification`).
|
|
591
|
+
|
|
592
|
+
| Field | Type | Required | Description |
|
|
593
|
+
|---|---|---|---|
|
|
594
|
+
| `uid` | `string` | ✅ | The unique identity ID (UUID) to resend the code for. |
|
|
595
|
+
|
|
596
|
+
### `ForgotPasswordDto`
|
|
597
|
+
Used to initiate a password reset (`/auth/forgot-password`).
|
|
598
|
+
|
|
599
|
+
| Field | Type | Required | Description |
|
|
600
|
+
|---|---|---|---|
|
|
601
|
+
| `email` | `string` | ❌ | Email address of the account. |
|
|
602
|
+
| `phone` | `string` | ❌ | Phone number of the account. |
|
|
603
|
+
| `username` | `string` | ❌ | Username of the account. |
|
|
604
|
+
|
|
605
|
+
> At least one of `email`, `phone`, or `username` must be provided.
|
|
606
|
+
|
|
607
|
+
### `ResetPasswordDto`
|
|
608
|
+
Used to reset the password after receiving an OTP (`/auth/reset-password`).
|
|
609
|
+
|
|
610
|
+
| Field | Type | Required | Description |
|
|
611
|
+
|---|---|---|---|
|
|
612
|
+
| `uid` | `string` | ✅ | The unique identity ID. |
|
|
613
|
+
| `code` | `string` | ✅ | The 6-digit OTP code received via email/SMS. |
|
|
614
|
+
| `newPassword` | `string` | ✅ | The new password (min 6 chars). |
|
|
615
|
+
|
|
616
|
+
### `UpdatePasswordDto`
|
|
617
|
+
Used to change the password for an authenticated user (`PATCH /auth/password`).
|
|
618
|
+
|
|
619
|
+
| Field | Type | Required | Description |
|
|
620
|
+
|---|---|---|---|
|
|
621
|
+
| `currentPassword` | `string` | ✅ | The user's current password. |
|
|
622
|
+
| `newPassword` | `string` | ✅ | The new password (min 6 chars). |
|
|
623
|
+
|
|
624
|
+
### `SecureAccountDto`
|
|
625
|
+
Used to lock an account via a security email link (`/auth/secure-account?uid=`).
|
|
626
|
+
|
|
627
|
+
| Field | Type | Required | Description |
|
|
628
|
+
|---|---|---|---|
|
|
629
|
+
| `token` | `string` | ✅ | The signed security token included in the alert email link. |
|
|
630
|
+
|
|
631
|
+
### `MagicLinkRequestDto`
|
|
632
|
+
Used to request a magic login link (`/auth/magic-link`).
|
|
633
|
+
|
|
634
|
+
| Field | Type | Required | Description |
|
|
635
|
+
|---|---|---|---|
|
|
636
|
+
| `email` | `string` | ✅ | The email address to send the magic link to. |
|
|
637
|
+
|
|
638
|
+
### `RefreshTokenDto`
|
|
639
|
+
Used to rotate tokens or logout (`/auth/refresh`, `/auth/logout`).
|
|
640
|
+
|
|
641
|
+
| Field | Type | Required | Description |
|
|
642
|
+
|---|---|---|---|
|
|
643
|
+
| `refreshToken` | `string` | ❌ | The refresh token. Required if not using HTTP-only cookies. |
|
|
644
|
+
|
|
645
|
+
### `EnrollMfaDto`
|
|
646
|
+
Used to start MFA enrollment (`/auth/mfa/enroll`).
|
|
647
|
+
|
|
648
|
+
| Field | Type | Required | Description |
|
|
649
|
+
|---|---|---|---|
|
|
650
|
+
| `type` | `MfaType` | ✅ | The type of MFA to enroll (e.g., `TOTP`). |
|
|
651
|
+
|
|
652
|
+
### `ActivateMfaDto`
|
|
653
|
+
Used to finalize MFA activation (`/auth/mfa/activate`).
|
|
654
|
+
|
|
655
|
+
| Field | Type | Required | Description |
|
|
656
|
+
|---|---|---|---|
|
|
657
|
+
| `type` | `MfaType` | ✅ | The type of MFA to activate. |
|
|
658
|
+
| `code` | `string` | ✅ | The 6-digit code from the authenticator app. |
|
|
659
|
+
|
|
660
|
+
---
|
|
661
|
+
|
|
662
|
+
## Enumerations (Enums)
|
|
663
|
+
|
|
664
|
+
### `AuthStrategy`
|
|
665
|
+
The available authentication methods.
|
|
666
|
+
|
|
667
|
+
- `EMAIL`
|
|
668
|
+
- `PHONE`
|
|
669
|
+
- `USERNAME`
|
|
670
|
+
- `GOOGLE`
|
|
671
|
+
- `FACEBOOK`
|
|
672
|
+
- `APPLE`
|
|
673
|
+
|
|
674
|
+
### `OAuthProviderType`
|
|
675
|
+
Social authentication providers.
|
|
676
|
+
|
|
677
|
+
- `GOOGLE`
|
|
678
|
+
- `FACEBOOK`
|
|
679
|
+
- `APPLE`
|
|
680
|
+
|
|
681
|
+
### `MfaType`
|
|
682
|
+
Supported MFA methods.
|
|
683
|
+
|
|
684
|
+
- `TOTP` (Time-based One-Time Password)
|
|
685
|
+
|
|
686
|
+
### `AuthTransport`
|
|
687
|
+
How tokens are delivered to and sent from the client.
|
|
688
|
+
|
|
689
|
+
- `cookie`: Uses secure, HTTP-only session cookies.
|
|
690
|
+
- `bearer`: Returns tokens in the JSON response body.
|
|
691
|
+
- `both`: Enables both cookie and bearer transport simultaneously.
|
|
692
|
+
|
|
693
|
+
---
|
|
694
|
+
|
|
695
|
+
*(All endpoints are automatically documented if you have `@nestjs/swagger` configured in your root app).*
|
|
696
|
+
|
|
697
|
+
---
|
|
698
|
+
|
|
699
|
+
## Configuration Reference
|
|
700
|
+
|
|
701
|
+
All options for `AuthModule.register()` / `AuthModule.forRootAsync()`:
|
|
702
|
+
|
|
703
|
+
| Option | Type | Default | Description |
|
|
704
|
+
|---|---|---|---|
|
|
705
|
+
| `jwtSecret` | `string` | — | **Required.** Secret for signing Access Tokens. |
|
|
706
|
+
| `jwtRefreshSecret` | `string` | — | **Required.** Secret for signing Refresh Tokens. |
|
|
707
|
+
| `accessTokenExpiresIn` | `string` | `'15m'` | Access token expiration. |
|
|
708
|
+
| `refreshTokenExpiresIn` | `string` | `'7d'` | Refresh token & session duration. |
|
|
709
|
+
| `transport` | `AuthTransport \| AuthTransport[]` | `[BEARER]` | Token delivery method(s). |
|
|
710
|
+
| `enabledStrategies` | `AuthStrategy[]` | All | Which auth strategies to activate. |
|
|
711
|
+
| `disableGlobalGuard` | `boolean` | `false` | Disable the automatic global JWT guard. |
|
|
712
|
+
| `disableController` | `boolean` | `false` | Disable the built-in `AuthController`. |
|
|
713
|
+
| `notificationProvider` | `Type<AuthNotificationProvider>` | — | Class for sending OTP codes. |
|
|
714
|
+
| `verificationRequired` | `boolean` | `false` | Block login until identity is verified. |
|
|
715
|
+
| `imports` | `any[]` | — | Modules to import into the Auth context (e.g., for `notificationProvider`). |
|
|
716
|
+
| `appName` | `string` | `'NestJS Auth'` | App name shown in TOTP authenticator apps. |
|
|
717
|
+
| `googleClientId` | `string` | — | Required for Google OAuth strategy. |
|
|
718
|
+
| `facebookAppId` | `string` | — | Required for Facebook OAuth strategy. |
|
|
719
|
+
| `facebookAppSecret` | `string` | — | Required for Facebook OAuth strategy. |
|
|
720
|
+
| `appleClientId` | `string` | — | Required for Apple OAuth strategy. |
|
|
721
|
+
| `appleTeamId` | `string` | — | Optional for Apple OAuth strategy. |
|
|
722
|
+
| `emailRequiresPassword` | `boolean` | `true` | Require a password for email-based auth. |
|
|
723
|
+
| `usernameRequiresPassword` | `boolean` | `true` | Require a password for username-based auth. |
|
|
724
|
+
| `phoneRequiresPassword` | `boolean` | `false` | Require a password for phone-based auth. |
|
|
725
|
+
| `allowedPhonePrefixes` | `string[]` | — | Restrict phone auth to specific country codes. |
|
|
726
|
+
| `frontendUrl` | `string` | — | Base URL of your frontend app. Used to build Magic Links and Security Alert links. |
|
|
727
|
+
| `otpExpiresIn` | `number` | `15` | OTP validity in minutes. Also controls magic link expiry. |
|
|
728
|
+
| `otpResendInterval` | `number` | `60` | Minimum seconds between OTP resend requests. |
|
|
729
|
+
| `throttlerLimit` | `number` | `10` | Max requests per `throttlerTtl` window. |
|
|
730
|
+
| `throttlerTtl` | `number` | `60` | Throttle window duration in seconds. |
|
|
731
|
+
| `disableThrottler` | `boolean` | `false` | Disable the built-in rate limiting entirely. |
|
|
732
|
+
| `autoMigrate` | `boolean` | `false` | Automatically run database schema migrations on startup. |
|
|
733
|
+
|
|
734
|
+
---
|
|
735
|
+
|
|
736
|
+
## Common Issues & Troubleshooting
|
|
737
|
+
|
|
738
|
+
### `@CurrentAuth()` returns `undefined`
|
|
739
|
+
If your `@CurrentAuth()` decorator returns `undefined` even when you are sending a valid token, check the following:
|
|
740
|
+
|
|
741
|
+
1. **Global Guard Disabled**: Ensure `disableGlobalGuard` is not set to `true` in your `AuthModule` configuration. If it is, you **must** manually apply `@UseGuards(JwtAuthGuard)` to your controller or route.
|
|
742
|
+
2. **Async Configuration**: If using `forRootAsync`, ensure your factory is correctly returning the `jwtSecret`.
|
|
743
|
+
3. **Missing Strategy**: Ensure the strategy you are using (e.g., `EMAIL`) is included in `enabledStrategies` (or leave it empty to enable all).
|
|
744
|
+
|
|
745
|
+
### 401 Unauthorized on Public Routes
|
|
746
|
+
If you are getting 401 errors on routes marked with `@Public()`, ensure that the `AuthModule` is correctly registered as a Global module and that the `JwtAuthGuard` (registered as an `APP_GUARD`) is successfully reading the reflectors.
|
|
747
|
+
|
|
748
|
+
---
|
|
749
|
+
|
|
750
|
+
## Entity Requirements
|
|
751
|
+
|
|
752
|
+
Because this library is decoupled, it manages its own tracking entities (`Auth`, `Session`, `MfaMethod`, `OtpToken`, `OAuthProvider`, `AuthIdentifier`). These entities use an opaque `uid: string` to identify users.
|
|
753
|
+
|
|
754
|
+
To use the Auth functionality, ensure `TypeOrmModule.forRoot()` is initialized in your consuming app.
|
|
755
|
+
|
|
756
|
+
---
|
|
757
|
+
|
|
758
|
+
## License
|
|
759
|
+
|
|
760
|
+
ISC
|