@lenne.tech/nest-server 11.12.0 → 11.13.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.
Files changed (95) hide show
  1. package/dist/config.env.js +1 -0
  2. package/dist/config.env.js.map +1 -1
  3. package/dist/core/common/interfaces/server-options.interface.d.ts +16 -0
  4. package/dist/core/modules/better-auth/better-auth.config.d.ts +13 -0
  5. package/dist/core/modules/better-auth/better-auth.config.js +68 -18
  6. package/dist/core/modules/better-auth/better-auth.config.js.map +1 -1
  7. package/dist/core/modules/better-auth/better-auth.resolver.d.ts +7 -3
  8. package/dist/core/modules/better-auth/better-auth.resolver.js +16 -6
  9. package/dist/core/modules/better-auth/better-auth.resolver.js.map +1 -1
  10. package/dist/core/modules/better-auth/core-better-auth-api.middleware.d.ts +2 -2
  11. package/dist/core/modules/better-auth/core-better-auth-api.middleware.js +46 -2
  12. package/dist/core/modules/better-auth/core-better-auth-api.middleware.js.map +1 -1
  13. package/dist/core/modules/better-auth/core-better-auth-auth.model.d.ts +1 -0
  14. package/dist/core/modules/better-auth/core-better-auth-auth.model.js +7 -0
  15. package/dist/core/modules/better-auth/core-better-auth-auth.model.js.map +1 -1
  16. package/dist/core/modules/better-auth/core-better-auth-email-verification.service.d.ts +48 -0
  17. package/dist/core/modules/better-auth/core-better-auth-email-verification.service.js +241 -0
  18. package/dist/core/modules/better-auth/core-better-auth-email-verification.service.js.map +1 -0
  19. package/dist/core/modules/better-auth/core-better-auth-models.d.ts +2 -1
  20. package/dist/core/modules/better-auth/core-better-auth-models.js +8 -4
  21. package/dist/core/modules/better-auth/core-better-auth-models.js.map +1 -1
  22. package/dist/core/modules/better-auth/core-better-auth-signup-validator.service.d.ts +18 -0
  23. package/dist/core/modules/better-auth/core-better-auth-signup-validator.service.js +82 -0
  24. package/dist/core/modules/better-auth/core-better-auth-signup-validator.service.js.map +1 -0
  25. package/dist/core/modules/better-auth/core-better-auth-user.mapper.d.ts +0 -1
  26. package/dist/core/modules/better-auth/core-better-auth-user.mapper.js +15 -8
  27. package/dist/core/modules/better-auth/core-better-auth-user.mapper.js.map +1 -1
  28. package/dist/core/modules/better-auth/core-better-auth-web.helper.d.ts +1 -0
  29. package/dist/core/modules/better-auth/core-better-auth-web.helper.js +33 -24
  30. package/dist/core/modules/better-auth/core-better-auth-web.helper.js.map +1 -1
  31. package/dist/core/modules/better-auth/core-better-auth.controller.d.ts +11 -1
  32. package/dist/core/modules/better-auth/core-better-auth.controller.js +91 -15
  33. package/dist/core/modules/better-auth/core-better-auth.controller.js.map +1 -1
  34. package/dist/core/modules/better-auth/core-better-auth.middleware.js +55 -19
  35. package/dist/core/modules/better-auth/core-better-auth.middleware.js.map +1 -1
  36. package/dist/core/modules/better-auth/core-better-auth.module.d.ts +6 -0
  37. package/dist/core/modules/better-auth/core-better-auth.module.js +129 -24
  38. package/dist/core/modules/better-auth/core-better-auth.module.js.map +1 -1
  39. package/dist/core/modules/better-auth/core-better-auth.resolver.d.ts +12 -5
  40. package/dist/core/modules/better-auth/core-better-auth.resolver.js +64 -17
  41. package/dist/core/modules/better-auth/core-better-auth.resolver.js.map +1 -1
  42. package/dist/core/modules/better-auth/core-better-auth.service.d.ts +4 -1
  43. package/dist/core/modules/better-auth/core-better-auth.service.js +123 -23
  44. package/dist/core/modules/better-auth/core-better-auth.service.js.map +1 -1
  45. package/dist/core/modules/better-auth/index.d.ts +2 -0
  46. package/dist/core/modules/better-auth/index.js +2 -0
  47. package/dist/core/modules/better-auth/index.js.map +1 -1
  48. package/dist/core/modules/error-code/error-codes.d.ts +45 -0
  49. package/dist/core/modules/error-code/error-codes.js +40 -0
  50. package/dist/core/modules/error-code/error-codes.js.map +1 -1
  51. package/dist/core/modules/user/core-user.model.d.ts +1 -0
  52. package/dist/core/modules/user/core-user.model.js +11 -0
  53. package/dist/core/modules/user/core-user.model.js.map +1 -1
  54. package/dist/server/modules/better-auth/better-auth.controller.d.ts +3 -1
  55. package/dist/server/modules/better-auth/better-auth.controller.js +12 -3
  56. package/dist/server/modules/better-auth/better-auth.controller.js.map +1 -1
  57. package/dist/server/modules/better-auth/better-auth.resolver.d.ts +7 -3
  58. package/dist/server/modules/better-auth/better-auth.resolver.js +16 -6
  59. package/dist/server/modules/better-auth/better-auth.resolver.js.map +1 -1
  60. package/dist/server/modules/error-code/error-codes.d.ts +5 -0
  61. package/dist/server/modules/user/user.model.d.ts +5 -0
  62. package/dist/templates/email-verification-de.ejs +78 -0
  63. package/dist/templates/email-verification-en.ejs +78 -0
  64. package/dist/test/test.helper.d.ts +4 -0
  65. package/dist/test/test.helper.js +54 -1
  66. package/dist/test/test.helper.js.map +1 -1
  67. package/dist/tsconfig.build.tsbuildinfo +1 -1
  68. package/package.json +1 -1
  69. package/src/config.env.ts +2 -0
  70. package/src/core/common/interfaces/server-options.interface.ts +240 -0
  71. package/src/core/modules/better-auth/INTEGRATION-CHECKLIST.md +113 -0
  72. package/src/core/modules/better-auth/README.md +72 -7
  73. package/src/core/modules/better-auth/better-auth.config.ts +168 -42
  74. package/src/core/modules/better-auth/better-auth.resolver.ts +16 -5
  75. package/src/core/modules/better-auth/core-better-auth-api.middleware.ts +65 -8
  76. package/src/core/modules/better-auth/core-better-auth-auth.model.ts +10 -0
  77. package/src/core/modules/better-auth/core-better-auth-email-verification.service.ts +433 -0
  78. package/src/core/modules/better-auth/core-better-auth-models.ts +6 -3
  79. package/src/core/modules/better-auth/core-better-auth-signup-validator.service.ts +178 -0
  80. package/src/core/modules/better-auth/core-better-auth-user.mapper.ts +18 -14
  81. package/src/core/modules/better-auth/core-better-auth-web.helper.ts +53 -40
  82. package/src/core/modules/better-auth/core-better-auth.controller.ts +155 -16
  83. package/src/core/modules/better-auth/core-better-auth.middleware.ts +89 -31
  84. package/src/core/modules/better-auth/core-better-auth.module.ts +215 -38
  85. package/src/core/modules/better-auth/core-better-auth.resolver.ts +140 -20
  86. package/src/core/modules/better-auth/core-better-auth.service.ts +181 -25
  87. package/src/core/modules/better-auth/index.ts +2 -0
  88. package/src/core/modules/error-code/error-codes.ts +45 -0
  89. package/src/core/modules/user/core-user.model.ts +15 -0
  90. package/src/server/modules/better-auth/better-auth.controller.ts +6 -2
  91. package/src/server/modules/better-auth/better-auth.resolver.ts +16 -5
  92. package/src/templates/email-verification-de.ejs +78 -0
  93. package/src/templates/email-verification-en.ejs +78 -0
  94. package/src/test/README.md +190 -0
  95. package/src/test/test.helper.ts +82 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lenne.tech/nest-server",
3
- "version": "11.12.0",
3
+ "version": "11.13.0",
4
4
  "description": "Modern, fast, powerful Node.js web framework in TypeScript based on Nest with a GraphQL API and a connection to MongoDB (or other databases).",
5
5
  "keywords": [
6
6
  "node",
package/src/config.env.ts CHANGED
@@ -125,6 +125,8 @@ const config: { [env: string]: IServerOptions } = {
125
125
  },
126
126
  automaticObjectIdFiltering: true,
127
127
  betterAuth: {
128
+ // Email verification disabled for test environment (no real mailbox available)
129
+ emailVerification: false,
128
130
  // JWT enabled by default (zero-config)
129
131
  jwt: { enabled: true, expiresIn: '15m' },
130
132
  // Passkey auto-activated when URLs can be resolved (env: 'local' → localhost defaults)
@@ -231,6 +231,128 @@ export interface IAuthRateLimit {
231
231
  */
232
232
  export type IBetterAuth = IBetterAuthWithoutPasskey | IBetterAuthWithPasskey;
233
233
 
234
+ /**
235
+ * Email verification configuration for Better-Auth
236
+ *
237
+ * Controls email verification behavior after sign-up.
238
+ * When enabled, users receive a verification email and must verify
239
+ * their email address before certain actions are allowed.
240
+ *
241
+ * **Enabled by Default:** Email verification is enabled by default.
242
+ * Set `emailVerification: false` or `emailVerification: { enabled: false }` to disable.
243
+ *
244
+ * Accepts:
245
+ * - `undefined`: Enabled with defaults (zero-config)
246
+ * - `true` or `{}`: Enable with defaults (same as undefined)
247
+ * - `{ locale: 'de', ... }`: Enable with custom settings
248
+ * - `false` or `{ enabled: false }`: Explicitly disable
249
+ *
250
+ * @since 11.13.0
251
+ *
252
+ * @example
253
+ * ```typescript
254
+ * // Default: Email verification enabled
255
+ * betterAuth: {}
256
+ *
257
+ * // Custom configuration
258
+ * betterAuth: {
259
+ * emailVerification: {
260
+ * locale: 'de',
261
+ * autoSignInAfterVerification: true,
262
+ * expiresIn: 86400, // 24 hours in seconds
263
+ * }
264
+ * }
265
+ *
266
+ * // Disable email verification
267
+ * betterAuth: {
268
+ * emailVerification: false,
269
+ * }
270
+ * ```
271
+ */
272
+ export interface IBetterAuthEmailVerificationConfig {
273
+ /**
274
+ * Whether to automatically sign in the user after email verification.
275
+ * @default true
276
+ */
277
+ autoSignInAfterVerification?: boolean;
278
+
279
+ /**
280
+ * Brevo template ID for verification emails.
281
+ * When set and Brevo is configured (config.brevo), verification emails
282
+ * are sent via Brevo's transactional API instead of SMTP/EJS templates.
283
+ *
284
+ * Template variables passed to Brevo:
285
+ * - `name`: User display name
286
+ * - `link`: Verification URL
287
+ * - `appName`: Application name
288
+ * - `expiresIn`: Formatted expiration time
289
+ *
290
+ * @default undefined (uses SMTP/EJS templates)
291
+ */
292
+ brevoTemplateId?: number;
293
+
294
+ /**
295
+ * Frontend callback URL for email verification.
296
+ *
297
+ * When set, the verification link in the email will point to this URL
298
+ * with the token as a query parameter (e.g., `{callbackURL}?token=xxx`).
299
+ * The frontend page should then call the backend verify-email endpoint
300
+ * to complete verification.
301
+ *
302
+ * Supports both absolute URLs and relative paths:
303
+ * - Absolute: `https://example.com/auth/verify-email`
304
+ * - Relative: `/auth/verify-email` (resolved against `appUrl`)
305
+ *
306
+ * When not set, the verification link points directly to the backend
307
+ * endpoint which handles verification and redirects.
308
+ *
309
+ * @default undefined (backend-handled verification)
310
+ * @since 11.13.0
311
+ */
312
+ callbackURL?: string;
313
+
314
+ /**
315
+ * Whether email verification is enabled.
316
+ * @default true (enabled by default when BetterAuth is active)
317
+ */
318
+ enabled?: boolean;
319
+
320
+ /**
321
+ * Time in seconds until the verification link expires.
322
+ * @default 86400 (24 hours)
323
+ */
324
+ expiresIn?: number;
325
+
326
+ /**
327
+ * Locale for the verification email template.
328
+ * Used to select the correct language template.
329
+ * @default 'en'
330
+ */
331
+ locale?: string;
332
+
333
+ /**
334
+ * Cooldown in seconds between resend requests for the same email address.
335
+ * Prevents abuse by limiting how often verification emails can be resent.
336
+ * Applied per email address in-memory.
337
+ *
338
+ * @default 60
339
+ * @since 11.13.0
340
+ */
341
+ resendCooldownSeconds?: number;
342
+
343
+ /**
344
+ * Custom template name for the verification email.
345
+ * The system looks for templates in this order:
346
+ * 1. `<template>-<locale>.ejs` in project templates
347
+ * 2. `<template>.ejs` in project templates
348
+ * 3. `<template>-<locale>.ejs` in nest-server templates (fallback)
349
+ * 4. `<template>.ejs` in nest-server templates (fallback)
350
+ *
351
+ * @default 'email-verification'
352
+ */
353
+ template?: string;
354
+ }
355
+
234
356
  /**
235
357
  * JWT plugin configuration for Better-Auth
236
358
  *
@@ -426,6 +548,59 @@ export interface IBetterAuthRateLimit {
426
548
  windowSeconds?: number;
427
549
  }
428
550
 
551
+ /**
552
+ * Sign-up checks configuration for Better-Auth
553
+ *
554
+ * Controls which fields are required during sign-up.
555
+ * This is useful for enforcing terms acceptance, age verification, etc.
556
+ *
557
+ * **Enabled by Default:** Sign-up checks are enabled by default with
558
+ * `requiredFields: ['termsAndPrivacyAccepted']`.
559
+ *
560
+ * Accepts:
561
+ * - `undefined`: Enabled with defaults (`termsAndPrivacyAccepted` required)
562
+ * - `true` or `{}`: Enable with defaults (same as undefined)
563
+ * - `{ requiredFields: [...] }`: Enable with custom required fields
564
+ * - `false` or `{ enabled: false }`: Disable sign-up checks entirely
565
+ *
566
+ * @since 11.13.0
567
+ *
568
+ * @example
569
+ * ```typescript
570
+ * // Default: termsAndPrivacyAccepted is required
571
+ * betterAuth: {}
572
+ *
573
+ * // Custom required fields
574
+ * betterAuth: {
575
+ * signUpChecks: {
576
+ * requiredFields: ['termsAndPrivacyAccepted', 'ageConfirmed'],
577
+ * }
578
+ * }
579
+ *
580
+ * // Disable sign-up checks (no fields required)
581
+ * betterAuth: {
582
+ * signUpChecks: false,
583
+ * }
584
+ * ```
585
+ */
586
+ export interface IBetterAuthSignUpChecksConfig {
587
+ /**
588
+ * Whether sign-up checks are enabled.
589
+ * @default true (enabled by default when BetterAuth is active)
590
+ */
591
+ enabled?: boolean;
592
+
593
+ /**
594
+ * Fields that must be provided and truthy during sign-up.
595
+ * If a required field is missing or falsy, sign-up will fail.
596
+ *
597
+ * @default ['termsAndPrivacyAccepted']
598
+ *
599
+ * @example ['termsAndPrivacyAccepted', 'ageConfirmed', 'newsletterOptIn']
600
+ */
601
+ requiredFields?: string[];
602
+ }
603
+
429
604
  /**
430
605
  * Interface for better-auth social provider configuration
431
606
  *
@@ -1498,6 +1673,39 @@ interface IBetterAuthBase {
1498
1673
  enabled?: boolean;
1499
1674
  };
1500
1675
 
1676
+ /**
1677
+ * Email verification configuration.
1678
+ *
1679
+ * **Enabled by Default:** Email verification is enabled by default.
1680
+ * Users receive a verification email after sign-up.
1681
+ *
1682
+ * Accepts:
1683
+ * - `undefined`: Enabled with defaults (zero-config)
1684
+ * - `true` or `{}`: Enable with defaults (same as undefined)
1685
+ * - `{ locale: 'de', ... }`: Enable with custom settings
1686
+ * - `false` or `{ enabled: false }`: Explicitly disable
1687
+ *
1688
+ * @default undefined (enabled by default)
1689
+ * @since 11.13.0
1690
+ *
1691
+ * @example
1692
+ * ```typescript
1693
+ * // Email verification enabled by default - no config needed
1694
+ *
1695
+ * // Custom configuration
1696
+ * betterAuth: {
1697
+ * emailVerification: {
1698
+ * locale: 'de',
1699
+ * autoSignInAfterVerification: true,
1700
+ * }
1701
+ * }
1702
+ *
1703
+ * // Disable email verification
1704
+ * betterAuth: { emailVerification: false }
1705
+ * ```
1706
+ */
1707
+ emailVerification?: boolean | IBetterAuthEmailVerificationConfig;
1708
+
1501
1709
  /**
1502
1710
  * Whether better-auth is enabled.
1503
1711
  *
@@ -1631,6 +1839,38 @@ interface IBetterAuthBase {
1631
1839
  */
1632
1840
  secret?: string;
1633
1841
 
1842
+ /**
1843
+ * Sign-up checks configuration.
1844
+ *
1845
+ * **Enabled by Default:** Sign-up checks are enabled by default with
1846
+ * `requiredFields: ['termsAndPrivacyAccepted']`.
1847
+ *
1848
+ * Accepts:
1849
+ * - `undefined`: Enabled with defaults (termsAndPrivacyAccepted required)
1850
+ * - `true` or `{}`: Enable with defaults (same as undefined)
1851
+ * - `{ requiredFields: [...] }`: Enable with custom required fields
1852
+ * - `false` or `{ enabled: false }`: Disable sign-up checks entirely
1853
+ *
1854
+ * @default undefined (enabled by default)
1855
+ * @since 11.13.0
1856
+ *
1857
+ * @example
1858
+ * ```typescript
1859
+ * // Default: termsAndPrivacyAccepted is required during sign-up
1860
+ *
1861
+ * // Custom required fields
1862
+ * betterAuth: {
1863
+ * signUpChecks: {
1864
+ * requiredFields: ['termsAndPrivacyAccepted', 'ageConfirmed'],
1865
+ * }
1866
+ * }
1867
+ *
1868
+ * // Disable sign-up checks (no fields required)
1869
+ * betterAuth: { signUpChecks: false }
1870
+ * ```
1871
+ */
1872
+ signUpChecks?: boolean | IBetterAuthSignUpChecksConfig;
1873
+
1634
1874
  /**
1635
1875
  * Social login providers configuration
1636
1876
  * Supports all Better-Auth providers dynamically (google, github, apple, discord, etc.)
@@ -58,6 +58,8 @@ GraphQL schema is built from decorators at compile time. The parent class (`Core
58
58
 
59
59
  **Note:** `@UseGuards(AuthGuard(JWT))` is NOT needed when using `@Roles(S_USER)` or `@Roles(ADMIN)` because `RolesGuard` already extends `AuthGuard(JWT)` internally.
60
60
 
61
+ **Sign-Up Validation (v11.13.0+):** The resolver includes `CoreBetterAuthSignUpValidatorService` injection with `@Optional()`. This enables the `termsAndPrivacyAccepted` parameter on the `betterAuthSignUp` mutation.
62
+
61
63
  ---
62
64
 
63
65
  ### 4. Update UserService (CRITICAL!)
@@ -178,6 +180,103 @@ const config = {
178
180
 
179
181
  ---
180
182
 
183
+ ## Email Verification (v11.13.0+)
184
+
185
+ Email verification is **enabled by default** via Better-Auth's `emailVerification` plugin.
186
+
187
+ ### Default Behavior
188
+
189
+ - Users receive a verification email after sign-up
190
+ - Email contains a verification link with token
191
+ - After verification, `verifiedAt` is automatically set on the user
192
+ - Templates are provided in German and English
193
+
194
+ ### Configuration
195
+
196
+ ```typescript
197
+ const config = {
198
+ betterAuth: {
199
+ // Email verification is enabled by default
200
+ // To customize:
201
+ emailVerification: {
202
+ expiresIn: 86400, // Token expiration in seconds (default: 24h)
203
+ template: 'custom-verify', // Custom template name
204
+ locale: 'en', // Template locale (default: 'de')
205
+ },
206
+ // To disable:
207
+ emailVerification: false,
208
+ },
209
+ };
210
+ ```
211
+
212
+ ### Custom Email Templates
213
+
214
+ Create custom templates in your project's templates directory:
215
+ - `templates/email-verification-de.ejs` - German
216
+ - `templates/email-verification-en.ejs` - English
217
+
218
+ Available variables: `name`, `link`, `expiresIn`, `appName`
219
+
220
+ ---
221
+
222
+ ## Sign-Up Checks (v11.13.0+)
223
+
224
+ Sign-up validation is **enabled by default** requiring `termsAndPrivacyAccepted`.
225
+
226
+ ### Default Behavior
227
+
228
+ - `termsAndPrivacyAccepted: true` is required for sign-up
229
+ - When accepted, `termsAndPrivacyAcceptedAt` is stored in the user record
230
+ - Sign-up fails with error `LTNS_0021` if not accepted
231
+
232
+ ### GraphQL Usage
233
+
234
+ ```graphql
235
+ mutation {
236
+ betterAuthSignUp(
237
+ email: "user@example.com"
238
+ password: "hashedPassword"
239
+ name: "User Name"
240
+ termsAndPrivacyAccepted: true # Required by default
241
+ ) {
242
+ success
243
+ user { id email }
244
+ }
245
+ }
246
+ ```
247
+
248
+ ### Configuration
249
+
250
+ ```typescript
251
+ const config = {
252
+ betterAuth: {
253
+ // Sign-up checks are enabled by default
254
+ // To customize required fields:
255
+ signUpChecks: {
256
+ requiredFields: ['termsAndPrivacyAccepted', 'ageConfirmed'],
257
+ },
258
+ // To disable all sign-up checks:
259
+ signUpChecks: false,
260
+ },
261
+ };
262
+ ```
263
+
264
+ ### REST API
265
+
266
+ For REST sign-up, include `termsAndPrivacyAccepted` in the request body:
267
+
268
+ ```json
269
+ POST /iam/sign-up/email
270
+ {
271
+ "email": "user@example.com",
272
+ "password": "hashedPassword",
273
+ "name": "User Name",
274
+ "termsAndPrivacyAccepted": true
275
+ }
276
+ ```
277
+
278
+ ---
279
+
181
280
  ## Verification Checklist
182
281
 
183
282
  After integration, verify:
@@ -189,6 +288,16 @@ After integration, verify:
189
288
  - [ ] Sign-up via BetterAuth creates user in database with `iamId`
190
289
  - [ ] Sign-in via BetterAuth works correctly
191
290
 
291
+ ### Additional checks for v11.13.0+ features:
292
+ - [ ] Sign-up without `termsAndPrivacyAccepted` returns error `LTNS_0021`
293
+ - [ ] Sign-up with `termsAndPrivacyAccepted: true` succeeds
294
+ - [ ] User record contains `termsAndPrivacyAcceptedAt` timestamp after sign-up
295
+ - [ ] Email verification link is sent after sign-up (check console in local mode)
296
+ - [ ] After clicking verification link, `verifiedAt` is set on user
297
+ - [ ] Passkey login returns user data in response (verify enrichment works)
298
+ - [ ] Passkey login redirects to dashboard after successful authentication
299
+ - [ ] Passkey can be registered, listed, and deleted from security settings
300
+
192
301
  ### Additional checks for Migration scenario:
193
302
  - [ ] Sign-in via Legacy Auth works for BetterAuth-created users
194
303
  - [ ] Sign-in via BetterAuth works for Legacy-created users
@@ -206,6 +315,8 @@ After integration, verify:
206
315
  | Wrong `basePath` in config | 404 on BetterAuth endpoints | Ensure basePath matches controller (default: `/iam`) |
207
316
  | Using wrong CoreModule signature | Build errors or missing features | New projects: 1-parameter, Existing: 3-parameter |
208
317
  | AuthResolver override missing `checkLegacyGraphQLEnabled()` | Legacy endpoint disabling doesn't work (no HTTP 410) | Call `this.checkLegacyGraphQLEnabled('signIn')` in overrides |
318
+ | Missing `signUpValidator` in custom Resolver (v11.13.0+) | Sign-up validation not working | Add `@Optional() signUpValidator?: CoreBetterAuthSignUpValidatorService` to constructor and pass to `super()` |
319
+ | Missing `termsAndPrivacyAccepted` parameter in Resolver (v11.13.0+) | GraphQL error "Unknown argument" | Add `@Args('termsAndPrivacyAccepted', { nullable: true })` to `betterAuthSignUp` method |
209
320
 
210
321
  ---
211
322
 
@@ -361,6 +472,8 @@ Handle passkey authentication with session validation fallback.
361
472
 
362
473
  **IMPORTANT:** For JWT mode (`cookies: false`), you MUST use the `authenticateWithPasskey()` function from the composable instead of `authClient.signIn.passkey()` directly. This is because JWT mode requires sending a `challengeId` to the server for challenge verification.
363
474
 
475
+ **Note on Passkey Login Response (v11.13.0+):** The server enriches the passkey verify-authentication response with user data. Better Auth's passkey plugin only returns `{ session }`, but the server fetches the user from the database and adds it to the response. The composable handles both scenarios (user in response vs. fallback to get-session).
476
+
364
477
  ```typescript
365
478
  // login.vue - Passkey login (JWT-compatible)
366
479
  // Use authenticateWithPasskey from useBetterAuth composable
@@ -48,6 +48,8 @@ const config = {
48
48
  - **JWT Tokens** - For API clients and stateless authentication (**enabled by default**)
49
49
  - **Two-Factor Authentication (2FA)** - TOTP-based second factor (**enabled by default**)
50
50
  - **Passkey/WebAuthn** - Passwordless authentication (**enabled by default**, requires resolvable URLs)
51
+ - **Email Verification** - Verify user email addresses (**enabled by default** since v11.13.0)
52
+ - **Sign-Up Checks** - Validate sign-up requirements like `termsAndPrivacyAccepted` (**enabled by default** since v11.13.0)
51
53
 
52
54
  ### Core Features
53
55
 
@@ -497,6 +499,66 @@ export default {
497
499
 
498
500
  ## Advanced Configuration
499
501
 
502
+ ### Email Verification (v11.13.0+)
503
+
504
+ Email verification is **enabled by default**. Users receive a verification email after sign-up and `verifiedAt` is automatically set when verified.
505
+
506
+ ```typescript
507
+ const config = {
508
+ betterAuth: {
509
+ // Email verification is enabled by default
510
+ // To customize:
511
+ emailVerification: {
512
+ expiresIn: 86400, // Token expiration in seconds (default: 24h)
513
+ template: 'custom-verify', // Custom template name
514
+ locale: 'en', // Template locale (default: 'de')
515
+ brevoTemplateId: 42, // Send via Brevo transactional API (optional)
516
+ },
517
+ // To disable:
518
+ emailVerification: false,
519
+ },
520
+ };
521
+ ```
522
+
523
+ **Custom Templates:** Create `templates/email-verification-{locale}.ejs` in your project. Available variables: `name`, `link`, `expiresIn`, `appName`.
524
+
525
+ **Brevo Integration:** When `brevoTemplateId` is set and Brevo is configured (`config.brevo`), verification emails are sent via Brevo's transactional API instead of SMTP/EJS templates. The same template variables (`name`, `link`, `appName`, `expiresIn`) are passed to the Brevo template.
526
+
527
+ ### Sign-Up Checks (v11.13.0+)
528
+
529
+ Sign-up validation is **enabled by default** requiring `termsAndPrivacyAccepted: true`.
530
+
531
+ ```typescript
532
+ const config = {
533
+ betterAuth: {
534
+ // Sign-up checks are enabled by default
535
+ // To customize required fields:
536
+ signUpChecks: {
537
+ requiredFields: ['termsAndPrivacyAccepted', 'ageConfirmed'],
538
+ },
539
+ // To disable all sign-up checks:
540
+ signUpChecks: false,
541
+ },
542
+ };
543
+ ```
544
+
545
+ When `termsAndPrivacyAccepted: true` is provided, `termsAndPrivacyAcceptedAt` is automatically stored in the user record.
546
+
547
+ **GraphQL Example:**
548
+ ```graphql
549
+ mutation {
550
+ betterAuthSignUp(
551
+ email: "user@example.com"
552
+ password: "hashedPassword"
553
+ name: "User"
554
+ termsAndPrivacyAccepted: true # Required by default
555
+ ) {
556
+ success
557
+ user { id email }
558
+ }
559
+ }
560
+ ```
561
+
500
562
  ### Email/Password Authentication
501
563
 
502
564
  Email/password authentication is enabled by default. You can disable it if you only want social login:
@@ -939,12 +1001,14 @@ In addition to REST endpoints, Better-Auth provides GraphQL queries and mutation
939
1001
 
940
1002
  #### Authentication
941
1003
 
942
- | Mutation | Arguments | Return Type | Description |
943
- | --------------------- | ---------------------------- | -------------------- | ------------------------- |
944
- | `betterAuthSignIn` | `email`, `password` | `BetterAuthAuthModel`| Sign in with email/pass |
945
- | `betterAuthSignUp` | `email`, `password`, `name?` | `BetterAuthAuthModel`| Register new account |
946
- | `betterAuthSignOut` | - | `Boolean` | Sign out (requires auth) |
947
- | `betterAuthVerify2FA` | `code` | `BetterAuthAuthModel`| Verify 2FA code |
1004
+ | Mutation | Arguments | Return Type | Description |
1005
+ | --------------------- | -------------------------------------------- | -------------------- | ------------------------- |
1006
+ | `betterAuthSignIn` | `email`, `password` | `BetterAuthAuthModel`| Sign in with email/pass |
1007
+ | `betterAuthSignUp` | `email`, `password`, `name?`, `termsAndPrivacyAccepted?` | `BetterAuthAuthModel`| Register new account |
1008
+ | `betterAuthSignOut` | - | `Boolean` | Sign out (requires auth) |
1009
+ | `betterAuthVerify2FA` | `code` | `BetterAuthAuthModel`| Verify 2FA code |
1010
+
1011
+ **Note (v11.13.0+):** `termsAndPrivacyAccepted` is required by default. Set `signUpChecks: false` to disable.
948
1012
 
949
1013
  #### 2FA Management (requires authentication)
950
1014
 
@@ -1054,12 +1118,13 @@ mutation {
1054
1118
  }
1055
1119
  }
1056
1120
 
1057
- # Sign up
1121
+ # Sign up (v11.13.0+: termsAndPrivacyAccepted required by default)
1058
1122
  mutation {
1059
1123
  betterAuthSignUp(
1060
1124
  email: "newuser@example.com"
1061
1125
  password: "securePassword123"
1062
1126
  name: "New User"
1127
+ termsAndPrivacyAccepted: true
1063
1128
  ) {
1064
1129
  success
1065
1130
  user {