Skip to content

Commit 445949f

Browse files
authored
Add setup command for Auth0 quickstart applications (#1428)
* feat(quickstart): add setup command for Auth0 quickstart applications * add documentation for quickstarts setup and fix lint * enhance setup command with input validation and user prompts
1 parent f94c606 commit 445949f

5 files changed

Lines changed: 259 additions & 0 deletions

File tree

docs/auth0_quickstarts.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ Step-by-step guides to quickly integrate Auth0 into your application.
1111

1212
- [auth0 quickstarts download](auth0_quickstarts_download.md) - Download a Quickstart sample app for a specific tech stack
1313
- [auth0 quickstarts list](auth0_quickstarts_list.md) - List the available Quickstarts
14+
- [auth0 quickstarts setup](auth0_quickstarts_setup.md) - Set up Auth0 for your quickstart application
1415

docs/auth0_quickstarts_download.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,6 @@ auth0 quickstarts download [flags]
4646

4747
- [auth0 quickstarts download](auth0_quickstarts_download.md) - Download a Quickstart sample app for a specific tech stack
4848
- [auth0 quickstarts list](auth0_quickstarts_list.md) - List the available Quickstarts
49+
- [auth0 quickstarts setup](auth0_quickstarts_setup.md) - Set up Auth0 for your quickstart application
4950

5051

docs/auth0_quickstarts_list.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,6 @@ auth0 quickstarts list [flags]
4848

4949
- [auth0 quickstarts download](auth0_quickstarts_download.md) - Download a Quickstart sample app for a specific tech stack
5050
- [auth0 quickstarts list](auth0_quickstarts_list.md) - List the available Quickstarts
51+
- [auth0 quickstarts setup](auth0_quickstarts_setup.md) - Set up Auth0 for your quickstart application
5152

5253

docs/auth0_quickstarts_setup.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
---
2+
layout: default
3+
parent: auth0 quickstarts
4+
has_toc: false
5+
---
6+
# auth0 quickstarts setup
7+
8+
Creates an Auth0 application and generates a .env file with the necessary configuration.
9+
10+
The command will:
11+
1. Check if you are authenticated (and prompt for login if needed)
12+
2. Create an Auth0 application based on the specified type
13+
3. Generate a .env file with the appropriate environment variables
14+
15+
Supported types:
16+
- vite: For client-side SPAs (React, Vue, Svelte, etc.)
17+
- nextjs: For Next.js server-side applications
18+
19+
## Usage
20+
```
21+
auth0 quickstarts setup [flags]
22+
```
23+
24+
## Examples
25+
26+
```
27+
auth0 quickstarts setup --type vite
28+
auth0 quickstarts setup --type nextjs
29+
auth0 quickstarts setup --type vite --name "My App"
30+
auth0 quickstarts setup --type nextjs --port 8080
31+
auth0 qs setup --type vite -n "My App" -p 5173
32+
```
33+
34+
35+
## Flags
36+
37+
```
38+
--json Output in json format.
39+
-n, --name string Name of the Auth0 application (defaults to current directory name)
40+
-p, --port int Port number for the application (default: 5173 for vite, 3000 for nextjs)
41+
-t, --type string Type of quickstart (vite, nextjs)
42+
```
43+
44+
45+
## Inherited Flags
46+
47+
```
48+
--debug Enable debug mode.
49+
--no-color Disable colors.
50+
--no-input Disable interactivity.
51+
--tenant string Specific tenant to use.
52+
```
53+
54+
55+
## Related Commands
56+
57+
- [auth0 quickstarts download](auth0_quickstarts_download.md) - Download a Quickstart sample app for a specific tech stack
58+
- [auth0 quickstarts list](auth0_quickstarts_list.md) - List the available Quickstarts
59+
- [auth0 quickstarts setup](auth0_quickstarts_setup.md) - Set up Auth0 for your quickstart application
60+
61+

internal/cli/quickstarts.go

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ func quickstartsCmd(cli *cli) *cobra.Command {
6666

6767
cmd.AddCommand(listQuickstartsCmd(cli))
6868
cmd.AddCommand(downloadQuickstartCmd(cli))
69+
cmd.AddCommand(setupQuickstartCmd(cli))
6970

7071
return cmd
7172
}
@@ -413,3 +414,197 @@ func (i *qsInputs) fromArgs(cmd *cobra.Command, args []string, cli *cli) error {
413414

414415
return nil
415416
}
417+
418+
var (
419+
qsType = Flag{
420+
Name: "Type",
421+
LongForm: "type",
422+
ShortForm: "t",
423+
Help: "Type of quickstart (vite, nextjs)",
424+
IsRequired: true,
425+
}
426+
qsAppName = Flag{
427+
Name: "Name",
428+
LongForm: "name",
429+
ShortForm: "n",
430+
Help: "Name of the Auth0 application (defaults to current directory name)",
431+
}
432+
qsPort = Flag{
433+
Name: "Port",
434+
LongForm: "port",
435+
ShortForm: "p",
436+
Help: "Port number for the application (default: 5173 for vite, 3000 for nextjs)",
437+
}
438+
)
439+
440+
func setupQuickstartCmd(cli *cli) *cobra.Command {
441+
var inputs struct {
442+
Type string
443+
Name string
444+
Port int
445+
}
446+
447+
cmd := &cobra.Command{
448+
Use: "setup",
449+
Args: cobra.NoArgs,
450+
Short: "Set up Auth0 for your quickstart application",
451+
Long: "Creates an Auth0 application and generates a .env file with the necessary configuration.\n\n" +
452+
"The command will:\n" +
453+
" 1. Check if you are authenticated (and prompt for login if needed)\n" +
454+
" 2. Create an Auth0 application based on the specified type\n" +
455+
" 3. Generate a .env file with the appropriate environment variables\n\n" +
456+
"Supported types:\n" +
457+
" - vite: For client-side SPAs (React, Vue, Svelte, etc.)\n" +
458+
" - nextjs: For Next.js server-side applications",
459+
Example: ` auth0 quickstarts setup --type vite
460+
auth0 quickstarts setup --type nextjs
461+
auth0 quickstarts setup --type vite --name "My App"
462+
auth0 quickstarts setup --type nextjs --port 8080
463+
auth0 qs setup --type vite -n "My App" -p 5173`,
464+
RunE: func(cmd *cobra.Command, args []string) error {
465+
ctx := cmd.Context()
466+
467+
normalizedType := strings.ToLower(inputs.Type)
468+
if normalizedType != "vite" && normalizedType != "nextjs" {
469+
return fmt.Errorf("unsupported quickstart type: %s (supported types: vite, nextjs)", inputs.Type)
470+
}
471+
472+
if err := qsType.Select(cmd, &inputs.Type, []string{"vite (React, Svelte, Vue, Vanilla JS)", "nextjs"}, nil); err != nil {
473+
return err
474+
}
475+
476+
if err := cli.setupWithAuthentication(ctx); err != nil {
477+
return fmt.Errorf("authentication required: %w", err)
478+
}
479+
480+
defaultName := "My App"
481+
482+
if err := qsAppName.Ask(cmd, &inputs.Name, &defaultName); err != nil {
483+
return err
484+
}
485+
486+
var appType, baseURL, envFileName string
487+
var callbacks, logoutURLs, origins, webOrigins []string
488+
var defaultPort int
489+
490+
switch inputs.Type {
491+
case "vite":
492+
appType = appTypeSPA
493+
defaultPort = 5173
494+
envFileName = ".env"
495+
496+
case "nextjs":
497+
appType = appTypeRegularWeb
498+
defaultPort = 3000
499+
envFileName = ".env.local"
500+
}
501+
502+
if inputs.Port == 0 {
503+
inputs.Port = defaultPort
504+
}
505+
506+
if inputs.Port < 1024 || inputs.Port > 65535 {
507+
return fmt.Errorf("invalid port number: %d (must be between 1024 and 65535)", inputs.Port)
508+
}
509+
510+
baseURL = fmt.Sprintf("http://localhost:%d", inputs.Port)
511+
512+
// Configure URLs based on app type.
513+
if inputs.Type == "vite" {
514+
callbacks = []string{baseURL}
515+
logoutURLs = []string{baseURL}
516+
origins = []string{baseURL}
517+
webOrigins = []string{baseURL}
518+
} else {
519+
callbackURL := fmt.Sprintf("%s/auth/callback", baseURL)
520+
callbacks = []string{callbackURL}
521+
logoutURLs = []string{baseURL}
522+
}
523+
524+
cli.renderer.Infof("Creating Auth0 application '%s'...", inputs.Name)
525+
526+
oidcConformant := true
527+
algorithm := "RS256"
528+
metadata := map[string]interface{}{
529+
"created_by": "quickstart-docs-manual-cli",
530+
}
531+
532+
a := &management.Client{
533+
Name: &inputs.Name,
534+
AppType: &appType,
535+
Callbacks: &callbacks,
536+
AllowedLogoutURLs: &logoutURLs,
537+
OIDCConformant: &oidcConformant,
538+
JWTConfiguration: &management.ClientJWTConfiguration{
539+
Algorithm: &algorithm,
540+
},
541+
ClientMetadata: &metadata,
542+
}
543+
544+
if inputs.Type == "vite" {
545+
a.AllowedOrigins = &origins
546+
a.WebOrigins = &webOrigins
547+
}
548+
549+
if err := ansi.Waiting(func() error {
550+
return cli.api.Client.Create(ctx, a)
551+
}); err != nil {
552+
return fmt.Errorf("failed to create application: %w", err)
553+
}
554+
555+
cli.renderer.Infof("Application created successfully with Client ID: %s", a.GetClientID())
556+
557+
tenant, err := cli.Config.GetTenant(cli.tenant)
558+
if err != nil {
559+
return fmt.Errorf("failed to get tenant: %w", err)
560+
}
561+
562+
var envContent strings.Builder
563+
564+
switch inputs.Type {
565+
case "vite":
566+
envContent.WriteString(fmt.Sprintf("VITE_AUTH0_DOMAIN=%s\n", tenant.Domain))
567+
envContent.WriteString(fmt.Sprintf("VITE_AUTH0_CLIENT_ID=%s\n", a.GetClientID()))
568+
569+
case "nextjs":
570+
secret, err := generateState(32)
571+
if err != nil {
572+
return fmt.Errorf("failed to generate AUTH0_SECRET: %w", err)
573+
}
574+
575+
envContent.WriteString(fmt.Sprintf("AUTH0_DOMAIN=%s\n", tenant.Domain))
576+
envContent.WriteString(fmt.Sprintf("AUTH0_CLIENT_ID=%s\n", a.GetClientID()))
577+
envContent.WriteString(fmt.Sprintf("AUTH0_CLIENT_SECRET=%s\n", a.GetClientSecret()))
578+
envContent.WriteString(fmt.Sprintf("AUTH0_SECRET=%s\n", secret))
579+
envContent.WriteString(fmt.Sprintf("APP_BASE_URL=%s\n", baseURL))
580+
}
581+
582+
message := fmt.Sprintf("Proceed to overwrite '%s' file? : ", envFileName)
583+
if shouldCancelOverwrite(cli, cmd, envFileName, message) {
584+
cli.renderer.Warnf("Aborted creating %s file. Please create it manually using the following content:\n\n"+
585+
"─────────────────────────────────────────────────────────────\n"+"%s"+
586+
"─────────────────────────────────────────────────────────────\n", envFileName, envContent.String())
587+
} else {
588+
if err = os.WriteFile(envFileName, []byte(envContent.String()), 0600); err != nil {
589+
return fmt.Errorf("failed to write .env file: %w", err)
590+
}
591+
592+
cli.renderer.Infof("%s file created successfully with your Auth0 configuration\n", envFileName)
593+
}
594+
595+
cli.renderer.Infof("Next steps: \n"+
596+
" 1. Install dependencies: npm install \n"+
597+
" 2. Start your application: npm run dev\n"+
598+
" 3. Open your browser at %s", baseURL)
599+
600+
return nil
601+
},
602+
}
603+
604+
cmd.Flags().BoolVar(&cli.json, "json", false, "Output in json format.")
605+
qsType.RegisterString(cmd, &inputs.Type, "")
606+
qsAppName.RegisterString(cmd, &inputs.Name, "")
607+
qsPort.RegisterInt(cmd, &inputs.Port, 0)
608+
609+
return cmd
610+
}

0 commit comments

Comments
 (0)