diff --git a/docs/auth0_quickstarts_setup.md b/docs/auth0_quickstarts_setup.md index bb286329d..c7a158fb1 100644 --- a/docs/auth0_quickstarts_setup.md +++ b/docs/auth0_quickstarts_setup.md @@ -16,6 +16,7 @@ Supported types: - vite: For client-side SPAs (React, Vue, Svelte, etc.) - nextjs: For Next.js server-side applications - fastify: For Fastify web applications + - jhipster-rwa: For JHipster regular web applications ## Usage ``` @@ -30,6 +31,7 @@ auth0 quickstarts setup [flags] auth0 quickstarts setup --type fastify auth0 quickstarts setup --type vite --name "My App" auth0 quickstarts setup --type nextjs --port 8080 + auth0 quickstarts setup --type jhipster-rwa auth0 qs setup --type fastify -n "My App" -p 3000 ``` @@ -38,9 +40,9 @@ auth0 quickstarts setup [flags] ``` --json Output in json format. - -n, --name string Name of the Auth0 application (defaults to current directory name) - -p, --port int Port number for the application (default: 5173 for vite, 3000 for nextjs/fastify) - -t, --type string Type of quickstart (vite, nextjs) + -n, --name string Name of the Auth0 application (default: 'My App' for vite, nextjs and fastify, 'JHipster' for jhipster-rwa) + -p, --port int Port number for the application (default: 5173 for vite, 3000 for nextjs/fastify, 8080 for jhipster-rwa) + -t, --type string Type of quickstart (vite, nextjs, fastify, jhipster-rwa) ``` diff --git a/internal/cli/quickstarts.go b/internal/cli/quickstarts.go index 9f585896e..d9978fc24 100644 --- a/internal/cli/quickstarts.go +++ b/internal/cli/quickstarts.go @@ -8,6 +8,7 @@ import ( "path" "path/filepath" "regexp" + "strconv" "strings" "github.com/auth0/go-auth0/management" @@ -420,20 +421,20 @@ var ( Name: "Type", LongForm: "type", ShortForm: "t", - Help: "Type of quickstart (vite, nextjs)", + Help: "Type of quickstart (vite, nextjs, fastify, jhipster-rwa)", IsRequired: true, } qsAppName = Flag{ Name: "Name", LongForm: "name", ShortForm: "n", - Help: "Name of the Auth0 application (defaults to current directory name)", + Help: "Name of the Auth0 application (default: 'My App' for vite, nextjs and fastify, 'JHipster' for jhipster-rwa)", } qsPort = Flag{ Name: "Port", LongForm: "port", ShortForm: "p", - Help: "Port number for the application (default: 5173 for vite, 3000 for nextjs/fastify)", + Help: "Port number for the application (default: 5173 for vite, 3000 for nextjs/fastify, 8080 for jhipster-rwa)", } ) @@ -456,24 +457,26 @@ func setupQuickstartCmd(cli *cli) *cobra.Command { "Supported types:\n" + " - vite: For client-side SPAs (React, Vue, Svelte, etc.)\n" + " - nextjs: For Next.js server-side applications\n" + - " - fastify: For Fastify web applications", + " - fastify: For Fastify web applications\n" + + " - jhipster-rwa: For JHipster regular web applications", Example: ` auth0 quickstarts setup --type vite auth0 quickstarts setup --type nextjs auth0 quickstarts setup --type fastify auth0 quickstarts setup --type vite --name "My App" auth0 quickstarts setup --type nextjs --port 8080 + auth0 quickstarts setup --type jhipster-rwa auth0 qs setup --type fastify -n "My App" -p 3000`, RunE: func(cmd *cobra.Command, args []string) error { ctx := cmd.Context() if inputs.Type != "" { normalizedType := strings.ToLower(inputs.Type) - if normalizedType != "vite" && normalizedType != "nextjs" && normalizedType != "fastify" { - return fmt.Errorf("unsupported quickstart type: %s (supported types: vite, nextjs, fastify)", inputs.Type) + if normalizedType != "vite" && normalizedType != "nextjs" && normalizedType != "fastify" && normalizedType != "jhipster-rwa" { + return fmt.Errorf("unsupported quickstart type: %s (supported types: vite, nextjs, fastify, jhipster-rwa)", inputs.Type) } } - if err := qsType.Select(cmd, &inputs.Type, []string{"vite", "nextjs", "fastify"}, nil); err != nil { + if err := qsType.Select(cmd, &inputs.Type, []string{"vite", "nextjs", "fastify", "jhipster-rwa"}, nil); err != nil { return err } @@ -482,41 +485,32 @@ func setupQuickstartCmd(cli *cli) *cobra.Command { } defaultName := "My App" - - if err := qsAppName.Ask(cmd, &inputs.Name, &defaultName); err != nil { - return err - } - - var appType, baseURL, envFileName string - var callbacks, logoutURLs, origins, webOrigins []string - var defaultPort string + var defaultPort int switch inputs.Type { case "vite": - appType = appTypeSPA - defaultPort = "5173" - envFileName = ".env" - + defaultPort = 5173 case "nextjs", "fastify": - appType = appTypeRegularWeb - defaultPort = "3000" - envFileName = ".env" + defaultPort = 3000 + case "jhipster-rwa": + defaultName = "JHipster" + defaultPort = 8080 } - // If port is not explicitly set (is 0), ask for it or use default. - if inputs.Port == 0 { - if err := qsPort.Ask(cmd, &inputs.Port, &defaultPort); err != nil { + // If name is not explicitly set (is empty), ask for it or use default. + if inputs.Name == "" { + inputs.Name = defaultName + if err := qsAppName.Ask(cmd, &inputs.Name, &defaultName); err != nil { return err } } - // If port is still 0 after asking (e.g., in non-interactive mode), use the default. + // If port is not explicitly set (is 0), ask for it or use default. if inputs.Port == 0 { - switch inputs.Type { - case "vite": - inputs.Port = 5173 - case "nextjs", "fastify": - inputs.Port = 3000 + inputs.Port = defaultPort + defaultPortStr := strconv.Itoa(defaultPort) + if err := qsPort.Ask(cmd, &inputs.Port, &defaultPortStr); err != nil { + return err } } @@ -524,11 +518,14 @@ func setupQuickstartCmd(cli *cli) *cobra.Command { return fmt.Errorf("invalid port number: %d (must be between 1024 and 65535)", inputs.Port) } - baseURL = fmt.Sprintf("http://localhost:%d", inputs.Port) + baseURL := fmt.Sprintf("http://localhost:%d", inputs.Port) + appType := appTypeRegularWeb + var callbacks, logoutURLs, origins, webOrigins []string // Configure URLs based on app type. switch inputs.Type { case "vite": + appType = appTypeSPA callbacks = []string{baseURL} logoutURLs = []string{baseURL} origins = []string{baseURL} @@ -541,6 +538,10 @@ func setupQuickstartCmd(cli *cli) *cobra.Command { callbackURL := fmt.Sprintf("%s/auth/callback", baseURL) callbacks = []string{callbackURL} logoutURLs = []string{baseURL} + case "jhipster-rwa": + callbackURL := fmt.Sprintf("%s/login/oauth2/code/oidc", baseURL) + callbacks = []string{callbackURL} + logoutURLs = []string{baseURL} } cli.renderer.Infof("Creating Auth0 application '%s'...", inputs.Name) @@ -581,12 +582,13 @@ func setupQuickstartCmd(cli *cli) *cobra.Command { return fmt.Errorf("failed to get tenant: %w", err) } + envFileName := ".env" var envContent strings.Builder switch inputs.Type { case "vite": - envContent.WriteString(fmt.Sprintf("VITE_AUTH0_DOMAIN=%s\n", tenant.Domain)) - envContent.WriteString(fmt.Sprintf("VITE_AUTH0_CLIENT_ID=%s\n", a.GetClientID())) + fmt.Fprintf(&envContent, "VITE_AUTH0_DOMAIN=%s\n", tenant.Domain) + fmt.Fprintf(&envContent, "VITE_AUTH0_CLIENT_ID=%s\n", a.GetClientID()) case "nextjs": secret, err := generateState(32) @@ -594,11 +596,11 @@ func setupQuickstartCmd(cli *cli) *cobra.Command { return fmt.Errorf("failed to generate AUTH0_SECRET: %w", err) } - envContent.WriteString(fmt.Sprintf("AUTH0_DOMAIN=%s\n", tenant.Domain)) - envContent.WriteString(fmt.Sprintf("AUTH0_CLIENT_ID=%s\n", a.GetClientID())) - envContent.WriteString(fmt.Sprintf("AUTH0_CLIENT_SECRET=%s\n", a.GetClientSecret())) - envContent.WriteString(fmt.Sprintf("AUTH0_SECRET=%s\n", secret)) - envContent.WriteString(fmt.Sprintf("APP_BASE_URL=%s\n", baseURL)) + fmt.Fprintf(&envContent, "AUTH0_DOMAIN=%s\n", tenant.Domain) + fmt.Fprintf(&envContent, "AUTH0_CLIENT_ID=%s\n", a.GetClientID()) + fmt.Fprintf(&envContent, "AUTH0_CLIENT_SECRET=%s\n", a.GetClientSecret()) + fmt.Fprintf(&envContent, "AUTH0_SECRET=%s\n", secret) + fmt.Fprintf(&envContent, "APP_BASE_URL=%s\n", baseURL) case "fastify": sessionSecret, err := generateState(64) @@ -606,11 +608,18 @@ func setupQuickstartCmd(cli *cli) *cobra.Command { return fmt.Errorf("failed to generate SESSION_SECRET: %w", err) } - envContent.WriteString(fmt.Sprintf("AUTH0_DOMAIN=%s\n", tenant.Domain)) - envContent.WriteString(fmt.Sprintf("AUTH0_CLIENT_ID=%s\n", a.GetClientID())) - envContent.WriteString(fmt.Sprintf("AUTH0_CLIENT_SECRET=%s\n", a.GetClientSecret())) - envContent.WriteString(fmt.Sprintf("SESSION_SECRET=%s\n", sessionSecret)) - envContent.WriteString(fmt.Sprintf("APP_BASE_URL=%s\n", baseURL)) + fmt.Fprintf(&envContent, "AUTH0_DOMAIN=%s\n", tenant.Domain) + fmt.Fprintf(&envContent, "AUTH0_CLIENT_ID=%s\n", a.GetClientID()) + fmt.Fprintf(&envContent, "AUTH0_CLIENT_SECRET=%s\n", a.GetClientSecret()) + fmt.Fprintf(&envContent, "SESSION_SECRET=%s\n", sessionSecret) + fmt.Fprintf(&envContent, "APP_BASE_URL=%s\n", baseURL) + + case "jhipster-rwa": + envFileName = ".auth0.env" + fmt.Fprintf(&envContent, "SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_OIDC_ISSUER_URI=https://%s/\n", tenant.Domain) + fmt.Fprintf(&envContent, "SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_OIDC_CLIENT_ID=%s\n", a.GetClientID()) + fmt.Fprintf(&envContent, "SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_OIDC_CLIENT_SECRET=%s\n", a.GetClientSecret()) + fmt.Fprintf(&envContent, "JHIPSTER_SECURITY_OAUTH2_AUDIENCE=https://%s/api/v2/\n", tenant.Domain) } message := fmt.Sprintf(" Proceed to overwrite '%s' file? : ", envFileName) @@ -626,10 +635,15 @@ func setupQuickstartCmd(cli *cli) *cobra.Command { cli.renderer.Infof("%s file created successfully with your Auth0 configuration\n", envFileName) } - cli.renderer.Infof("Next steps: \n"+ - " 1. Install dependencies: npm install \n"+ - " 2. Start your application: npm run dev\n"+ - " 3. Open your browser at %s", baseURL) + switch inputs.Type { + case "jhipster-rwa": + cli.renderer.Infof("Please refer to the JHipster documentation https://www.jhipster.tech/security/#auth0 to complete the setup") + default: + cli.renderer.Infof("Next steps: \n"+ + " 1. Install dependencies: npm install \n"+ + " 2. Start your application: npm run dev\n"+ + " 3. Open your browser at %s", baseURL) + } return nil },