diff --git a/README.md b/README.md index 3fdc654..4051f4d 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ This repository provides `engflow_auth`, a [Bazel credential helper](https://blo ## Use -1. Run `engflow_auth login [CLUSTER URL]` to obtain a credential. This prints a URL to visit in your browser. +1. Run `engflow_auth login [CLUSTER URL]` to obtain a credential. This opens a URL in your browser. 1. Visit the URL to complete the process, logging in if necessary. `engflow_auth` will download and store a credential in on your system's encrypted keyring. This process needs to be repeated after the credential expires, typically every 90 days. diff --git a/cmd/engflow_auth/main.go b/cmd/engflow_auth/main.go index 2fcb4a9..be4c678 100644 --- a/cmd/engflow_auth/main.go +++ b/cmd/engflow_auth/main.go @@ -47,7 +47,7 @@ const ( ) type appState struct { - // These vars are initialized by `build()` iff they are not pre-populated; + // These vars are initialized by `build()` if and only if they are not pre-populated; // they should be pre-populated in tests and left nil otherwise. userConfigDir string browserOpener browser.Opener diff --git a/internal/browser/browser.go b/internal/browser/browser.go index 6f59e00..14e0d5f 100644 --- a/internal/browser/browser.go +++ b/internal/browser/browser.go @@ -18,6 +18,8 @@ import ( "fmt" "net/url" "os" + "os/exec" + "runtime" ) type Opener interface { @@ -26,11 +28,43 @@ type Opener interface { type StderrPrint struct{} +func openURL(url string) error { + switch runtime.GOOS { + case "darwin": // macOS + return exec.Command("open", url).Run() + case "linux": + providers := []string{"xdg-open", "x-www-browser", "www-browser"} + + // There are multiple possible providers to open a browser on linux + // One of them is xdg-open, another is x-www-browser, then there's www-browser, etc. + // Look for one that exists and run it + for _, provider := range providers { + if binPath, err := exec.LookPath(provider); err == nil { + err = exec.Command(binPath, url).Run() + if err == nil { + return nil + } + } + } + return fmt.Errorf("unsupported platform") + case "windows": + return exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Run() + default: + return fmt.Errorf("unsupported platform") + } +} + func (p *StderrPrint) Open(u *url.URL) error { fmt.Fprintf( os.Stderr, - "Please open the following URL in your web browser to authenticate:\n\n\t%s\n\n", + `Attempting to automaticaly open the authentication URL in your web browser. +If the browser does not open or you wish to use a different device to authorize this request, open the following URL: + + %s + +`, u, ) + _ = openURL(u.String()) return nil }