Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the get-tokens command #56

Merged
merged 6 commits into from
Jan 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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