Skip to content

Commit

Permalink
fix: use updated token once after the renewal (#290)
Browse files Browse the repository at this point in the history
* fix: reload token once renewed

* login return updated tenant

* cleanup
  • Loading branch information
jfatta authored May 14, 2021
1 parent 83f9ea5 commit 7fe639a
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 35 deletions.
52 changes: 27 additions & 25 deletions internal/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ type cli struct {
// core primitives exposed to command builders.
api *auth0.API
renderer *display.Renderer

// set of flags which are user specified.
debug bool
tenant string
Expand Down Expand Up @@ -123,21 +122,36 @@ func (c *cli) setup(ctx context.Context) error {
return err
}

t, err := c.getTenant()
t, err := c.prepareTenant(ctx)
if err != nil {
return err
}

if t.AccessToken == "" {
return errUnauthenticated
m, err := management.New(t.Domain,
management.WithStaticToken(t.AccessToken),
management.WithUserAgent(fmt.Sprintf("%v/%v", userAgent, strings.TrimPrefix(buildinfo.Version, "v"))))
if err != nil {
return err
}

if scopesChanged(t) {
// required scopes changed,
// a new token is required
err = RunLogin(ctx, c, true)
c.api = auth0.NewAPI(m)
return nil
}

// prepareTenant loads the tenant, refreshing its token if necessary.
// The tenant access token needs a refresh if:
// 1. the tenant scopes are different than the currently required scopes.
// 2. the access token is expired.
func (c *cli) prepareTenant(ctx context.Context) (tenant, error) {
t, err := c.getTenant()
if err != nil {
return tenant{}, err
}

if t.AccessToken == "" || scopesChanged(t) {
t, err = RunLogin(ctx, c, true)
if err != nil {
return err
return tenant{}, err
}
} else if isExpired(t.ExpiresAt, accessTokenExpThreshold) {
// check if the stored access token is expired:
Expand All @@ -151,9 +165,9 @@ func (c *cli) setup(ctx context.Context) error {
if err != nil {
// ask and guide the user through the login process:
c.renderer.Errorf("failed to renew access token, %s", err)
err = RunLogin(ctx, c, true)
t, err = RunLogin(ctx, c, true)
if err != nil {
return err
return tenant{}, err
}
} else {
// persist the updated tenant with renewed access token
Expand All @@ -164,24 +178,12 @@ func (c *cli) setup(ctx context.Context) error {

err = c.addTenant(t)
if err != nil {
return err
return tenant{}, err
}
}
}

// continue with the command setup:
if t.AccessToken != "" {
m, err := management.New(t.Domain,
management.WithStaticToken(t.AccessToken),
management.WithUserAgent(fmt.Sprintf("%v/%v", userAgent, strings.TrimPrefix(buildinfo.Version, "v"))))
if err != nil {
return err
}

c.api = auth0.NewAPI(m)
}

return err
return t, nil
}

// isExpired is true if now() + a threshold is after the given date
Expand Down
22 changes: 12 additions & 10 deletions internal/cli/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ func loginCmd(cli *cli) *cobra.Command {
Long: "Sign in to your Auth0 account and authorize the CLI to access the Management API.",
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
return RunLogin(ctx, cli, false)
_, err := RunLogin(ctx, cli, false)
return err
},
}

Expand All @@ -31,7 +32,7 @@ func loginCmd(cli *cli) *cobra.Command {
// 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) error {
func RunLogin(ctx context.Context, cli *cli, expired bool) (tenant, error) {
if expired {
cli.renderer.Warnf("Please sign in to re-authorize the CLI.")
} else {
Expand All @@ -42,7 +43,7 @@ func RunLogin(ctx context.Context, cli *cli, expired bool) error {
a := &auth.Authenticator{}
state, err := a.Start(ctx)
if err != nil {
return fmt.Errorf("could not start the authentication process: %w.", err)
return tenant{}, fmt.Errorf("could not start the authentication process: %w.", err)
}

fmt.Printf("Your Device Confirmation code is: %s\n\n", ansi.Bold(state.UserCode))
Expand All @@ -61,7 +62,7 @@ func RunLogin(ctx context.Context, cli *cli, expired bool) error {
})

if err != nil {
return fmt.Errorf("login error: %w", err)
return tenant{}, fmt.Errorf("login error: %w", err)
}

fmt.Print("\n")
Expand All @@ -76,29 +77,30 @@ func RunLogin(ctx context.Context, cli *cli, expired bool) error {
cli.renderer.Warnf("Could not store the refresh token locally, please expect to login again once your access token expired. See https://github.com/auth0/auth0-cli/blob/main/KNOWN-ISSUES.md.")
}

err = cli.addTenant(tenant{
t := tenant{
Name: res.Tenant,
Domain: res.Domain,
AccessToken: res.AccessToken,
ExpiresAt: time.Now().Add(
time.Duration(res.ExpiresIn) * time.Second,
),
Scopes: auth.RequiredScopes(),
})
}
err = cli.addTenant(t)
if err != nil {
return fmt.Errorf("Unexpected error adding tenant to config: %w", err)
return tenant{}, fmt.Errorf("Unexpected error adding tenant to config: %w", err)
}

if cli.config.DefaultTenant != res.Domain {
promptText := fmt.Sprintf("Your default tenant is %s. Do you want to change it to %s?", cli.config.DefaultTenant, res.Domain)
if confirmed := prompt.Confirm(promptText); !confirmed {
return nil
return tenant{}, nil
}
cli.config.DefaultTenant = res.Domain
if err := cli.persistConfig(); err != nil {
return fmt.Errorf("An error occurred while setting the default tenant: %w", err)
return tenant{}, fmt.Errorf("An error occurred while setting the default tenant: %w", err)
}
}

return nil
return t, nil
}

0 comments on commit 7fe639a

Please sign in to comment.