Skip to content

Commit

Permalink
feat: add client credentials flow (#304)
Browse files Browse the repository at this point in the history
* feat: add MVP for client credentials flow

This would potentially support private cloud customers

* Don't require login on tenant add

* Update internal/cli/tenants.go

Co-authored-by: Rita Zerrizuela <[email protected]>
  • Loading branch information
cyx and Widcket authored Jul 23, 2021
1 parent a2a8bd1 commit 711dbbd
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 4 deletions.
30 changes: 27 additions & 3 deletions internal/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ type tenant struct {
ExpiresAt time.Time `json:"expires_at"`
Apps map[string]app `json:"apps,omitempty"`
DefaultAppID string `json:"default_app_id,omitempty"`

ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
}

type app struct {
Expand Down Expand Up @@ -132,9 +135,23 @@ func (c *cli) setup(ctx context.Context) error {
return err
}

m, err := management.New(t.Domain,
management.WithStaticToken(t.AccessToken),
management.WithUserAgent(fmt.Sprintf("%v/%v", userAgent, strings.TrimPrefix(buildinfo.Version, "v"))))
var (
m *management.Management
ua = fmt.Sprintf("%v/%v", userAgent, strings.TrimPrefix(buildinfo.Version, "v"))
)

if t.ClientID != "" && t.ClientSecret != "" {
m, err = management.New(t.Domain,
management.WithClientCredentials(t.ClientID, t.ClientSecret),
management.WithUserAgent(ua),
)
} else {
m, err = management.New(t.Domain,
management.WithStaticToken(t.AccessToken),
management.WithUserAgent(ua),
)
}

if err != nil {
return err
}
Expand All @@ -153,6 +170,10 @@ func (c *cli) prepareTenant(ctx context.Context) (tenant, error) {
return tenant{}, err
}

if t.ClientID != "" && t.ClientSecret != "" {
return t, nil
}

if t.AccessToken == "" || scopesChanged(t) {
t, err = RunLogin(ctx, c, true)
if err != nil {
Expand All @@ -167,6 +188,9 @@ func (c *cli) prepareTenant(ctx context.Context) (tenant, error) {
Client: http.DefaultClient,
}

// NOTE(cyx): this code will have to be adapted to instead
// maybe take the clientID/secret as additional params, or
// something similar.
res, err := tr.Refresh(ctx, t.Domain)
if err != nil {
// ask and guide the user through the login process:
Expand Down
2 changes: 1 addition & 1 deletion internal/cli/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ func buildRootCmd(cli *cli) *cobra.Command {
}

// Selecting tenants shouldn't really trigger a login.
if cmd.Use == "use" && cmd.Parent().Use == "tenants" {
if cmd.Parent().Use == "tenants" && (cmd.Use == "use" || cmd.Use == "add") {
return nil
}

Expand Down
66 changes: 66 additions & 0 deletions internal/cli/tenants.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,22 @@ var (
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 {
Expand All @@ -25,6 +41,7 @@ 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 @@ -132,6 +149,55 @@ 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 {
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
}

t := tenant{
Domain: inputs.Domain,
ClientID: inputs.ClientID,
ClientSecret: inputs.ClientSecret,
}

if err := cli.addTenant(t); err != nil {
return err
}

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

return cmd
}

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

0 comments on commit 711dbbd

Please sign in to comment.