Skip to content

Commit

Permalink
DXCDT-267: Consolidate auth0 add tenants into auth0 login (1/x) (#…
Browse files Browse the repository at this point in the history
…546)

Co-authored-by: Will Vedder <[email protected]>
Co-authored-by: Sergiu Ghitea <[email protected]>
  • Loading branch information
3 people authored Dec 9, 2022
1 parent e06962a commit 64f9db8
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 161 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ test-unit: ## Run unit tests
test-integration: $(GO_BIN)/commander ## Run integration tests. To run a specific test pass the FILTER var. Usage: `make test-integration FILTER="attack protection"`
${call print, "Running integration tests"}
@$(MAKE) install # ensure fresh install prior to running test
auth0 tenants add ${AUTH0_CLI_CLIENT_DOMAIN} --client-id ${AUTH0_CLI_CLIENT_ID} --client-secret ${AUTH0_CLI_CLIENT_SECRET} && commander test ./test/integration/test-cases.yaml --filter "$(FILTER)"; \
auth0 login --domain ${AUTH0_CLI_CLIENT_DOMAIN} --client-id ${AUTH0_CLI_CLIENT_ID} --client-secret ${AUTH0_CLI_CLIENT_SECRET} && commander test ./test/integration/test-cases.yaml --filter "$(FILTER)"; \
exit_code=$$?; \
bash ./test/integration/scripts/test-cleanup.sh; \
exit $$exit_code
Expand Down
14 changes: 12 additions & 2 deletions docs/auth0_login.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,26 @@ Authenticate the Auth0 CLI

### Synopsis

Sign in to your Auth0 account and authorize the CLI to access the Management API.
Authenticates the Auth0 CLI either as a user using personal credentials or as a machine using client credentials.

```
auth0 login [flags]
```

### Examples

```
auth0 login
auth0 login --domain <tenant-domain> --client-id <client-id> --client-secret <client-secret>
```

### Options

```
-h, --help help for login
--client-id string Client ID of the application when authenticating via client credentials.
--client-secret string Client secret of the application when authenticating via client credentials.
--domain string Tenant domain of the application when authenticating via client credentials.
-h, --help help for login
```

### Options inherited from parent commands
Expand Down
1 change: 0 additions & 1 deletion docs/auth0_tenants.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ Manage configured tenants.
### SEE ALSO

* [auth0](/auth0-cli/) - Supercharge your development workflow.
* [auth0 tenants add](auth0_tenants_add.md) - Add a tenant with client credentials
* [auth0 tenants list](auth0_tenants_list.md) - List your tenants
* [auth0 tenants open](auth0_tenants_open.md) - Open tenant settings page in the Auth0 Dashboard
* [auth0 tenants use](auth0_tenants_use.md) - Set the active tenant
Expand Down
41 changes: 0 additions & 41 deletions docs/auth0_tenants_add.md

This file was deleted.

4 changes: 2 additions & 2 deletions internal/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ func (c *cli) prepareTenant(ctx context.Context) (Tenant, error) {
}

if t.AccessToken == "" || (scopesChanged(t) && t.authenticatedWithDeviceCodeFlow()) {
return RunLogin(ctx, c, true)
return RunLoginAsUser(ctx, c, true)
}

if !t.hasExpiredToken() {
Expand All @@ -218,7 +218,7 @@ func (c *cli) prepareTenant(ctx context.Context) (Tenant, error) {
if err := t.regenerateAccessToken(ctx, c); err != nil {
// Ask and guide the user through the login process.
c.renderer.Errorf("failed to renew access token, %s", err)
return RunLogin(ctx, c, true)
return RunLoginAsUser(ctx, c, true)
}

if err := c.addTenant(t); err != nil {
Expand Down
109 changes: 104 additions & 5 deletions internal/cli/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,63 @@ import (
"github.com/auth0/auth0-cli/internal/prompt"
)

var (
loginTenantDomain = Flag{
Name: "Tenant Domain",
LongForm: "domain",
Help: "Tenant domain of the application when authenticating via client credentials.",
IsRequired: false,
AlwaysPrompt: false,
}

loginClientID = Flag{
Name: "Client ID",
LongForm: "client-id",
Help: "Client ID of the application when authenticating via client credentials.",
IsRequired: false,
AlwaysPrompt: false,
}

loginClientSecret = Flag{
Name: "Client Secret",
LongForm: "client-secret",
Help: "Client secret of the application when authenticating via client credentials.",
IsRequired: false,
AlwaysPrompt: false,
}
)

type LoginInputs struct {
Domain string
ClientID string
ClientSecret string
}

func (i *LoginInputs) shouldLoginAsMachine() bool {
return i.ClientID != "" || i.ClientSecret != "" || i.Domain != ""
}

func loginCmd(cli *cli) *cobra.Command {
var inputs LoginInputs

cmd := &cobra.Command{
Use: "login",
Args: cobra.NoArgs,
Short: "Authenticate the Auth0 CLI",
Long: "Sign in to your Auth0 account and authorize the CLI to access the Management API.",
Long: "Authenticates the Auth0 CLI either as a user using personal credentials or as a machine using client credentials.",
Example: `auth0 login
auth0 login --domain <tenant-domain> --client-id <client-id> --client-secret <client-secret>`,
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
if _, err := RunLogin(ctx, cli, false); err != nil {
return err

if inputs.shouldLoginAsMachine() {
if err := RunLoginAsMachine(ctx, inputs, cli, cmd); err != nil {
return err
}
} else {
if _, err := RunLoginAsUser(ctx, cli, false); err != nil {
return err
}
}

cli.tracker.TrackCommandRun(cmd, cli.config.InstallID)
Expand All @@ -30,20 +77,26 @@ func loginCmd(cli *cli) *cobra.Command {
},
}

loginTenantDomain.RegisterString(cmd, &inputs.Domain, "")
loginClientID.RegisterString(cmd, &inputs.ClientID, "")
loginClientSecret.RegisterString(cmd, &inputs.ClientSecret, "")
cmd.MarkFlagsRequiredTogether("client-id", "client-secret", "domain")

cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) {
_ = cmd.Flags().MarkHidden("tenant")
_ = cmd.Flags().MarkHidden("json")
_ = cmd.Flags().MarkHidden("no-input")
cmd.Parent().HelpFunc()(cmd, args)
})

return cmd
}

// RunLogin runs the login flow guiding the user through the process
// RunLoginAsUser runs the login flow guiding the user through the process
// by showing the login instructions, opening the browser.
// Use `expired` to run the login from other commands setup:
// this will only affect the messages.
func RunLogin(ctx context.Context, cli *cli, expired bool) (Tenant, error) {
func RunLoginAsUser(ctx context.Context, cli *cli, expired bool) (Tenant, error) {
message := fmt.Sprintf(
"%s\n\n%s\n\n",
"✪ Welcome to the Auth0 CLI 🎊",
Expand Down Expand Up @@ -141,3 +194,49 @@ func RunLogin(ctx context.Context, cli *cli, expired bool) (Tenant, error) {

return tenant, nil
}

// RunLoginAsMachine facilitates the authentication process using client credentials (client ID, client secret)
func RunLoginAsMachine(ctx context.Context, inputs LoginInputs, cli *cli, cmd *cobra.Command) error {
if err := loginTenantDomain.Ask(cmd, &inputs.Domain, nil); err != nil {
return err
}

if err := loginClientID.Ask(cmd, &inputs.ClientID, nil); err != nil {
return err
}

if err := loginClientSecret.AskPassword(cmd, &inputs.ClientSecret, nil); err != nil {
return err
}

token, err := auth.GetAccessTokenFromClientCreds(auth.ClientCredentials{
ClientID: inputs.ClientID,
ClientSecret: inputs.ClientSecret,
Domain: inputs.Domain,
})
if err != nil {
return err
}

t := Tenant{
Domain: inputs.Domain,
AccessToken: token.AccessToken,
ExpiresAt: token.ExpiresAt,
ClientID: inputs.ClientID,
ClientSecret: inputs.ClientSecret,
}

if err := cli.addTenant(t); err != nil {
return fmt.Errorf("unexpected error when attempting to save tenant data: %w", err)
}

cli.renderer.Newline()
cli.renderer.Infof("Successfully logged in.")
cli.renderer.Infof("Tenant: %s", inputs.Domain)

if err := checkInstallID(cli); err != nil {
return fmt.Errorf("failed to update the config: %w", err)
}

return nil
}
100 changes: 5 additions & 95 deletions internal/cli/tenants.go
Original file line number Diff line number Diff line change
@@ -1,38 +1,13 @@
package cli

import (
"errors"
"fmt"

"github.com/spf13/cobra"

"github.com/auth0/auth0-cli/internal/auth"
"github.com/auth0/auth0-cli/internal/prompt"
)

var (
tenantDomain = Argument{
Name: "Tenant",
Help: "Tenant to select",
}

tenantClientID = Flag{
Name: "Client ID",
LongForm: "client-id",
ShortForm: "i",
Help: "Client ID of the application.",
IsRequired: true,
}

tenantClientSecret = Flag{
Name: "Client Secret",
LongForm: "client-secret",
ShortForm: "s",
Help: "Client Secret of the application.",
IsRequired: true,
}
)

func tenantsCmd(cli *cli) *cobra.Command {
cmd := &cobra.Command{
Use: "tenants",
Expand All @@ -44,7 +19,6 @@ func tenantsCmd(cli *cli) *cobra.Command {
cmd.AddCommand(useTenantCmd(cli))
cmd.AddCommand(listTenantCmd(cli))
cmd.AddCommand(openTenantCmd(cli))
cmd.AddCommand(addTenantCmd(cli))
return cmd
}

Expand Down Expand Up @@ -129,6 +103,11 @@ func openTenantCmd(cli *cli) *cobra.Command {
Domain string
}

var tenantDomain = Argument{
Name: "Tenant",
Help: "Tenant to select",
}

cmd := &cobra.Command{
Use: "open",
Args: cobra.MaximumNArgs(1),
Expand Down Expand Up @@ -162,75 +141,6 @@ func openTenantCmd(cli *cli) *cobra.Command {
return cmd
}

func addTenantCmd(cli *cli) *cobra.Command {
var inputs struct {
Domain string
ClientID string
ClientSecret string
}

cmd := &cobra.Command{
Use: "add",
Args: cobra.MaximumNArgs(1),
Short: "Add a tenant with client credentials",
Long: "Add a tenant with client credentials.",
Example: "auth0 tenants add <tenant> --client-id <id> --client-secret <secret>",
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
err := tenantDomain.Pick(cmd, &inputs.Domain, cli.tenantPickerOptions)
if err != nil {
if !errors.Is(err, errUnauthenticated) {
return err
}

if err := tenantDomain.Ask(cmd, &inputs.Domain); err != nil {
return err
}
}
} else {
inputs.Domain = args[0]
}

if err := tenantClientID.Ask(cmd, &inputs.ClientID, nil); err != nil {
return err
}

if err := tenantClientSecret.Ask(cmd, &inputs.ClientSecret, nil); err != nil {
return err
}

token, err := auth.GetAccessTokenFromClientCreds(auth.ClientCredentials{
ClientID: inputs.ClientID,
ClientSecret: inputs.ClientSecret,
Domain: inputs.Domain,
})
if err != nil {
return err
}

t := Tenant{
Domain: inputs.Domain,
AccessToken: token.AccessToken,
ExpiresAt: token.ExpiresAt,
ClientID: inputs.ClientID,
ClientSecret: inputs.ClientSecret,
}

if err := cli.addTenant(t); err != nil {
return fmt.Errorf("unexpected error when attempting to save tenant data: %w", err)
}

cli.renderer.Infof("Tenant added successfully: %s", t.Domain)
return nil
},
}

tenantClientID.RegisterString(cmd, &inputs.ClientID, "")
tenantClientSecret.RegisterString(cmd, &inputs.ClientSecret, "")

return cmd
}

func (c *cli) tenantPickerOptions() (pickerOptions, error) {
tens, err := c.listTenants()
if err != nil {
Expand Down
Loading

0 comments on commit 64f9db8

Please sign in to comment.