@lenne.tech/nest-server 11.21.3 → 11.22.0
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/.claude/rules/architecture.md +79 -0
- package/.claude/rules/better-auth.md +262 -0
- package/.claude/rules/configurable-features.md +308 -0
- package/.claude/rules/core-modules.md +205 -0
- package/.claude/rules/migration-guides.md +149 -0
- package/.claude/rules/module-deprecation.md +214 -0
- package/.claude/rules/module-inheritance.md +97 -0
- package/.claude/rules/package-management.md +112 -0
- package/.claude/rules/role-system.md +146 -0
- package/.claude/rules/testing.md +120 -0
- package/.claude/rules/versioning.md +53 -0
- package/CLAUDE.md +172 -0
- package/dist/core/common/interfaces/server-options.interface.d.ts +10 -0
- package/dist/core/modules/error-code/error-code.module.js.map +1 -1
- package/dist/core.module.d.ts +3 -3
- package/dist/core.module.js +17 -4
- package/dist/core.module.js.map +1 -1
- package/dist/server/server.module.js +6 -6
- package/dist/server/server.module.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/docs/REQUEST-LIFECYCLE.md +1256 -0
- package/docs/error-codes.md +446 -0
- package/migration-guides/11.10.x-to-11.11.x.md +266 -0
- package/migration-guides/11.11.x-to-11.12.x.md +323 -0
- package/migration-guides/11.12.x-to-11.13.0.md +612 -0
- package/migration-guides/11.13.x-to-11.14.0.md +348 -0
- package/migration-guides/11.14.x-to-11.15.0.md +262 -0
- package/migration-guides/11.15.0-to-11.15.3.md +118 -0
- package/migration-guides/11.15.x-to-11.16.0.md +497 -0
- package/migration-guides/11.16.x-to-11.17.0.md +130 -0
- package/migration-guides/11.17.x-to-11.18.0.md +393 -0
- package/migration-guides/11.18.x-to-11.19.0.md +151 -0
- package/migration-guides/11.19.x-to-11.20.0.md +170 -0
- package/migration-guides/11.20.x-to-11.21.0.md +216 -0
- package/migration-guides/11.21.0-to-11.21.1.md +194 -0
- package/migration-guides/11.21.1-to-11.21.2.md +114 -0
- package/migration-guides/11.21.2-to-11.21.3.md +175 -0
- package/migration-guides/11.21.x-to-11.22.0.md +224 -0
- package/migration-guides/11.3.x-to-11.4.x.md +233 -0
- package/migration-guides/11.6.x-to-11.7.x.md +394 -0
- package/migration-guides/11.7.x-to-11.8.x.md +318 -0
- package/migration-guides/11.8.x-to-11.9.x.md +322 -0
- package/migration-guides/11.9.x-to-11.10.x.md +571 -0
- package/migration-guides/TEMPLATE.md +113 -0
- package/package.json +8 -3
- package/src/core/common/interfaces/server-options.interface.ts +83 -16
- package/src/core/modules/better-auth/CUSTOMIZATION.md +24 -17
- package/src/core/modules/better-auth/INTEGRATION-CHECKLIST.md +5 -5
- package/src/core/modules/error-code/INTEGRATION-CHECKLIST.md +42 -12
- package/src/core/modules/error-code/error-code.module.ts +4 -9
- package/src/core.module.ts +52 -10
- package/src/server/server.module.ts +7 -9
|
@@ -0,0 +1,571 @@
|
|
|
1
|
+
# Migration Guide: 11.9.x → 11.10.x
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
| Category | Details |
|
|
6
|
+
|----------|---------|
|
|
7
|
+
| **Breaking Changes** | None (trustedOrigins now auto-detected from baseUrl) |
|
|
8
|
+
| **New Features** | **Zero-Config Passkey**, URL Auto-Detection, Database Challenge Storage (JWT mode), Logging helpers, BetterAuthTokenService, Secure-by-Default RolesGuard, RolesGuardRegistry |
|
|
9
|
+
| **Bugfixes** | Session token forwarding, RolesGuard enforcement in IAM-only mode |
|
|
10
|
+
| **Migration Effort** | Very Low (~5 minutes) - Most projects need no changes |
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Quick Migration
|
|
15
|
+
|
|
16
|
+
### All Projects
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Update package
|
|
20
|
+
npm install @lenne.tech/nest-server@11.10.x
|
|
21
|
+
|
|
22
|
+
# Verify build
|
|
23
|
+
npm run build
|
|
24
|
+
|
|
25
|
+
# Run tests
|
|
26
|
+
npm test
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**That's it!** Most projects need no code changes due to Zero-Config improvements.
|
|
30
|
+
|
|
31
|
+
### New in 11.10.3: Zero-Config Passkey
|
|
32
|
+
|
|
33
|
+
Passkey now works without explicit configuration! URL auto-detection makes setup much simpler:
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
// config.env.ts - BEFORE (11.10.0-11.10.2)
|
|
37
|
+
betterAuth: {
|
|
38
|
+
passkey: true,
|
|
39
|
+
trustedOrigins: ['http://localhost:3001'], // Was required
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// config.env.ts - AFTER (11.10.3) - Zero-Config!
|
|
43
|
+
// Option 1: Use env: 'local' for development (auto: API=:3000, App=:3001)
|
|
44
|
+
const config = {
|
|
45
|
+
env: 'local', // Passkey auto-activated with localhost defaults
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// Option 2: Set root-level baseUrl for production
|
|
49
|
+
const config = {
|
|
50
|
+
baseUrl: 'https://api.example.com', // Auto-detects appUrl, rpId, trustedOrigins
|
|
51
|
+
env: 'production',
|
|
52
|
+
};
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### IAM-only Projects (No Changes Required)
|
|
56
|
+
|
|
57
|
+
If you use the 1-parameter `CoreModule.forRoot(environment)` signature (IAM-only, no Legacy Auth), **no changes are required**. Since **11.10.3**, `registerRolesGuardGlobally` defaults to `true`, ensuring `@Roles()` decorators work automatically.
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
// server.module.ts - RolesGuard is registered automatically!
|
|
61
|
+
CoreBetterAuthModule.forRoot({
|
|
62
|
+
config: environment.betterAuth,
|
|
63
|
+
// registerRolesGuardGlobally: true // Now the default! No need to specify.
|
|
64
|
+
})
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Note:** Projects upgrading from 11.10.0-11.10.2 that already have `registerRolesGuardGlobally: true` can keep or remove it - the behavior is unchanged.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## What's New in 11.10.x
|
|
72
|
+
|
|
73
|
+
### 1. Zero-Config Passkey with URL Auto-Detection (11.10.3)
|
|
74
|
+
|
|
75
|
+
**All three plugins (JWT, 2FA, Passkey) are now enabled by default!**
|
|
76
|
+
|
|
77
|
+
Passkey configuration is now automatically derived from your server configuration:
|
|
78
|
+
|
|
79
|
+
| Config Source | `baseUrl` (API) | `appUrl` (Frontend) | Passkey |
|
|
80
|
+
|---------------|-----------------|---------------------|---------|
|
|
81
|
+
| `env: 'local'/'ci'/'e2e'` | `http://localhost:3000` | `http://localhost:3001` | ✅ auto |
|
|
82
|
+
| Root-level `baseUrl` set | as configured | derived (removes `api.` prefix) | ✅ auto |
|
|
83
|
+
| Neither set | - | - | ⚠️ disabled (warning) |
|
|
84
|
+
|
|
85
|
+
**URL Auto-Detection Logic:**
|
|
86
|
+
1. `appUrl` is derived from `baseUrl` by removing `api.` prefix (e.g., `api.example.com` → `example.com`)
|
|
87
|
+
2. `rpId` is extracted from `appUrl` hostname (e.g., `example.com`)
|
|
88
|
+
3. `origin` = `appUrl` (e.g., `https://example.com`)
|
|
89
|
+
4. `trustedOrigins` = `[appUrl]`
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
// RECOMMENDED: Set root-level baseUrl
|
|
93
|
+
const config = {
|
|
94
|
+
baseUrl: 'https://api.example.com', // Passkey values auto-detected
|
|
95
|
+
env: 'production',
|
|
96
|
+
};
|
|
97
|
+
// Auto-detected: rpId='example.com', origin='https://example.com', trustedOrigins=['https://example.com']
|
|
98
|
+
|
|
99
|
+
// For development: Use env: 'local'
|
|
100
|
+
const config = {
|
|
101
|
+
env: 'local', // Uses localhost:3000 (API), localhost:3001 (App)
|
|
102
|
+
};
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Graceful Degradation:** If URLs cannot be resolved, Passkey is disabled with a warning - other auth methods continue to work.
|
|
106
|
+
|
|
107
|
+
### 2. Database Challenge Storage for JWT Mode (11.10.3)
|
|
108
|
+
|
|
109
|
+
New `CoreBetterAuthChallengeService` enables Passkey authentication in **cookieless/JWT mode**.
|
|
110
|
+
|
|
111
|
+
**Problem:** Better-Auth's Passkey plugin uses cookies to store WebAuthn challenges. This doesn't work with JWT-based APIs.
|
|
112
|
+
|
|
113
|
+
**Solution:** An adapter pattern bridges the gap:
|
|
114
|
+
1. On `generate-options`: Extract Better-Auth's `verificationToken` from Set-Cookie, store mapping in MongoDB
|
|
115
|
+
2. Return `challengeId` to client (not the verificationToken for security)
|
|
116
|
+
3. On `verify`: Client sends `challengeId`, we inject `verificationToken` as cookie for Better-Auth
|
|
117
|
+
|
|
118
|
+
**Security measures:**
|
|
119
|
+
- 256-bit entropy challenge IDs (`crypto.randomBytes(32)`)
|
|
120
|
+
- TTL-based MongoDB index for automatic cleanup
|
|
121
|
+
- One-time use (deleted after verification)
|
|
122
|
+
- User binding (challenges tied to specific user)
|
|
123
|
+
|
|
124
|
+
**Client-side usage (JWT mode):**
|
|
125
|
+
```typescript
|
|
126
|
+
// Use composable methods which handle challengeId automatically
|
|
127
|
+
const { authenticateWithPasskey, registerPasskey } = useBetterAuth();
|
|
128
|
+
|
|
129
|
+
// Authentication
|
|
130
|
+
const result = await authenticateWithPasskey();
|
|
131
|
+
|
|
132
|
+
// Registration
|
|
133
|
+
const result = await registerPasskey('My Device');
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### 3. TypeScript Compile-Time Validation for Passkey CORS (11.10.0)
|
|
137
|
+
|
|
138
|
+
The `IBetterAuth` type enforces `trustedOrigins` when Passkey is enabled. **Note:** With URL auto-detection in 11.10.3, this is automatically handled.
|
|
139
|
+
|
|
140
|
+
### 2. Logging Helper for Secure Logging
|
|
141
|
+
|
|
142
|
+
New helper functions for safely logging sensitive data (GDPR compliant):
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
import { maskToken, maskEmail, maskCookieHeader, isProduction } from '@lenne.tech/nest-server';
|
|
146
|
+
|
|
147
|
+
// Mask tokens: 'abc123xyz789' → 'abc1...9789'
|
|
148
|
+
this.logger.debug(`Token: ${maskToken(token)}`);
|
|
149
|
+
|
|
150
|
+
// Mask emails: 'john.doe@example.com' → 'jo***@example.com'
|
|
151
|
+
this.logger.debug(`User: ${maskEmail(user.email)}`);
|
|
152
|
+
|
|
153
|
+
// Mask cookie headers: 'session=abc123; token=xyz' → 'session=***; token=***'
|
|
154
|
+
this.logger.debug(`Cookies: ${maskCookieHeader(req.headers.cookie)}`);
|
|
155
|
+
|
|
156
|
+
// Conditional logging for non-production only
|
|
157
|
+
if (!isProduction()) {
|
|
158
|
+
this.logger.debug('Debug info...');
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### 3. Improved Session Lookup Performance
|
|
163
|
+
|
|
164
|
+
The `getSessionByToken()` method now uses a MongoDB aggregation pipeline for single-query session+user lookup, improving performance and handling both ObjectId and string userId formats automatically.
|
|
165
|
+
|
|
166
|
+
### 4. Enhanced Cookie Handling for Plugin Compatibility
|
|
167
|
+
|
|
168
|
+
Session tokens are now set in multiple cookies to ensure compatibility with Better Auth plugins (especially Passkey):
|
|
169
|
+
|
|
170
|
+
| Cookie | Purpose |
|
|
171
|
+
|--------|---------|
|
|
172
|
+
| `token` | nest-server compatibility |
|
|
173
|
+
| `{basePath}.session_token` | Better Auth native (e.g., `iam.session_token`) |
|
|
174
|
+
| `better-auth.session_token` | Legacy Better Auth |
|
|
175
|
+
|
|
176
|
+
### 5. Native Better Auth Plugin Endpoints
|
|
177
|
+
|
|
178
|
+
2FA and Passkey endpoints now use Better Auth's native plugin handlers, providing more features:
|
|
179
|
+
|
|
180
|
+
**Two-Factor Authentication (2FA):**
|
|
181
|
+
|
|
182
|
+
| Endpoint | Method | Description |
|
|
183
|
+
|----------|--------|-------------|
|
|
184
|
+
| `/iam/two-factor/enable` | POST | Enable 2FA, get TOTP URI |
|
|
185
|
+
| `/iam/two-factor/disable` | POST | Disable 2FA |
|
|
186
|
+
| `/iam/two-factor/verify-totp` | POST | Verify TOTP code |
|
|
187
|
+
| `/iam/two-factor/generate-backup-codes` | POST | Generate backup codes |
|
|
188
|
+
| `/iam/two-factor/verify-backup-code` | POST | Verify backup code |
|
|
189
|
+
|
|
190
|
+
**Passkey (WebAuthn):**
|
|
191
|
+
|
|
192
|
+
| Endpoint | Method | Description |
|
|
193
|
+
|----------|--------|-------------|
|
|
194
|
+
| `/iam/passkey/generate-register-options` | POST | Get WebAuthn registration options |
|
|
195
|
+
| `/iam/passkey/verify-registration` | POST | Verify and store passkey |
|
|
196
|
+
| `/iam/passkey/generate-authenticate-options` | POST | Get WebAuthn authentication options |
|
|
197
|
+
| `/iam/passkey/verify-authentication` | POST | Verify passkey authentication |
|
|
198
|
+
| `/iam/passkey/list-user-passkeys` | POST | List user's passkeys |
|
|
199
|
+
| `/iam/passkey/delete-passkey` | POST | Delete a passkey |
|
|
200
|
+
| `/iam/passkey/update-passkey` | POST | Update passkey name |
|
|
201
|
+
|
|
202
|
+
### 6. BetterAuthTokenService
|
|
203
|
+
|
|
204
|
+
New centralized service for token extraction and user loading in BetterAuth authentication.
|
|
205
|
+
|
|
206
|
+
**What the service provides:**
|
|
207
|
+
- Token extraction from Authorization header or cookies
|
|
208
|
+
- JWT token verification via BetterAuth
|
|
209
|
+
- Session token verification via database lookup
|
|
210
|
+
- User loading from MongoDB with `hasRole()` capability
|
|
211
|
+
|
|
212
|
+
**Benefits:**
|
|
213
|
+
- Consolidates token verification logic that was previously duplicated in AuthGuard and RolesGuard
|
|
214
|
+
- Lazy resolution: Guards use `ModuleRef.get()` with `{ strict: false }` for optional dependencies
|
|
215
|
+
- Improved testability and maintainability
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
import { BetterAuthTokenService } from '@lenne.tech/nest-server';
|
|
219
|
+
|
|
220
|
+
// In a guard or service
|
|
221
|
+
const { token, source } = this.tokenService.extractTokenFromRequest(request);
|
|
222
|
+
if (token) {
|
|
223
|
+
const user = await this.tokenService.verifyAndLoadUser(token);
|
|
224
|
+
if (user) {
|
|
225
|
+
request.user = user;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### 7. Secure-by-Default RolesGuard (11.10.3)
|
|
231
|
+
|
|
232
|
+
The `registerRolesGuardGlobally` option now defaults to `true` for security-by-default behavior.
|
|
233
|
+
|
|
234
|
+
**Problem (11.10.0-11.10.2):**
|
|
235
|
+
In IAM-only setups, `@Roles()` decorators were not enforced unless `registerRolesGuardGlobally: true` was explicitly set.
|
|
236
|
+
|
|
237
|
+
**Solution (11.10.3+):**
|
|
238
|
+
```typescript
|
|
239
|
+
// server.module.ts - IAM-only Setup
|
|
240
|
+
@Module({
|
|
241
|
+
imports: [
|
|
242
|
+
CoreModule.forRoot(environment), // 1-parameter signature = IAM-only
|
|
243
|
+
CoreBetterAuthModule.forRoot({
|
|
244
|
+
config: environment.betterAuth,
|
|
245
|
+
// registerRolesGuardGlobally defaults to true - @Roles() decorators work automatically!
|
|
246
|
+
}),
|
|
247
|
+
],
|
|
248
|
+
})
|
|
249
|
+
export class ServerModule {}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
**Behavior:**
|
|
253
|
+
- `registerRolesGuardGlobally: true` (default) - RolesGuard registered globally, `@Roles()` enforced
|
|
254
|
+
- `registerRolesGuardGlobally: false` - Explicit opt-out (shows security warning if no other guard registered)
|
|
255
|
+
|
|
256
|
+
**RolesGuardRegistry (Advanced):**
|
|
257
|
+
|
|
258
|
+
A shared `RolesGuardRegistry` prevents duplicate registrations when both CoreAuthModule (Legacy) and CoreBetterAuthModule (IAM) are used together:
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
import { RolesGuardRegistry } from '@lenne.tech/nest-server';
|
|
262
|
+
|
|
263
|
+
// Check if RolesGuard is already registered
|
|
264
|
+
if (RolesGuardRegistry.isRegistered()) {
|
|
265
|
+
console.log(`Registered by: ${RolesGuardRegistry.getRegisteredBy()}`);
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**Security Warning:**
|
|
270
|
+
|
|
271
|
+
If `registerRolesGuardGlobally: false` is explicitly set and no other guard is registered, a warning is logged:
|
|
272
|
+
|
|
273
|
+
```
|
|
274
|
+
⚠️ SECURITY WARNING: registerRolesGuardGlobally is explicitly set to false,
|
|
275
|
+
but no RolesGuard is registered globally. @Roles() decorators will NOT enforce access control!
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## Breaking Changes
|
|
281
|
+
|
|
282
|
+
### No Breaking Changes in 11.10.3
|
|
283
|
+
|
|
284
|
+
With URL auto-detection, the previous requirement for explicit `trustedOrigins` is now resolved automatically.
|
|
285
|
+
|
|
286
|
+
**For 11.10.0-11.10.2 users:** The TypeScript requirement for `trustedOrigins` with Passkey is now handled by auto-detection. You can simplify your config:
|
|
287
|
+
|
|
288
|
+
**Before (11.10.0-11.10.2):**
|
|
289
|
+
```typescript
|
|
290
|
+
betterAuth: {
|
|
291
|
+
passkey: true,
|
|
292
|
+
trustedOrigins: ['http://localhost:3001'], // Was required
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
**After (11.10.3) - Zero-Config:**
|
|
297
|
+
```typescript
|
|
298
|
+
// Just set env: 'local' or root-level baseUrl - trustedOrigins auto-detected!
|
|
299
|
+
const config = {
|
|
300
|
+
env: 'local',
|
|
301
|
+
// Passkey works automatically!
|
|
302
|
+
};
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Historical: `trustedOrigins` Requirement (11.10.0-11.10.2)
|
|
306
|
+
|
|
307
|
+
**Note:** This was resolved in 11.10.3 with URL auto-detection.
|
|
308
|
+
|
|
309
|
+
**Before (11.9.x):**
|
|
310
|
+
```typescript
|
|
311
|
+
betterAuth: {
|
|
312
|
+
passkey: true,
|
|
313
|
+
// trustedOrigins was optional (caused runtime CORS errors)
|
|
314
|
+
}
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
**In 11.10.0-11.10.2:**
|
|
318
|
+
```typescript
|
|
319
|
+
betterAuth: {
|
|
320
|
+
passkey: true,
|
|
321
|
+
trustedOrigins: ['http://localhost:3001', 'https://app.example.com'],
|
|
322
|
+
}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### 2. 2FA Endpoint Changes
|
|
326
|
+
|
|
327
|
+
**Impact:** Projects calling 2FA endpoints directly
|
|
328
|
+
|
|
329
|
+
The endpoint for verifying TOTP codes changed:
|
|
330
|
+
|
|
331
|
+
| Before (11.9.x) | After (11.10.x) |
|
|
332
|
+
|-----------------|-----------------|
|
|
333
|
+
| `POST /iam/two-factor/verify` | `POST /iam/two-factor/verify-totp` |
|
|
334
|
+
|
|
335
|
+
Additionally, new endpoints are available for backup codes.
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
## Bugfixes
|
|
340
|
+
|
|
341
|
+
### 2FA Session Token Cookie Handling
|
|
342
|
+
|
|
343
|
+
**Fixed Issue:** When signing in with 2FA enabled, the temporary session token was not being set as a cookie. This caused the 2FA verification step (`/iam/two-factor/verify-totp`) to fail with 401 Unauthorized because the browser couldn't authenticate the request.
|
|
344
|
+
|
|
345
|
+
**What was happening:**
|
|
346
|
+
1. User signs in with email/password
|
|
347
|
+
2. Server returns `requiresTwoFactor: true` but no cookie was set
|
|
348
|
+
3. User enters TOTP code
|
|
349
|
+
4. Request fails because there's no session token to identify the 2FA flow
|
|
350
|
+
|
|
351
|
+
**What's fixed:**
|
|
352
|
+
1. User signs in with email/password
|
|
353
|
+
2. Server returns `requiresTwoFactor: true` AND sets the temporary session token as a cookie
|
|
354
|
+
3. User enters TOTP code
|
|
355
|
+
4. Browser automatically sends the session cookie → verification succeeds
|
|
356
|
+
|
|
357
|
+
**No action required** - this is a bugfix that improves 2FA functionality without requiring any code changes.
|
|
358
|
+
|
|
359
|
+
### RolesGuard Enforcement in IAM-only Mode
|
|
360
|
+
|
|
361
|
+
**Fixed Issue:** In IAM-only setups (CoreModule.forRoot with 1 parameter), `@Roles()` decorators were not automatically enforced because the RolesGuard was not globally registered.
|
|
362
|
+
|
|
363
|
+
**Symptom:** Endpoints with `@Roles(RoleEnum.ADMIN)` were accessible without authentication.
|
|
364
|
+
|
|
365
|
+
**Cause:** CoreAuthModule (which globally registers the RolesGuard) is not imported in IAM-only setups.
|
|
366
|
+
|
|
367
|
+
**Solution (11.10.3+):** `registerRolesGuardGlobally` now defaults to `true`. **No action required** - `@Roles()` decorators are automatically enforced.
|
|
368
|
+
|
|
369
|
+
```typescript
|
|
370
|
+
// Works automatically in 11.10.3+
|
|
371
|
+
CoreBetterAuthModule.forRoot({
|
|
372
|
+
config: environment.betterAuth,
|
|
373
|
+
// registerRolesGuardGlobally defaults to true
|
|
374
|
+
})
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
**Note:** Projects upgrading from 11.10.0-11.10.2 that already have `registerRolesGuardGlobally: true` can keep or remove it.
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
## Detailed Migration Steps
|
|
382
|
+
|
|
383
|
+
### Step 1: Update Package
|
|
384
|
+
|
|
385
|
+
```bash
|
|
386
|
+
npm install @lenne.tech/nest-server@11.10.x
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### Step 2: Add trustedOrigins (If Using Passkey)
|
|
390
|
+
|
|
391
|
+
If you have `passkey: true` in your config, add `trustedOrigins`:
|
|
392
|
+
|
|
393
|
+
```typescript
|
|
394
|
+
// config.env.ts
|
|
395
|
+
betterAuth: {
|
|
396
|
+
passkey: true,
|
|
397
|
+
trustedOrigins: [
|
|
398
|
+
'http://localhost:3001', // Development frontend
|
|
399
|
+
'https://app.example.com', // Production frontend
|
|
400
|
+
],
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### Step 3: Update 2FA API Calls (If Using 2FA)
|
|
405
|
+
|
|
406
|
+
If your frontend calls the 2FA verify endpoint, update the path:
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
// Before
|
|
410
|
+
await fetch('/iam/two-factor/verify', { body: { code: '123456' } });
|
|
411
|
+
|
|
412
|
+
// After
|
|
413
|
+
await fetch('/iam/two-factor/verify-totp', { body: { code: '123456' } });
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### Step 4: Verify RolesGuard (IAM-only Setup)
|
|
417
|
+
|
|
418
|
+
**No changes required for 11.10.3+.** The `registerRolesGuardGlobally` option now defaults to `true`.
|
|
419
|
+
|
|
420
|
+
If you upgraded from 11.10.0-11.10.2 and added `registerRolesGuardGlobally: true`, you can optionally remove it:
|
|
421
|
+
|
|
422
|
+
```typescript
|
|
423
|
+
// server.module.ts - 11.10.3+ (registerRolesGuardGlobally defaults to true)
|
|
424
|
+
CoreBetterAuthModule.forRoot({
|
|
425
|
+
config: environment.betterAuth,
|
|
426
|
+
// registerRolesGuardGlobally: true, // Optional - this is now the default
|
|
427
|
+
})
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
**How to check if you're IAM-only:**
|
|
431
|
+
- 1-parameter: `CoreModule.forRoot(environment)` → IAM-only, RolesGuard registered automatically
|
|
432
|
+
- 3-parameter: `CoreModule.forRoot(CoreAuthService, AuthModule.forRoot(...), environment)` → Legacy + IAM, RolesGuard registered by CoreAuthModule
|
|
433
|
+
|
|
434
|
+
### Step 5: Verify Build and Tests
|
|
435
|
+
|
|
436
|
+
```bash
|
|
437
|
+
npm run build
|
|
438
|
+
npm test
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
|
|
443
|
+
## Compatibility Notes
|
|
444
|
+
|
|
445
|
+
### Existing Projects Without Passkey
|
|
446
|
+
|
|
447
|
+
No changes required. The migration is seamless.
|
|
448
|
+
|
|
449
|
+
### Existing Projects With 2FA Only
|
|
450
|
+
|
|
451
|
+
No breaking changes for basic 2FA usage. The new endpoints provide additional features (backup codes) but the core flow remains the same.
|
|
452
|
+
|
|
453
|
+
### Custom BetterAuthController Extensions
|
|
454
|
+
|
|
455
|
+
If you extend `CoreBetterAuthController`, note that the `handleBetterAuthPlugins()` method is now used for plugin endpoints. Your existing overrides should continue to work.
|
|
456
|
+
|
|
457
|
+
---
|
|
458
|
+
|
|
459
|
+
## Troubleshooting
|
|
460
|
+
|
|
461
|
+
### Passkey Disabled Warning
|
|
462
|
+
|
|
463
|
+
**Symptom:** Console shows `⚠️ PASSKEY DISABLED: Cannot auto-detect required values`
|
|
464
|
+
|
|
465
|
+
**Solution:** Ensure URLs can be resolved via one of these methods:
|
|
466
|
+
```typescript
|
|
467
|
+
// Option 1: Set env for local development
|
|
468
|
+
const config = { env: 'local' };
|
|
469
|
+
|
|
470
|
+
// Option 2: Set root-level baseUrl for production
|
|
471
|
+
const config = { baseUrl: 'https://api.example.com', env: 'production' };
|
|
472
|
+
|
|
473
|
+
// Option 3: Explicit passkey config (not recommended)
|
|
474
|
+
betterAuth: {
|
|
475
|
+
passkey: { rpId: 'example.com', origin: 'https://example.com' },
|
|
476
|
+
trustedOrigins: ['https://example.com'],
|
|
477
|
+
}
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
### CORS Error with Passkey
|
|
481
|
+
|
|
482
|
+
**Symptom:** Browser console shows CORS error when using Passkey
|
|
483
|
+
|
|
484
|
+
**Solution:** Ensure `trustedOrigins` is correctly auto-detected. Check console for URL resolution warnings. If auto-detection fails, provide explicit `trustedOrigins`:
|
|
485
|
+
```typescript
|
|
486
|
+
betterAuth: {
|
|
487
|
+
trustedOrigins: ['http://localhost:3001'], // Include protocol and port!
|
|
488
|
+
}
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
### Passkey Challenge Mapping Not Found (JWT Mode)
|
|
492
|
+
|
|
493
|
+
**Symptom:** `Challenge mapping not found` error when verifying passkey
|
|
494
|
+
|
|
495
|
+
**Solution:** Ensure you're using the composable methods that handle `challengeId`:
|
|
496
|
+
```typescript
|
|
497
|
+
// CORRECT: Use composable methods
|
|
498
|
+
const { authenticateWithPasskey } = useBetterAuth();
|
|
499
|
+
await authenticateWithPasskey();
|
|
500
|
+
|
|
501
|
+
// WRONG: Direct client call (doesn't handle challengeId in JWT mode)
|
|
502
|
+
await authClient.signIn.passkey();
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
### 2FA Verify Returns 404
|
|
506
|
+
|
|
507
|
+
**Symptom:** `POST /iam/two-factor/verify` returns 404
|
|
508
|
+
|
|
509
|
+
**Solution:** Update to new endpoint: `POST /iam/two-factor/verify-totp`
|
|
510
|
+
|
|
511
|
+
### Debug Logging Not Appearing
|
|
512
|
+
|
|
513
|
+
**Symptom:** Debug logs missing in development
|
|
514
|
+
|
|
515
|
+
**Solution:** Debug logs are now suppressed in production. Ensure `NODE_ENV` is not set to `production` during development.
|
|
516
|
+
|
|
517
|
+
### Protected Endpoints Accessible Without Authentication (IAM-only)
|
|
518
|
+
|
|
519
|
+
**Symptom:** Endpoints with `@Roles(RoleEnum.ADMIN)` are accessible without authentication in IAM-only setups.
|
|
520
|
+
|
|
521
|
+
**Cause (11.10.0-11.10.2):** RolesGuard was not globally registered by default.
|
|
522
|
+
|
|
523
|
+
**Solution:** Upgrade to 11.10.3+. The `registerRolesGuardGlobally` option now defaults to `true`.
|
|
524
|
+
|
|
525
|
+
If you explicitly set `registerRolesGuardGlobally: false`, ensure you have another guard mechanism in place:
|
|
526
|
+
```typescript
|
|
527
|
+
// Check console for security warning:
|
|
528
|
+
// ⚠️ SECURITY WARNING: registerRolesGuardGlobally is explicitly set to false...
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
---
|
|
532
|
+
|
|
533
|
+
## Module Documentation
|
|
534
|
+
|
|
535
|
+
### BetterAuth Module
|
|
536
|
+
|
|
537
|
+
- **README:** [src/core/modules/better-auth/README.md](../src/core/modules/better-auth/README.md)
|
|
538
|
+
- **Integration Checklist:** [src/core/modules/better-auth/INTEGRATION-CHECKLIST.md](../src/core/modules/better-auth/INTEGRATION-CHECKLIST.md)
|
|
539
|
+
- **Reference Implementation:** `src/server/modules/better-auth/`
|
|
540
|
+
|
|
541
|
+
---
|
|
542
|
+
|
|
543
|
+
## New Exports
|
|
544
|
+
|
|
545
|
+
The following are now exported from `@lenne.tech/nest-server`:
|
|
546
|
+
|
|
547
|
+
```typescript
|
|
548
|
+
// Logging helpers (11.10.0)
|
|
549
|
+
export { isProduction, maskCookieHeader, maskEmail, maskId, maskSensitive, maskToken } from './core/common/helpers/logging.helper';
|
|
550
|
+
|
|
551
|
+
// BetterAuth types (updated)
|
|
552
|
+
export { IBetterAuth, IBetterAuthWithPasskey, IBetterAuthWithoutPasskey } from './core/common/interfaces/server-options.interface';
|
|
553
|
+
|
|
554
|
+
// BetterAuthTokenService (11.10.2)
|
|
555
|
+
export { BetterAuthTokenService, TokenExtractionResult } from './core/modules/better-auth/better-auth-token.service';
|
|
556
|
+
|
|
557
|
+
// CoreBetterAuthChallengeService (11.10.3) - Database challenge storage for JWT mode
|
|
558
|
+
export { CoreBetterAuthChallengeService } from './core/modules/better-auth/core-better-auth-challenge.service';
|
|
559
|
+
|
|
560
|
+
// RolesGuardRegistry (11.10.3) - Prevents duplicate global RolesGuard registrations
|
|
561
|
+
export { RolesGuardRegistry } from './core/modules/auth/guards/roles-guard-registry';
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
---
|
|
565
|
+
|
|
566
|
+
## References
|
|
567
|
+
|
|
568
|
+
- [BetterAuth README](../src/core/modules/better-auth/README.md)
|
|
569
|
+
- [BetterAuth Integration Checklist](../src/core/modules/better-auth/INTEGRATION-CHECKLIST.md)
|
|
570
|
+
- [nest-server-starter](https://github.com/lenneTech/nest-server-starter) (reference implementation)
|
|
571
|
+
- [Better Auth Documentation](https://www.better-auth.com/docs)
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Migration Guide: X.Y.x → X.Z.x
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
| Category | Details |
|
|
6
|
+
|----------|---------|
|
|
7
|
+
| **Breaking Changes** | None / List them |
|
|
8
|
+
| **New Features** | List new features |
|
|
9
|
+
| **Bugfixes** | List bugfixes |
|
|
10
|
+
| **Migration Effort** | Estimated time |
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Quick Migration (No Breaking Changes)
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# Update package
|
|
18
|
+
npm install @lenne.tech/nest-server@X.Z.x
|
|
19
|
+
|
|
20
|
+
# If package.json dependencies changed
|
|
21
|
+
npm run update
|
|
22
|
+
|
|
23
|
+
# Verify build
|
|
24
|
+
npm run build
|
|
25
|
+
|
|
26
|
+
# Run tests
|
|
27
|
+
npm test
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## What's New in X.Z.x
|
|
33
|
+
|
|
34
|
+
### 1. Feature Name
|
|
35
|
+
|
|
36
|
+
Description of the feature and how to use it.
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
// Code example
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Breaking Changes (If Any)
|
|
45
|
+
|
|
46
|
+
### Change 1: Description
|
|
47
|
+
|
|
48
|
+
**Before:**
|
|
49
|
+
```typescript
|
|
50
|
+
// Old code
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**After:**
|
|
54
|
+
```typescript
|
|
55
|
+
// New code
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Detailed Migration Steps
|
|
61
|
+
|
|
62
|
+
### Step 1: Update Package
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npm install @lenne.tech/nest-server@X.Z.x
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Step 2: Address Breaking Changes
|
|
69
|
+
|
|
70
|
+
(Details for each breaking change)
|
|
71
|
+
|
|
72
|
+
### Step 3: Adopt New Features (Optional)
|
|
73
|
+
|
|
74
|
+
(Details for each new feature)
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Compatibility Notes
|
|
79
|
+
|
|
80
|
+
Notes about patterns that continue to work, custom implementations, etc.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Troubleshooting
|
|
85
|
+
|
|
86
|
+
### Common Issue 1
|
|
87
|
+
|
|
88
|
+
Solution...
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Module Documentation
|
|
93
|
+
|
|
94
|
+
For detailed information about affected modules, link to their documentation:
|
|
95
|
+
|
|
96
|
+
### Module Name
|
|
97
|
+
|
|
98
|
+
- **README:** [src/core/modules/module-name/README.md](../src/core/modules/module-name/README.md)
|
|
99
|
+
- **Integration Checklist:** [src/core/modules/module-name/INTEGRATION-CHECKLIST.md](../src/core/modules/module-name/INTEGRATION-CHECKLIST.md) (if exists)
|
|
100
|
+
- **Reference Implementation:** `src/server/modules/module-name/`
|
|
101
|
+
- **Key Files:** List important files with brief descriptions
|
|
102
|
+
|
|
103
|
+
> **Note:** Only include modules that have changes relevant to this migration.
|
|
104
|
+
> Check for existing documentation using:
|
|
105
|
+
> - `src/core/modules/**/README.md`
|
|
106
|
+
> - `src/core/modules/**/INTEGRATION-CHECKLIST.md`
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## References
|
|
111
|
+
|
|
112
|
+
- [Relevant documentation links]
|
|
113
|
+
- [nest-server-starter](https://github.com/lenneTech/nest-server-starter) (reference implementation)
|