@maka/maka-cli 5.1.45 → 5.1.46

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 (42) hide show
  1. package/.claude/settings.local.json +3 -1
  2. package/bundle/typescript/package.json +1 -1
  3. package/bundle/typescript/src/commands/ai/mcp.sub.cmd.js +118 -5
  4. package/bundle/typescript/src/commands/ai/mcp.sub.cmd.js.map +1 -1
  5. package/bundle/typescript/src/commands/create.js +2 -2
  6. package/bundle/typescript/src/commands/create.js.map +1 -1
  7. package/bundle/typescript/src/commands/run/run.command.js +0 -5
  8. package/bundle/typescript/src/commands/run/run.command.js.map +1 -1
  9. package/bundle/typescript/src/generators/kits/auth/_index.d.ts +1 -0
  10. package/bundle/typescript/src/generators/kits/auth/_index.js +1 -0
  11. package/bundle/typescript/src/generators/kits/auth/_index.js.map +1 -1
  12. package/bundle/typescript/src/generators/kits/auth/auth0-meteor.auth.gen.d.ts +1 -0
  13. package/bundle/typescript/src/generators/kits/auth/auth0-meteor.auth.gen.js +704 -0
  14. package/bundle/typescript/src/generators/kits/auth/auth0-meteor.auth.gen.js.map +1 -0
  15. package/bundle/typescript/src/generators/kits/auth/basic-meteor.auth.gen.js +2 -2
  16. package/bundle/typescript/src/generators/kits/auth/basic-meteor.auth.gen.js.map +1 -1
  17. package/bundle/typescript/src/generators/kits/mui/_index.d.ts +1 -0
  18. package/bundle/typescript/src/generators/kits/mui/_index.js +1 -0
  19. package/bundle/typescript/src/generators/kits/mui/_index.js.map +1 -1
  20. package/bundle/typescript/src/generators/kits/mui/auth0.mui.gen.d.ts +2 -0
  21. package/bundle/typescript/src/generators/kits/mui/auth0.mui.gen.js +158 -0
  22. package/bundle/typescript/src/generators/kits/mui/auth0.mui.gen.js.map +1 -0
  23. package/bundle/typescript/src/generators/publish.js +2 -6
  24. package/bundle/typescript/src/generators/publish.js.map +1 -1
  25. package/bundle/typescript/src/templates/react/kit/auth/service/auth0-client.js.jsx +141 -0
  26. package/bundle/typescript/src/templates/react/kit/auth/service/auth0-client.js.tsx +141 -0
  27. package/bundle/typescript/src/templates/react/kit/auth/service/auth0-config.js.jsx +46 -0
  28. package/bundle/typescript/src/templates/react/kit/auth/service/auth0-config.js.tsx +54 -0
  29. package/bundle/typescript/src/templates/react/kit/auth/service/auth0-methods.js.jsx +152 -0
  30. package/bundle/typescript/src/templates/react/kit/auth/service/auth0-methods.js.tsx +152 -0
  31. package/bundle/typescript/src/templates/react/kit/auth/service/auth0-validator.js.jsx +143 -0
  32. package/bundle/typescript/src/templates/react/kit/auth/service/auth0-validator.js.tsx +158 -0
  33. package/bundle/typescript/src/templates/react/kit/mui/auth0/auth-callback.js.jsx +71 -0
  34. package/bundle/typescript/src/templates/react/kit/mui/auth0/auth-callback.js.tsx +71 -0
  35. package/bundle/typescript/src/templates/react/kit/mui/auth0/auth0-account-settings.js.jsx +123 -0
  36. package/bundle/typescript/src/templates/react/kit/mui/auth0/auth0-account-settings.js.tsx +123 -0
  37. package/bundle/typescript/src/templates/react/kit/mui/auth0/auth0-login-button.js.jsx +56 -0
  38. package/bundle/typescript/src/templates/react/kit/mui/auth0/auth0-login-button.js.tsx +74 -0
  39. package/bundle/typescript/src/tools/scaffold/scaffold.class.d.ts +2 -1
  40. package/bundle/typescript/src/tools/scaffold/scaffold.class.js +12 -6
  41. package/bundle/typescript/src/tools/scaffold/scaffold.class.js.map +1 -1
  42. package/package.json +1 -1
@@ -0,0 +1,704 @@
1
+ import path from 'path';
2
+ import { Generator } from '../../../generator.js';
3
+ import { Log } from '../../../tools/log/log.class.js';
4
+ import AuthGen from './auth.generator.js';
5
+ import MakaGen from '../../../generators/maka.gen.js';
6
+ import { ClientEngines, } from '../../../tools/fsi/fsi.interfaces.js';
7
+ Generator.create({
8
+ name: 'auth0',
9
+ aliases: ['a0'],
10
+ usage: 'maka {generate, g}:{kit, k}:{auth, a}:{auth0, a0}',
11
+ shortDesc: 'Generate Auth0 authentication integration with Meteor accounts',
12
+ validOpts: [{
13
+ name: 'force',
14
+ boolFlag: true,
15
+ description: 'Overwrite existing files'
16
+ }],
17
+ isPro: true,
18
+ resourceNameRequired: false,
19
+ mustBeInMakaProject: true,
20
+ requiredEngines: {
21
+ client: ClientEngines.REACT,
22
+ },
23
+ description: `
24
+ This kit generates an Auth0 authentication integration for your Meteor application.
25
+
26
+ It includes:
27
+ - Auth0 client SDK configuration
28
+ - Server-side JWT token validation with JWKS
29
+ - Account linking between Auth0 and Meteor
30
+ - Seamless integration with existing authentication provider
31
+ `
32
+ }, async function (args, opts) {
33
+ const { fsi, pkg, scaffold, projectConfig } = this;
34
+ try {
35
+ const shouldForce = opts.force || false;
36
+ const projectDirectory = fsi.findProjectDirectory();
37
+ const appPath = fsi.findAppDirectory();
38
+ const isSsr = projectConfig.engines.ssr === 'meteor';
39
+ const jsEngine = projectConfig.engines.js;
40
+ Log.info('Setting up Auth0 authentication...');
41
+ // Install required npm packages
42
+ Log.info('Installing Auth0 dependencies...');
43
+ await pkg.checkNpmPackage(['@auth0/auth0-spa-js', 'jsonwebtoken', 'jwks-rsa'], { shouldInstall: true });
44
+ // Ensure auth provider exists
45
+ await MakaGen.processAndRunGenerator('kit:auth:provider', [], { force: shouldForce, cwd: projectDirectory, config: projectConfig });
46
+ // Ensure auth/roles publish exists
47
+ await MakaGen.processAndRunGenerator('publish', ['auth/roles'], { force: shouldForce, globalPublish: true, cwd: projectDirectory, config: projectConfig });
48
+ const resourceTopLevelPathLib = '/imports/startup/lib';
49
+ const resourceTopLevelPathClient = isSsr ? '/imports/startup/lib' : '/imports/startup/client';
50
+ const resourceTopLevelPathServer = '/imports/startup/server';
51
+ // ===================================================================================
52
+ // 1. Generate Auth0 Configuration (Shared)
53
+ // ===================================================================================
54
+ const pathToAuth0Config = scaffold.pathFromApp({
55
+ pathParts: [
56
+ resourceTopLevelPathLib,
57
+ '',
58
+ '',
59
+ 'auth0-config'
60
+ ]
61
+ });
62
+ await scaffold.template({
63
+ srcPath: `kit/auth/service/auth0-config.js`,
64
+ destPath: `${pathToAuth0Config}.${jsEngine}`,
65
+ framework: 'react',
66
+ context: {},
67
+ config: projectConfig,
68
+ force: shouldForce,
69
+ ignore: false
70
+ });
71
+ // ===================================================================================
72
+ // 2. Generate Auth0 Client (Client-side)
73
+ // ===================================================================================
74
+ const pathToAuth0Client = scaffold.pathFromApp({
75
+ pathParts: [
76
+ resourceTopLevelPathClient,
77
+ '',
78
+ '',
79
+ 'auth0-client'
80
+ ]
81
+ });
82
+ await scaffold.template({
83
+ srcPath: `kit/auth/service/auth0-client.js`,
84
+ destPath: `${pathToAuth0Client}.${jsEngine}`,
85
+ framework: 'react',
86
+ context: {},
87
+ config: projectConfig,
88
+ force: shouldForce,
89
+ ignore: false
90
+ });
91
+ // ===================================================================================
92
+ // 3. Generate Auth0 Validator (Server-side)
93
+ // ===================================================================================
94
+ const pathToAuth0Validator = scaffold.pathFromApp({
95
+ pathParts: [
96
+ resourceTopLevelPathServer,
97
+ '',
98
+ '',
99
+ 'auth0-validator'
100
+ ]
101
+ });
102
+ await scaffold.template({
103
+ srcPath: `kit/auth/service/auth0-validator.js`,
104
+ destPath: `${pathToAuth0Validator}.${jsEngine}`,
105
+ framework: 'react',
106
+ context: {},
107
+ config: projectConfig,
108
+ force: shouldForce,
109
+ ignore: false
110
+ });
111
+ // ===================================================================================
112
+ // 4. Generate Auth0 Methods (Server-side)
113
+ // ===================================================================================
114
+ const pathToAuth0Methods = scaffold.pathFromApp({
115
+ pathParts: [
116
+ resourceTopLevelPathServer,
117
+ 'methods',
118
+ '',
119
+ 'auth0-methods'
120
+ ]
121
+ });
122
+ await scaffold.template({
123
+ srcPath: `kit/auth/service/auth0-methods.js`,
124
+ destPath: `${pathToAuth0Methods}.${jsEngine}`,
125
+ framework: 'react',
126
+ context: {},
127
+ config: projectConfig,
128
+ force: shouldForce,
129
+ ignore: false
130
+ });
131
+ // ===================================================================================
132
+ // 5. Update authentication-service with Auth0 methods
133
+ // ===================================================================================
134
+ const pathToAuthService = scaffold.pathFromApp({
135
+ pathParts: [
136
+ resourceTopLevelPathClient,
137
+ '',
138
+ '',
139
+ 'authentication-service'
140
+ ]
141
+ });
142
+ // Import Auth0 client functions
143
+ await scaffold.injectAtBeginningOfFile({
144
+ filePath: `${pathToAuthService}.${jsEngine}`,
145
+ content: `import {
146
+ loginWithAuth0Redirect,
147
+ loginWithAuth0Popup,
148
+ handleAuth0Callback,
149
+ logoutAuth0,
150
+ getAuth0IdToken,
151
+ } from './auth0-client';
152
+ `
153
+ });
154
+ // Add Auth0 methods to AuthService class
155
+ const auth0Methods = `
156
+ // ============================================================================
157
+ // Auth0 Authentication Methods
158
+ // ============================================================================
159
+
160
+ /**
161
+ * Login with Auth0 using redirect flow
162
+ * User will be redirected to Auth0 login page
163
+ */
164
+ static async loginWithAuth0Redirect() {
165
+ try {
166
+ await loginWithAuth0Redirect();
167
+ } catch (error) {
168
+ console.error('Auth0 redirect login failed:', error);
169
+ throw error;
170
+ }
171
+ }
172
+
173
+ /**
174
+ * Login with Auth0 using popup flow
175
+ * Returns the authenticated Meteor user
176
+ */
177
+ static async loginWithAuth0Popup() {
178
+ try {
179
+ // Open Auth0 login popup and get ID token
180
+ const idToken = await loginWithAuth0Popup();
181
+
182
+ // Call Meteor method to validate token and create/link user
183
+ const result = await Meteor.callAsync('auth0.login', idToken);
184
+
185
+ // Login to Meteor with the generated token
186
+ return new Promise((resolve, reject) => {
187
+ Meteor.loginWithToken(result.token, (error) => {
188
+ if (error) {
189
+ reject(error);
190
+ } else {
191
+ resolve(Meteor.user());
192
+ }
193
+ });
194
+ });
195
+ } catch (error) {
196
+ console.error('Auth0 popup login failed:', error);
197
+ throw error;
198
+ }
199
+ }
200
+
201
+ /**
202
+ * Handle Auth0 callback after redirect
203
+ * Call this method on your callback page
204
+ */
205
+ static async handleAuth0Callback() {
206
+ try {
207
+ // Handle the redirect and get ID token
208
+ const idToken = await handleAuth0Callback();
209
+
210
+ // Call Meteor method to validate token and create/link user
211
+ const result = await Meteor.callAsync('auth0.login', idToken);
212
+
213
+ // Login to Meteor with the generated token
214
+ return new Promise((resolve, reject) => {
215
+ Meteor.loginWithToken(result.token, (error) => {
216
+ if (error) {
217
+ reject(error);
218
+ } else {
219
+ resolve(Meteor.user());
220
+ }
221
+ });
222
+ });
223
+ } catch (error) {
224
+ console.error('Auth0 callback handling failed:', error);
225
+ throw error;
226
+ }
227
+ }
228
+
229
+ /**
230
+ * Link Auth0 account to currently logged in Meteor user
231
+ */
232
+ static async linkAuth0Account() {
233
+ try {
234
+ // Get current Auth0 ID token
235
+ const idToken = await getAuth0IdToken();
236
+
237
+ // Call Meteor method to link accounts
238
+ await Meteor.callAsync('auth0.linkAccount', idToken);
239
+
240
+ return true;
241
+ } catch (error) {
242
+ console.error('Auth0 account linking failed:', error);
243
+ throw error;
244
+ }
245
+ }
246
+
247
+ /**
248
+ * Unlink Auth0 account from current user
249
+ */
250
+ static async unlinkAuth0Account() {
251
+ try {
252
+ await Meteor.callAsync('auth0.unlinkAccount');
253
+ return true;
254
+ } catch (error) {
255
+ console.error('Auth0 account unlinking failed:', error);
256
+ throw error;
257
+ }
258
+ }
259
+
260
+ /**
261
+ * Logout from both Auth0 and Meteor
262
+ */
263
+ static async logoutAuth0() {
264
+ try {
265
+ // Logout from Meteor first
266
+ await this.deauthenticateUser();
267
+
268
+ // Then logout from Auth0
269
+ await logoutAuth0();
270
+ } catch (error) {
271
+ console.error('Auth0 logout failed:', error);
272
+ throw error;
273
+ }
274
+ }
275
+ `;
276
+ await scaffold.injectIntoFile({
277
+ filePath: `${pathToAuthService}.${jsEngine}`,
278
+ content: auth0Methods,
279
+ begin: 'static async resetPasswordWithToken',
280
+ end: '}\n\nexport default AuthService',
281
+ replace: false
282
+ });
283
+ // ===================================================================================
284
+ // 6. Update authentication-provider with Auth0 context methods
285
+ // ===================================================================================
286
+ const pathToAuthProvider = scaffold.pathFromApp({
287
+ pathParts: [
288
+ resourceTopLevelPathClient,
289
+ '',
290
+ '',
291
+ 'authentication-provider'
292
+ ]
293
+ });
294
+ // Import AuthService if not already imported
295
+ await scaffold.injectAtBeginningOfFile({
296
+ filePath: `${pathToAuthProvider}.${jsEngine}`,
297
+ content: `import AuthService from './authentication-service';
298
+ `
299
+ });
300
+ // Add Auth0 methods to context value
301
+ const auth0ProviderMethods = ` loginWithAuth0Redirect: AuthService.loginWithAuth0Redirect,
302
+ loginWithAuth0Popup: AuthService.loginWithAuth0Popup,
303
+ linkAuth0Account: AuthService.linkAuth0Account,
304
+ unlinkAuth0Account: AuthService.unlinkAuth0Account,
305
+ `;
306
+ await scaffold.injectIntoFile({
307
+ filePath: `${pathToAuthProvider}.${jsEngine}`,
308
+ content: auth0ProviderMethods,
309
+ begin: 'const contextValue = useMemo\\(\\(\\) => \\(\\{',
310
+ end: '\\}\\), \\[',
311
+ replace: false
312
+ });
313
+ // ===================================================================================
314
+ // 7. Import auth0-methods on server startup
315
+ // ===================================================================================
316
+ const serverIndexFilePath = scaffold.pathFromApp({
317
+ pathParts: [
318
+ 'imports',
319
+ 'startup',
320
+ 'server',
321
+ 'index'
322
+ ]
323
+ });
324
+ await scaffold.injectAtEndOfFile({
325
+ filePath: `${serverIndexFilePath}.${jsEngine}`,
326
+ content: `import './methods/auth0-methods';
327
+ `
328
+ });
329
+ // ===================================================================================
330
+ // 8. Create settings.json example file
331
+ // ===================================================================================
332
+ const settingsExamplePath = path.join(projectDirectory, 'settings.auth0.json');
333
+ const settingsExample = {
334
+ public: {
335
+ auth0: {
336
+ domain: 'YOUR_AUTH0_DOMAIN.auth0.com',
337
+ clientId: 'YOUR_AUTH0_CLIENT_ID',
338
+ audience: 'https://YOUR_AUTH0_DOMAIN.auth0.com/api/v2/',
339
+ redirectUri: 'http://localhost:3000/auth/callback',
340
+ scope: 'openid profile email'
341
+ }
342
+ },
343
+ auth0: {
344
+ domain: 'YOUR_AUTH0_DOMAIN.auth0.com',
345
+ clientId: 'YOUR_AUTH0_CLIENT_ID',
346
+ clientSecret: 'YOUR_AUTH0_CLIENT_SECRET',
347
+ audience: 'https://YOUR_AUTH0_DOMAIN.auth0.com/api/v2/',
348
+ redirectUri: 'http://localhost:3000/auth/callback',
349
+ scope: 'openid profile email'
350
+ }
351
+ };
352
+ if (!fsi.isFile(settingsExamplePath) || shouldForce) {
353
+ fsi.writeToFile({
354
+ filePath: settingsExamplePath,
355
+ data: JSON.stringify(settingsExample, null, 2)
356
+ });
357
+ }
358
+ // ===================================================================================
359
+ // 9. Create .env.example file
360
+ // ===================================================================================
361
+ const envExamplePath = path.join(projectDirectory, '.env.auth0.example');
362
+ const envExample = `# Auth0 Configuration
363
+ # Copy this to your settings.json or .env file and fill in your Auth0 credentials
364
+
365
+ AUTH0_DOMAIN=your-domain.auth0.com
366
+ AUTH0_CLIENT_ID=your_client_id
367
+ AUTH0_CLIENT_SECRET=your_client_secret
368
+ AUTH0_AUDIENCE=https://your-domain.auth0.com/api/v2/
369
+ AUTH0_REDIRECT_URI=http://localhost:3000/auth/callback
370
+ AUTH0_SCOPE=openid profile email
371
+ `;
372
+ if (!fsi.isFile(envExamplePath) || shouldForce) {
373
+ fsi.writeToFile({
374
+ filePath: envExamplePath,
375
+ data: envExample
376
+ });
377
+ }
378
+ // ===================================================================================
379
+ // 10. Create README documentation
380
+ // ===================================================================================
381
+ const readmePath = path.join(projectDirectory, 'README.auth0.md');
382
+ const readmeContent = `# Auth0 Authentication Integration
383
+
384
+ This document explains how Auth0 authentication has been integrated into your Meteor application.
385
+
386
+ ## Overview
387
+
388
+ This integration provides a complete Auth0 authentication solution that:
389
+
390
+ - ✅ Supports both redirect and popup login flows
391
+ - ✅ Validates JWT tokens server-side using JWKS
392
+ - ✅ Automatically creates or links Meteor user accounts
393
+ - ✅ Allows account linking for existing users
394
+ - ✅ Provides seamless integration with your existing AuthContext
395
+
396
+ ## Architecture
397
+
398
+ ### Client-Side Components
399
+
400
+ **\`${resourceTopLevelPathLib}/auth0-config.${jsEngine}\`**
401
+ - Centralized Auth0 configuration
402
+ - Reads settings from \`Meteor.settings.public.auth0\`
403
+ - Provides configuration for both client and server
404
+
405
+ **\`${resourceTopLevelPathClient}/auth0-client.${jsEngine}\`**
406
+ - Auth0 SDK wrapper functions
407
+ - Handles login redirects and popups
408
+ - Manages Auth0 client instance
409
+ - Retrieves ID tokens
410
+
411
+ **\`${resourceTopLevelPathClient}/authentication-service.${jsEngine}\`**
412
+ - Extended with Auth0 authentication methods
413
+ - Bridges Auth0 with Meteor accounts
414
+ - Provides static methods for all Auth0 operations
415
+
416
+ **\`${resourceTopLevelPathClient}/authentication-provider.${jsEngine}\`**
417
+ - Context updated with Auth0 methods
418
+ - Makes Auth0 functions available throughout your app
419
+
420
+ ### Server-Side Components
421
+
422
+ **\`${resourceTopLevelPathServer}/auth0-validator.${jsEngine}\`**
423
+ - JWT token validation using JWKS
424
+ - Verifies token signature and claims
425
+ - Creates/updates user accounts from Auth0 data
426
+
427
+ **\`${resourceTopLevelPathServer}/methods/auth0-methods.${jsEngine}\`**
428
+ - Meteor methods for Auth0 operations
429
+ - \`auth0.login\` - Authenticates with ID token
430
+ - \`auth0.linkAccount\` - Links Auth0 to existing user
431
+ - \`auth0.unlinkAccount\` - Removes Auth0 link
432
+
433
+ ## Setup Instructions
434
+
435
+ ### 1. Configure Auth0 Application
436
+
437
+ 1. Go to [Auth0 Dashboard](https://manage.auth0.com/)
438
+ 2. Create a new application (Single Page Application)
439
+ 3. Configure the following settings:
440
+ - **Allowed Callback URLs**: \`http://localhost:3000/auth/callback\`
441
+ - **Allowed Logout URLs**: \`http://localhost:3000\`
442
+ - **Allowed Web Origins**: \`http://localhost:3000\`
443
+ - **Allowed Origins (CORS)**: \`http://localhost:3000\`
444
+
445
+ ### 2. Update Configuration
446
+
447
+ Edit \`settings.auth0.json\` with your Auth0 credentials:
448
+
449
+ \`\`\`json
450
+ {
451
+ "public": {
452
+ "auth0": {
453
+ "domain": "your-domain.auth0.com",
454
+ "clientId": "your_client_id",
455
+ "audience": "https://your-domain.auth0.com/api/v2/",
456
+ "redirectUri": "http://localhost:3000/auth/callback",
457
+ "scope": "openid profile email"
458
+ }
459
+ },
460
+ "auth0": {
461
+ "domain": "your-domain.auth0.com",
462
+ "clientId": "your_client_id",
463
+ "clientSecret": "your_client_secret",
464
+ "audience": "https://your-domain.auth0.com/api/v2/",
465
+ "redirectUri": "http://localhost:3000/auth/callback",
466
+ "scope": "openid profile email"
467
+ }
468
+ }
469
+ \`\`\`
470
+
471
+ ### 3. Start Your Application
472
+
473
+ \`\`\`bash
474
+ cd app
475
+ meteor --settings ../settings.auth0.json
476
+ \`\`\`
477
+
478
+ ## Usage
479
+
480
+ ### Using Auth0 in Components
481
+
482
+ The Auth0 methods are available through the AuthContext:
483
+
484
+ \`\`\`${jsEngine === 'tsx' ? 'typescript' : 'javascript'}
485
+ import React, { useContext } from 'react';
486
+ import { AuthContext } from '${resourceTopLevelPathClient}/authentication-provider';
487
+
488
+ function LoginButton() {
489
+ const auth = useContext(AuthContext);
490
+
491
+ const handleLogin = async () => {
492
+ try {
493
+ // Option 1: Redirect flow (recommended)
494
+ await auth.loginWithAuth0Redirect?.();
495
+
496
+ // Option 2: Popup flow
497
+ // const user = await auth.loginWithAuth0Popup?.();
498
+ // console.log('Logged in user:', user);
499
+ } catch (error) {
500
+ console.error('Login failed:', error);
501
+ }
502
+ };
503
+
504
+ return <button onClick={handleLogin}>Login with Auth0</button>;
505
+ }
506
+ \`\`\`
507
+
508
+ ### Using AuthService Directly
509
+
510
+ You can also use the AuthService static methods:
511
+
512
+ \`\`\`${jsEngine === 'tsx' ? 'typescript' : 'javascript'}
513
+ import AuthService from '${resourceTopLevelPathClient}/authentication-service';
514
+
515
+ // Redirect login
516
+ await AuthService.loginWithAuth0Redirect();
517
+
518
+ // Popup login
519
+ const user = await AuthService.loginWithAuth0Popup();
520
+
521
+ // Handle callback (use in callback page)
522
+ const user = await AuthService.handleAuth0Callback();
523
+
524
+ // Link Auth0 to logged-in user
525
+ await AuthService.linkAuth0Account();
526
+
527
+ // Unlink Auth0 account
528
+ await AuthService.unlinkAuth0Account();
529
+
530
+ // Logout from both Auth0 and Meteor
531
+ await AuthService.logoutAuth0();
532
+ \`\`\`
533
+
534
+ ## Authentication Flow
535
+
536
+ ### Redirect Flow
537
+
538
+ 1. User clicks login button
539
+ 2. \`loginWithAuth0Redirect()\` redirects to Auth0 login page
540
+ 3. User authenticates with Auth0
541
+ 4. Auth0 redirects back to \`/auth/callback\`
542
+ 5. Callback page calls \`handleAuth0Callback()\`
543
+ 6. Server validates JWT and creates/links Meteor user
544
+ 7. User is logged into Meteor and redirected to home page
545
+
546
+ ### Popup Flow
547
+
548
+ 1. User clicks login button
549
+ 2. \`loginWithAuth0Popup()\` opens Auth0 login in popup
550
+ 3. User authenticates with Auth0
551
+ 4. Popup closes and ID token is returned
552
+ 5. Server validates JWT and creates/links Meteor user
553
+ 6. User is logged into Meteor
554
+ 7. Component receives user object
555
+
556
+ ## Account Linking
557
+
558
+ Users can link their Auth0 account to an existing Meteor account:
559
+
560
+ \`\`\`${jsEngine === 'tsx' ? 'typescript' : 'javascript'}
561
+ // User must be logged in first
562
+ const auth = useContext(AuthContext);
563
+ await auth.linkAuth0Account?.();
564
+ \`\`\`
565
+
566
+ This allows users to:
567
+ - Login with either Meteor credentials or Auth0
568
+ - Maintain a single user account with multiple login methods
569
+ - Unlink Auth0 if they no longer want to use it
570
+
571
+ ## User Data Structure
572
+
573
+ When a user logs in with Auth0, their Meteor user document includes:
574
+
575
+ \`\`\`javascript
576
+ {
577
+ _id: "userId",
578
+ emails: [{ address: "user@example.com", verified: true }],
579
+ profile: { name: "John Doe" },
580
+ services: {
581
+ auth0: {
582
+ id: "auth0|123456789",
583
+ email: "user@example.com",
584
+ name: "John Doe",
585
+ picture: "https://...",
586
+ email_verified: true
587
+ }
588
+ }
589
+ }
590
+ \`\`\`
591
+
592
+ ## Security Features
593
+
594
+ - **JWT Validation**: Tokens are verified using Auth0's JWKS endpoint
595
+ - **Token Expiration**: Tokens are checked for expiration
596
+ - **Issuer Verification**: Ensures tokens come from your Auth0 domain
597
+ - **Audience Verification**: Validates tokens are for your application
598
+ - **Account Linking Protection**: Prevents duplicate account linking
599
+
600
+ ## Troubleshooting
601
+
602
+ ### "Invalid token" Error
603
+
604
+ - Check that your Auth0 domain and clientId are correct
605
+ - Verify the token hasn't expired
606
+ - Ensure your Auth0 application settings are configured correctly
607
+
608
+ ### "Auth0 configuration missing" Error
609
+
610
+ - Make sure you're starting Meteor with \`--settings ../settings.auth0.json\`
611
+ - Verify the settings file contains all required Auth0 configuration
612
+
613
+ ### Callback URL Mismatch
614
+
615
+ - Ensure the callback URL in Auth0 dashboard matches your \`redirectUri\`
616
+ - For production, update the callback URL to your production domain
617
+
618
+ ### CORS Errors
619
+
620
+ - Add your domain to "Allowed Web Origins" in Auth0 dashboard
621
+ - Ensure "Allowed Origins (CORS)" includes your domain
622
+
623
+ ## API Reference
624
+
625
+ ### AuthService Methods
626
+
627
+ #### \`loginWithAuth0Redirect()\`
628
+ Redirects user to Auth0 login page. User will leave your application.
629
+
630
+ **Returns**: Promise<void>
631
+
632
+ #### \`loginWithAuth0Popup()\`
633
+ Opens Auth0 login in a popup window. User stays on your application.
634
+
635
+ **Returns**: Promise<User>
636
+
637
+ #### \`handleAuth0Callback()\`
638
+ Handles the OAuth callback after redirect. Call this on your callback page.
639
+
640
+ **Returns**: Promise<User>
641
+
642
+ #### \`linkAuth0Account()\`
643
+ Links Auth0 account to currently logged-in Meteor user.
644
+
645
+ **Returns**: Promise<boolean>
646
+
647
+ **Throws**: Error if user not logged in or account already linked
648
+
649
+ #### \`unlinkAuth0Account()\`
650
+ Removes Auth0 link from current user.
651
+
652
+ **Returns**: Promise<boolean>
653
+
654
+ **Throws**: Error if Auth0 is the only login method
655
+
656
+ #### \`logoutAuth0()\`
657
+ Logs out from both Meteor and Auth0.
658
+
659
+ **Returns**: Promise<void>
660
+
661
+ ## Next Steps
662
+
663
+ 1. **Generate UI Components**: Run \`maka g:k:m:auth0\` to generate MUI login components
664
+ 2. **Customize User Profile**: Add additional user fields from Auth0 token
665
+ 3. **Add Roles**: Integrate with \`alanning:roles\` for authorization
666
+ 4. **Production Setup**: Update callback URLs for production domain
667
+ 5. **Social Connections**: Enable social login providers in Auth0 dashboard
668
+
669
+ ## Additional Resources
670
+
671
+ - [Auth0 Documentation](https://auth0.com/docs)
672
+ - [Auth0 SPA SDK](https://auth0.com/docs/libraries/auth0-spa-js)
673
+ - [Meteor Accounts](https://docs.meteor.com/api/accounts.html)
674
+ - [JWT.io](https://jwt.io/) - Debug JWT tokens
675
+
676
+ ## Support
677
+
678
+ For issues specific to this integration, please check:
679
+ - Auth0 dashboard for application configuration
680
+ - Browser console for client-side errors
681
+ - Meteor server logs for server-side errors
682
+ - Network tab to inspect Auth0 API calls
683
+ `;
684
+ if (!fsi.isFile(readmePath) || shouldForce) {
685
+ fsi.writeToFile({
686
+ filePath: readmePath,
687
+ data: readmeContent
688
+ });
689
+ Log.success('✓ Created README.auth0.md documentation');
690
+ }
691
+ Log.success('\n✓ Auth0 authentication integration generated successfully!');
692
+ Log.info('\nNext steps:');
693
+ Log.info('1. Configure your Auth0 application at https://manage.auth0.com/');
694
+ Log.info('2. Update settings.auth0.json with your Auth0 credentials');
695
+ Log.info('3. Start your app with: meteor --settings ../settings.auth0.json');
696
+ Log.info('4. Use AuthService.loginWithAuth0Redirect() or AuthService.loginWithAuth0Popup() in your components');
697
+ Log.info('\n📖 For detailed documentation, see README.auth0.md');
698
+ }
699
+ catch (e) {
700
+ Log.error(e);
701
+ process.exit(1);
702
+ }
703
+ }, async function () { }, AuthGen);
704
+ //# sourceMappingURL=auth0-meteor.auth.gen.js.map