// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package command

import (
	"context"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"math/rand"
	"net"
	"net/http"
	"net/url"
	"path/filepath"
	"strings"

	tfe "github.com/hashicorp/go-tfe"
	svchost "github.com/hashicorp/terraform-svchost"
	svcauth "github.com/hashicorp/terraform-svchost/auth"
	"github.com/hashicorp/terraform-svchost/disco"
	"github.com/hashicorp/terraform/internal/command/cliconfig"
	"github.com/hashicorp/terraform/internal/httpclient"
	"github.com/hashicorp/terraform/internal/logging"
	"github.com/hashicorp/terraform/internal/terraform"
	"github.com/hashicorp/terraform/internal/tfdiags"

	uuid "github.com/hashicorp/go-uuid"
	"golang.org/x/oauth2"
)

// LoginCommand is a Command implementation that runs an interactive login
// flow for a remote service host. It then stashes credentials in a tfrc
// file in the user's home directory.
type LoginCommand struct {
	Meta
}

// Run implements cli.Command.
func (c *LoginCommand) Run(args []string) int {
	args = c.Meta.process(args)
	cmdFlags := c.Meta.extendedFlagSet("login")
	cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	args = cmdFlags.Args()
	if len(args) > 1 {
		c.Ui.Error(
			"The login command expects at most one argument: the host to log in to.")
		cmdFlags.Usage()
		return 1
	}

	var diags tfdiags.Diagnostics

	if !c.input {
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Error,
			"Login is an interactive command",
			"The \"terraform login\" command uses interactive prompts to obtain and record credentials, so it can't be run with input disabled.\n\nTo configure credentials in a non-interactive context, write existing credentials directly to a CLI configuration file.",
		))
		c.showDiagnostics(diags)
		return 1
	}

	givenHostname := "app.terraform.io"
	if len(args) != 0 {
		givenHostname = args[0]
	}

	hostname, err := svchost.ForComparison(givenHostname)
	if err != nil {
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Error,
			"Invalid hostname",
			fmt.Sprintf("The given hostname %q is not valid: %s.", givenHostname, err.Error()),
		))
		c.showDiagnostics(diags)
		return 1
	}

	// From now on, since we've validated the given hostname, we should use
	// dispHostname in the UI to ensure we're presenting it in the canonical
	// form, in case that helpers users with debugging when things aren't
	// working as expected. (Perhaps the normalization is part of the cause.)
	dispHostname := hostname.ForDisplay()

	host, err := c.Services.Discover(hostname)
	if err != nil {
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Error,
			"Service discovery failed for "+dispHostname,

			// Contrary to usual Go idiom, the Discover function returns
			// full sentences with initial capitalization in its error messages,
			// and they are written with the end-user as the audience. We
			// only need to add the trailing period to make them consistent
			// with our usual error reporting standards.
			err.Error()+".",
		))
		c.showDiagnostics(diags)
		return 1
	}

	creds := c.Services.CredentialsSource().(*cliconfig.CredentialsSource)
	filename, _ := creds.CredentialsFilePath()
	credsCtx := &loginCredentialsContext{
		Location:      creds.HostCredentialsLocation(hostname),
		LocalFilename: filename, // empty in the very unlikely event that we can't select a config directory for this user
		HelperType:    creds.CredentialsHelperType(),
	}

	clientConfig, err := host.ServiceOAuthClient("login.v1")
	switch err.(type) {
	case nil:
		// Great! No problem, then.
	case *disco.ErrServiceNotProvided:
		// This is also fine! We'll try the manual token creation process.
	case *disco.ErrVersionNotSupported:
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Warning,
			"Host does not support Terraform login",
			fmt.Sprintf("The given hostname %q allows creating Terraform authorization tokens, but requires a newer version of Terraform CLI to do so.", dispHostname),
		))
	default:
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Warning,
			"Host does not support Terraform login",
			fmt.Sprintf("The given hostname %q cannot support \"terraform login\": %s.", dispHostname, err),
		))
	}

	// If login service is unavailable, check for a TFE v2 API as fallback
	var tfeservice *url.URL
	if clientConfig == nil {
		tfeservice, err = host.ServiceURL("tfe.v2")
		switch err.(type) {
		case nil:
			// Success!
		case *disco.ErrServiceNotProvided:
			diags = diags.Append(tfdiags.Sourceless(
				tfdiags.Error,
				"Host does not support Terraform tokens API",
				fmt.Sprintf("The given hostname %q does not support creating Terraform authorization tokens.", dispHostname),
			))
		case *disco.ErrVersionNotSupported:
			diags = diags.Append(tfdiags.Sourceless(
				tfdiags.Error,
				"Host does not support Terraform tokens API",
				fmt.Sprintf("The given hostname %q allows creating Terraform authorization tokens, but requires a newer version of Terraform CLI to do so.", dispHostname),
			))
		default:
			diags = diags.Append(tfdiags.Sourceless(
				tfdiags.Error,
				"Host does not support Terraform tokens API",
				fmt.Sprintf("The given hostname %q cannot support \"terraform login\": %s.", dispHostname, err),
			))
		}
	}

	if credsCtx.Location == cliconfig.CredentialsInOtherFile {
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Error,
			fmt.Sprintf("Credentials for %s are manually configured", dispHostname),
			"The \"terraform login\" command cannot log in because credentials for this host are already configured in a CLI configuration file.\n\nTo log in, first revoke the existing credentials and remove that block from the CLI configuration.",
		))
	}

	if diags.HasErrors() {
		c.showDiagnostics(diags)
		return 1
	}

	var token svcauth.HostCredentialsToken
	var tokenDiags tfdiags.Diagnostics

	// Prefer Terraform login if available
	if clientConfig != nil {
		var oauthToken *oauth2.Token

		switch {
		case clientConfig.SupportedGrantTypes.Has(disco.OAuthAuthzCodeGrant):
			// We prefer an OAuth code grant if the server supports it.
			oauthToken, tokenDiags = c.interactiveGetTokenByCode(hostname, credsCtx, clientConfig)
		case clientConfig.SupportedGrantTypes.Has(disco.OAuthOwnerPasswordGrant) && hostname == svchost.Hostname("app.terraform.io"):
			// The password grant type is allowed only for Terraform Cloud SaaS.
			// Note this case is purely theoretical at this point, as TFC currently uses
			// its own bespoke login protocol (tfe)
			oauthToken, tokenDiags = c.interactiveGetTokenByPassword(hostname, credsCtx, clientConfig)
		default:
			tokenDiags = tokenDiags.Append(tfdiags.Sourceless(
				tfdiags.Error,
				"Host does not support Terraform login",
				fmt.Sprintf("The given hostname %q does not allow any OAuth grant types that are supported by this version of Terraform.", dispHostname),
			))
		}
		if oauthToken != nil {
			token = svcauth.HostCredentialsToken(oauthToken.AccessToken)
		}
	} else if tfeservice != nil {
		token, tokenDiags = c.interactiveGetTokenByUI(hostname, credsCtx, tfeservice)
	}

	diags = diags.Append(tokenDiags)
	if diags.HasErrors() {
		c.showDiagnostics(diags)
		return 1
	}

	err = creds.StoreForHost(hostname, token)
	if err != nil {
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Error,
			"Failed to save API token",
			fmt.Sprintf("The given host returned an API token, but Terraform failed to save it: %s.", err),
		))
	}

	c.showDiagnostics(diags)
	if diags.HasErrors() {
		return 1
	}

	c.Ui.Output("\n---------------------------------------------------------------------------------\n")
	if hostname == "app.terraform.io" { // Terraform Cloud
		var motd struct {
			Message string        `json:"msg"`
			Errors  []interface{} `json:"errors"`
		}

		// Throughout the entire process of fetching a MOTD from TFC, use a default
		// message if the platform-provided message is unavailable for any reason -
		// be it the service isn't provided, the request failed, or any sort of
		// platform error returned.

		motdServiceURL, err := host.ServiceURL("motd.v1")
		if err != nil {
			c.logMOTDError(err)
			c.outputDefaultTFCLoginSuccess()
			return 0
		}

		req, err := http.NewRequest("GET", motdServiceURL.String(), nil)
		if err != nil {
			c.logMOTDError(err)
			c.outputDefaultTFCLoginSuccess()
			return 0
		}

		req.Header.Set("Authorization", "Bearer "+token.Token())

		resp, err := httpclient.New().Do(req)
		if err != nil {
			c.logMOTDError(err)
			c.outputDefaultTFCLoginSuccess()
			return 0
		}

		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			c.logMOTDError(err)
			c.outputDefaultTFCLoginSuccess()
			return 0
		}

		defer resp.Body.Close()
		json.Unmarshal(body, &motd)

		if motd.Errors == nil && motd.Message != "" {
			c.Ui.Output(
				c.Colorize().Color(motd.Message),
			)
			return 0
		} else {
			c.logMOTDError(fmt.Errorf("platform responded with errors or an empty message"))
			c.outputDefaultTFCLoginSuccess()
			return 0
		}
	}

	if tfeservice != nil { // Terraform Enterprise
		c.outputDefaultTFELoginSuccess(dispHostname)
	} else {
		c.Ui.Output(
			fmt.Sprintf(
				c.Colorize().Color(strings.TrimSpace(`
[green][bold]Success![reset] [bold]Terraform has obtained and saved an API token.[reset]

The new API token will be used for any future Terraform command that must make
authenticated requests to %s.
`)),
				dispHostname,
			) + "\n",
		)
	}

	return 0
}

func (c *LoginCommand) outputDefaultTFELoginSuccess(dispHostname string) {
	c.Ui.Output(
		fmt.Sprintf(
			c.Colorize().Color(strings.TrimSpace(`
[green][bold]Success![reset] [bold]Logged in to Terraform Enterprise (%s)[reset]
`)),
			dispHostname,
		) + "\n",
	)
}

func (c *LoginCommand) outputDefaultTFCLoginSuccess() {
	c.Ui.Output(c.Colorize().Color(strings.TrimSpace(`
[green][bold]Success![reset] [bold]Logged in to Terraform Cloud[reset]
` + "\n")))
}

func (c *LoginCommand) logMOTDError(err error) {
	log.Printf("[TRACE] login: An error occurred attempting to fetch a message of the day for Terraform Cloud: %s", err)
}

// Help implements cli.Command.
func (c *LoginCommand) Help() string {
	defaultFile := c.defaultOutputFile()
	if defaultFile == "" {
		// Because this is just for the help message and it's very unlikely
		// that a user wouldn't have a functioning home directory anyway,
		// we'll just use a placeholder here. The real command has some
		// more complex behavior for this case. This result is not correct
		// on all platforms, but given how unlikely we are to hit this case
		// that seems okay.
		defaultFile = "~/.terraform/credentials.tfrc.json"
	}

	helpText := fmt.Sprintf(`
Usage: terraform [global options] login [hostname]

  Retrieves an authentication token for the given hostname, if it supports
  automatic login, and saves it in a credentials file in your home directory.

  If no hostname is provided, the default hostname is app.terraform.io, to
  log in to Terraform Cloud.

  If not overridden by credentials helper settings in the CLI configuration,
  the credentials will be written to the following local file:
      %s
`, defaultFile)
	return strings.TrimSpace(helpText)
}

// Synopsis implements cli.Command.
func (c *LoginCommand) Synopsis() string {
	return "Obtain and save credentials for a remote host"
}

func (c *LoginCommand) defaultOutputFile() string {
	if c.CLIConfigDir == "" {
		return "" // no default available
	}
	return filepath.Join(c.CLIConfigDir, "credentials.tfrc.json")
}

func (c *LoginCommand) interactiveGetTokenByCode(hostname svchost.Hostname, credsCtx *loginCredentialsContext, clientConfig *disco.OAuthClient) (*oauth2.Token, tfdiags.Diagnostics) {
	var diags tfdiags.Diagnostics

	confirm, confirmDiags := c.interactiveContextConsent(hostname, disco.OAuthAuthzCodeGrant, credsCtx)
	diags = diags.Append(confirmDiags)
	if !confirm {
		diags = diags.Append(errors.New("Login cancelled"))
		return nil, diags
	}

	// We'll use an entirely pseudo-random UUID for our temporary request
	// state. The OAuth server must echo this back to us in the callback
	// request to make it difficult for some other running process to
	// interfere by sending its own request to our temporary server.
	reqState, err := uuid.GenerateUUID()
	if err != nil {
		// This should be very unlikely, but could potentially occur if e.g.
		// there's not enough pseudo-random entropy available.
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Error,
			"Can't generate login request state",
			fmt.Sprintf("Cannot generate random request identifier for login request: %s.", err),
		))
		return nil, diags
	}

	proofKey, proofKeyChallenge, err := c.proofKey()
	if err != nil {
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Error,
			"Can't generate login request state",
			fmt.Sprintf("Cannot generate random prrof key for login request: %s.", err),
		))
		return nil, diags
	}

	listener, callbackURL, err := c.listenerForCallback(clientConfig.MinPort, clientConfig.MaxPort)
	if err != nil {
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Error,
			"Can't start temporary login server",
			fmt.Sprintf(
				"The login process uses OAuth, which requires starting a temporary HTTP server on localhost. However, no TCP port numbers between %d and %d are available to create such a server.",
				clientConfig.MinPort, clientConfig.MaxPort,
			),
		))
		return nil, diags
	}

	// codeCh will allow our temporary HTTP server to transmit the OAuth code
	// to the main execution path that follows.
	codeCh := make(chan string)
	server := &http.Server{
		Handler: http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
			log.Printf("[TRACE] login: request to callback server")
			err := req.ParseForm()
			if err != nil {
				log.Printf("[ERROR] login: cannot ParseForm on callback request: %s", err)
				resp.WriteHeader(400)
				return
			}
			gotState := req.Form.Get("state")
			if gotState != reqState {
				log.Printf("[ERROR] login: incorrect \"state\" value in callback request")
				resp.WriteHeader(400)
				return
			}
			gotCode := req.Form.Get("code")
			if gotCode == "" {
				log.Printf("[ERROR] login: no \"code\" argument in callback request")
				resp.WriteHeader(400)
				return
			}

			log.Printf("[TRACE] login: request contains an authorization code")

			// Send the code to our blocking wait below, so that the token
			// fetching process can continue.
			codeCh <- gotCode
			close(codeCh)

			log.Printf("[TRACE] login: returning response from callback server")

			resp.Header().Add("Content-Type", "text/html")
			resp.WriteHeader(200)
			resp.Write([]byte(callbackSuccessMessage))
		}),
	}
	go func() {
		defer logging.PanicHandler()
		err := server.Serve(listener)
		if err != nil && err != http.ErrServerClosed {
			diags = diags.Append(tfdiags.Sourceless(
				tfdiags.Error,
				"Can't start temporary login server",
				fmt.Sprintf(
					"The login process uses OAuth, which requires starting a temporary HTTP server on localhost. However, no TCP port numbers between %d and %d are available to create such a server.",
					clientConfig.MinPort, clientConfig.MaxPort,
				),
			))
			close(codeCh)
		}
	}()

	oauthConfig := &oauth2.Config{
		ClientID:    clientConfig.ID,
		Endpoint:    clientConfig.Endpoint(),
		RedirectURL: callbackURL,
		Scopes:      clientConfig.Scopes,
	}

	authCodeURL := oauthConfig.AuthCodeURL(
		reqState,
		oauth2.SetAuthURLParam("code_challenge", proofKeyChallenge),
		oauth2.SetAuthURLParam("code_challenge_method", "S256"),
	)

	launchBrowserManually := false
	if c.BrowserLauncher != nil {
		err = c.BrowserLauncher.OpenURL(authCodeURL)
		if err == nil {
			c.Ui.Output(fmt.Sprintf("Terraform must now open a web browser to the login page for %s.\n", hostname.ForDisplay()))
			c.Ui.Output(fmt.Sprintf("If a browser does not open this automatically, open the following URL to proceed:\n    %s\n", authCodeURL))
		} else {
			// Assume we're on a platform where opening a browser isn't possible.
			launchBrowserManually = true
		}
	} else {
		launchBrowserManually = true
	}

	if launchBrowserManually {
		c.Ui.Output(fmt.Sprintf("Open the following URL to access the login page for %s:\n    %s\n", hostname.ForDisplay(), authCodeURL))
	}

	c.Ui.Output("Terraform will now wait for the host to signal that login was successful.\n")

	code, ok := <-codeCh
	if !ok {
		// If we got no code at all then the server wasn't able to start
		// up, so we'll just give up.
		return nil, diags
	}

	if err := server.Close(); err != nil {
		// The server will close soon enough when our process exits anyway,
		// so we won't fuss about it for right now.
		log.Printf("[WARN] login: callback server can't shut down: %s", err)
	}

	ctx := context.WithValue(context.Background(), oauth2.HTTPClient, httpclient.New())
	token, err := oauthConfig.Exchange(
		ctx, code,
		oauth2.SetAuthURLParam("code_verifier", proofKey),
	)
	if err != nil {
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Error,
			"Failed to obtain auth token",
			fmt.Sprintf("The remote server did not assign an auth token: %s.", err),
		))
		return nil, diags
	}

	return token, diags
}

func (c *LoginCommand) interactiveGetTokenByPassword(hostname svchost.Hostname, credsCtx *loginCredentialsContext, clientConfig *disco.OAuthClient) (*oauth2.Token, tfdiags.Diagnostics) {
	var diags tfdiags.Diagnostics

	confirm, confirmDiags := c.interactiveContextConsent(hostname, disco.OAuthOwnerPasswordGrant, credsCtx)
	diags = diags.Append(confirmDiags)
	if !confirm {
		diags = diags.Append(errors.New("Login cancelled"))
		return nil, diags
	}

	c.Ui.Output("\n---------------------------------------------------------------------------------\n")
	c.Ui.Output("Terraform must temporarily use your password to request an API token.\nThis password will NOT be saved locally.\n")

	username, err := c.UIInput().Input(context.Background(), &terraform.InputOpts{
		Id:    "username",
		Query: fmt.Sprintf("Username for %s:", hostname.ForDisplay()),
	})
	if err != nil {
		diags = diags.Append(fmt.Errorf("Failed to request username: %s", err))
		return nil, diags
	}
	password, err := c.UIInput().Input(context.Background(), &terraform.InputOpts{
		Id:     "password",
		Query:  fmt.Sprintf("Password for %s:", hostname.ForDisplay()),
		Secret: true,
	})
	if err != nil {
		diags = diags.Append(fmt.Errorf("Failed to request password: %s", err))
		return nil, diags
	}

	oauthConfig := &oauth2.Config{
		ClientID: clientConfig.ID,
		Endpoint: clientConfig.Endpoint(),
		Scopes:   clientConfig.Scopes,
	}
	token, err := oauthConfig.PasswordCredentialsToken(context.Background(), username, password)
	if err != nil {
		// FIXME: The OAuth2 library generates errors that are not appropriate
		// for a Terraform end-user audience, so once we have more experience
		// with which errors are most common we should try to recognize them
		// here and produce better error messages for them.
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Error,
			"Failed to retrieve API token",
			fmt.Sprintf("The remote host did not issue an API token: %s.", err),
		))
	}

	return token, diags
}

func (c *LoginCommand) interactiveGetTokenByUI(hostname svchost.Hostname, credsCtx *loginCredentialsContext, service *url.URL) (svcauth.HostCredentialsToken, tfdiags.Diagnostics) {
	var diags tfdiags.Diagnostics

	confirm, confirmDiags := c.interactiveContextConsent(hostname, disco.OAuthGrantType(""), credsCtx)
	diags = diags.Append(confirmDiags)
	if !confirm {
		diags = diags.Append(errors.New("Login cancelled"))
		return "", diags
	}

	c.Ui.Output("\n---------------------------------------------------------------------------------\n")

	tokensURL := url.URL{
		Scheme:   "https",
		Host:     service.Hostname(),
		Path:     "/app/settings/tokens",
		RawQuery: "source=terraform-login",
	}

	launchBrowserManually := false
	if c.BrowserLauncher != nil {
		err := c.BrowserLauncher.OpenURL(tokensURL.String())
		if err == nil {
			c.Ui.Output(fmt.Sprintf("Terraform must now open a web browser to the tokens page for %s.\n", hostname.ForDisplay()))
			c.Ui.Output(fmt.Sprintf("If a browser does not open this automatically, open the following URL to proceed:\n    %s\n", tokensURL.String()))
		} else {
			log.Printf("[DEBUG] error opening web browser: %s", err)
			// Assume we're on a platform where opening a browser isn't possible.
			launchBrowserManually = true
		}
	} else {
		launchBrowserManually = true
	}

	if launchBrowserManually {
		c.Ui.Output(fmt.Sprintf("Open the following URL to access the tokens page for %s:\n    %s\n", hostname.ForDisplay(), tokensURL.String()))
	}

	c.Ui.Output("\n---------------------------------------------------------------------------------\n")
	c.Ui.Output("Generate a token using your browser, and copy-paste it into this prompt.\n")

	// credsCtx might not be set if we're using a mock credentials source
	// in a test, but it should always be set in normal use.
	if credsCtx != nil {
		switch credsCtx.Location {
		case cliconfig.CredentialsViaHelper:
			c.Ui.Output(fmt.Sprintf("Terraform will store the token in the configured %q credentials helper\nfor use by subsequent commands.\n", credsCtx.HelperType))
		case cliconfig.CredentialsInPrimaryFile, cliconfig.CredentialsNotAvailable:
			c.Ui.Output(fmt.Sprintf("Terraform will store the token in plain text in the following file\nfor use by subsequent commands:\n    %s\n", credsCtx.LocalFilename))
		}
	}

	token, err := c.UIInput().Input(context.Background(), &terraform.InputOpts{
		Id:     "token",
		Query:  fmt.Sprintf("Token for %s:", hostname.ForDisplay()),
		Secret: true,
	})
	if err != nil {
		diags := diags.Append(fmt.Errorf("Failed to retrieve token: %s", err))
		return "", diags
	}

	token = strings.TrimSpace(token)
	cfg := &tfe.Config{
		Address:  service.String(),
		BasePath: service.Path,
		Token:    token,
		Headers:  make(http.Header),
	}
	client, err := tfe.NewClient(cfg)
	if err != nil {
		diags = diags.Append(fmt.Errorf("Failed to create API client: %s", err))
		return "", diags
	}
	user, err := client.Users.ReadCurrent(context.Background())
	if err == tfe.ErrUnauthorized {
		diags = diags.Append(fmt.Errorf("Token is invalid: %s", err))
		return "", diags
	} else if err != nil {
		diags = diags.Append(fmt.Errorf("Failed to retrieve user account details: %s", err))
		return "", diags
	}
	c.Ui.Output(fmt.Sprintf(c.Colorize().Color("\nRetrieved token for user [bold]%s[reset]\n"), user.Username))

	return svcauth.HostCredentialsToken(token), nil
}

func (c *LoginCommand) interactiveContextConsent(hostname svchost.Hostname, grantType disco.OAuthGrantType, credsCtx *loginCredentialsContext) (bool, tfdiags.Diagnostics) {
	var diags tfdiags.Diagnostics
	mechanism := "OAuth"
	if grantType == "" {
		mechanism = "your browser"
	}

	c.Ui.Output(fmt.Sprintf("Terraform will request an API token for %s using %s.\n", hostname.ForDisplay(), mechanism))

	if grantType.UsesAuthorizationEndpoint() {
		c.Ui.Output(
			"This will work only if you are able to use a web browser on this computer to\ncomplete a login process. If not, you must obtain an API token by another\nmeans and configure it in the CLI configuration manually.\n",
		)
	}

	// credsCtx might not be set if we're using a mock credentials source
	// in a test, but it should always be set in normal use.
	if credsCtx != nil {
		switch credsCtx.Location {
		case cliconfig.CredentialsViaHelper:
			c.Ui.Output(fmt.Sprintf("If login is successful, Terraform will store the token in the configured\n%q credentials helper for use by subsequent commands.\n", credsCtx.HelperType))
		case cliconfig.CredentialsInPrimaryFile, cliconfig.CredentialsNotAvailable:
			c.Ui.Output(fmt.Sprintf("If login is successful, Terraform will store the token in plain text in\nthe following file for use by subsequent commands:\n    %s\n", credsCtx.LocalFilename))
		}
	}

	v, err := c.UIInput().Input(context.Background(), &terraform.InputOpts{
		Id:          "approve",
		Query:       "Do you want to proceed?",
		Description: `Only 'yes' will be accepted to confirm.`,
	})
	if err != nil {
		// Should not happen because this command checks that input is enabled
		// before we get to this point.
		diags = diags.Append(err)
		return false, diags
	}

	return strings.ToLower(v) == "yes", diags
}

func (c *LoginCommand) listenerForCallback(minPort, maxPort uint16) (net.Listener, string, error) {
	if minPort < 1024 || maxPort < 1024 {
		// This should never happen because it should've been checked by
		// the svchost/disco package when reading the service description,
		// but we'll prefer to fail hard rather than inadvertently trying
		// to open an unprivileged port if there are bugs at that layer.
		panic("listenerForCallback called with privileged port number")
	}

	availCount := int(maxPort) - int(minPort)

	// We're going to try port numbers within the range at random, so we need
	// to terminate eventually in case _none_ of the ports are available.
	// We'll make that 150% of the number of ports just to give us some room
	// for the random number generator to generate the same port more than
	// once.
	// Note that we don't really care about true randomness here... we're just
	// trying to hop around in the available port space rather than always
	// working up from the lowest, because we have no information to predict
	// that any particular number will be more likely to be available than
	// another.
	maxTries := availCount + (availCount / 2)

	for tries := 0; tries < maxTries; tries++ {
		port := rand.Intn(availCount) + int(minPort)
		addr := fmt.Sprintf("127.0.0.1:%d", port)
		log.Printf("[TRACE] login: trying %s as a listen address for temporary OAuth callback server", addr)
		l, err := net.Listen("tcp4", addr)
		if err == nil {
			// We use a path that doesn't end in a slash here because some
			// OAuth server implementations don't allow callback URLs to
			// end with slashes.
			callbackURL := fmt.Sprintf("http://localhost:%d/login", port)
			log.Printf("[TRACE] login: callback URL will be %s", callbackURL)
			return l, callbackURL, nil
		}
	}

	return nil, "", fmt.Errorf("no suitable TCP ports (between %d and %d) are available for the temporary OAuth callback server", minPort, maxPort)
}

func (c *LoginCommand) proofKey() (key, challenge string, err error) {
	// Wel use a UUID-like string as the "proof key for code exchange" (PKCE)
	// that will eventually authenticate our request to the token endpoint.
	// Standard UUIDs are explicitly not suitable as secrets according to the
	// UUID spec, but our go-uuid just generates totally random number sequences
	// formatted in the conventional UUID syntax, so that concern does not
	// apply here: this is just a 128-bit crypto-random number.
	uu, err := uuid.GenerateUUID()
	if err != nil {
		return "", "", err
	}

	key = fmt.Sprintf("%s.%09d", uu, rand.Intn(999999999))

	h := sha256.New()
	h.Write([]byte(key))
	challenge = base64.RawURLEncoding.EncodeToString(h.Sum(nil))

	return key, challenge, nil
}

type loginCredentialsContext struct {
	Location      cliconfig.CredentialsLocation
	LocalFilename string
	HelperType    string
}

const callbackSuccessMessage = `
<html>
<head>
<title>Terraform Login</title>
<style type="text/css">
body {
	font-family: monospace;
	color: #fff;
	background-color: #000;
}
</style>
</head>
<body>

<p>The login server has returned an authentication code to Terraform.</p>
<p>Now close this page and return to the terminal where <tt>terraform login</tt>
is running to see the result of the login process.</p>

</body>
</html>
`
