get an available port for login localhost server, instead of hardcoded port
@@ -7,6 +7,7 @@ import (
"io/ioutil"
"log"
"math/rand"
+ "net"
"net/http"
"net/http/httputil"
"net/url"
@@ -97,20 +98,13 @@ type azureAPIHelper struct{}
//Login perform azure login through browser
func (login AzureLoginService) Login(ctx context.Context) error {
queryCh := make(chan url.Values, 1)
- mux := http.NewServeMux()
- mux.HandleFunc("/", queryHandler(queryCh))
- server := &http.Server{Addr: ":8401", Handler: mux}
- go func() {
- if err := server.ListenAndServe(); err != nil {
- queryCh <- url.Values{
- "error": []string{fmt.Sprintf("error starting http server with: %v", err)},
- }
+ serverPort, err := startLoginServer(queryCh)
+ if err != nil {
+ return err
}
- }()
- state := randomString("", 10)
- authURL := fmt.Sprintf(authorizeFormat, clientID, "http://localhost:8401", state, scopes)
- openbrowser(authURL)
+ redirectURL := "http://localhost:" + strconv.Itoa(serverPort)
+ openAzureLoginPage(redirectURL)
select {
case <-ctx.Done():
@@ -129,7 +123,7 @@ func (login AzureLoginService) Login(ctx context.Context) error {
"client_id": []string{clientID},
"code": code,
"scope": []string{scopes},
- "redirect_uri": []string{"http://localhost:8401"},
+ "redirect_uri": []string{redirectURL},
}
token, err := login.apiHelper.queryToken(data, "organizations")
if err != nil {
@@ -183,6 +177,32 @@ func (login AzureLoginService) Login(ctx context.Context) error {
}
}
+func startLoginServer(queryCh chan url.Values) (int, error) {
+ mux := http.NewServeMux()
+ mux.HandleFunc("/", queryHandler(queryCh))
+ listener, err := net.Listen("tcp", ":0")
+ if err != nil {
+ return 0, err
+ }
+
+ availablePort := listener.Addr().(*net.TCPAddr).Port
+ server := &http.Server{Handler: mux}
+ go func() {
+ if err := server.Serve(listener); err != nil {
+ queryCh <- url.Values{
+ "error": []string{fmt.Sprintf("error starting http server with: %v", err)},
+ }
+ }
+ }()
+ return availablePort, nil
+}
+
+func openAzureLoginPage(redirectURL string) {
+ state := randomString("", 10)
+ authURL := fmt.Sprintf(authorizeFormat, clientID, redirectURL, state, scopes)
+ openbrowser(authURL)
+}
+
func queryHandler(queryCh chan url.Values) func(w http.ResponseWriter, r *http.Request) {
queryHandler := func(w http.ResponseWriter, r *http.Request) {
_, hasCode := r.URL.Query()["code"]
