Skip to content

Commit

Permalink
Add the get-tokens command (#56)
Browse files Browse the repository at this point in the history
  • Loading branch information
xer0x authored Jan 28, 2021
1 parent 75e3b82 commit 591c7d3
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 1 deletion.
18 changes: 17 additions & 1 deletion internal/cli/get_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,25 @@ Fetch an access token for the given client and API.
return err
}

// TODO: We can check here if the client is an m2m client, and if so
appType := client.GetAppType()

cli.renderer.Infof("Domain: " + tenant.Domain)
cli.renderer.Infof("ClientID: " + clientID)
cli.renderer.Infof("Type: " + appType + "\n")

// We can check here if the client is an m2m client, and if so
// initiate the client credentials flow instead to fetch a token,
// avoiding the browser and HTTP server shenanigans altogether.
if appType == "non_interactive" {
tokenResponse, err := runClientCredentialsFlow(cli, client, clientID, audience, tenant)
if err != nil {
return err
}

fmt.Fprint(cli.renderer.MessageWriter, "\n")
cli.renderer.GetToken(client, tokenResponse)
return nil
}

if proceed := runLoginFlowPreflightChecks(cli, client); !proceed {
return nil
Expand Down
52 changes: 52 additions & 0 deletions internal/cli/utils_shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ package cli
import (
"fmt"

"encoding/json"
"github.com/auth0/auth0-cli/internal/ansi"
"github.com/auth0/auth0-cli/internal/auth/authutil"
"github.com/auth0/auth0-cli/internal/auth0"
"github.com/auth0/auth0-cli/internal/open"
"github.com/auth0/auth0-cli/internal/prompt"
"gopkg.in/auth0.v5/management"
"net/http"
"net/url"
)

const (
Expand All @@ -23,6 +26,55 @@ var (
cliLoginTestingScopes []string = []string{"openid", "profile"}
)

func BuildOauthTokenURL(domain string) string {
var path string = "/oauth/token"

u := &url.URL{
Scheme: "https",
Host: domain,
Path: path,
}

return u.String()
}

func BuildOauthTokenParams(clientID, clientSecret, audience string) url.Values {
q := url.Values{
"audience": {audience},
"client_id": {clientID},
"client_secret": {clientSecret},
"grant_type": {"client_credentials"},
}
return q
}

// runClientCredentialsFlow runs an M2M client credentials flow without opening a browser
func runClientCredentialsFlow(cli *cli, c *management.Client, clientID string, audience string, tenant tenant) (*authutil.TokenResponse, error) {

var tokenResponse *authutil.TokenResponse

tokenURL := BuildOauthTokenURL(tenant.Domain)
payload := BuildOauthTokenParams(clientID, c.GetClientSecret(), audience)

// TODO: Check if the audience is valid, and suggest a different client if it is wrong.

err := ansi.Spinner("Waiting for token", func() error {
res, err := http.PostForm(tokenURL, payload)
if err != nil {
return err
}
defer res.Body.Close()

err = json.NewDecoder(res.Body).Decode(&tokenResponse)
if err != nil {
return fmt.Errorf("cannot decode response: %w", err)
}
return nil
})

return tokenResponse, err
}

// runLoginFlowPreflightChecks checks if we need to make any updates to the
// client being tested in order to log in successfully. If so, it asks the user
// to confirm whether to proceed.
Expand Down

0 comments on commit 591c7d3

Please sign in to comment.