package main import ( "flag" "fmt" "time" "net/http" "net/url" "io/ioutil" "strconv" "strings" "encoding/json" ) var ( httpPort = flag.Int("http_port", 80, "HTTP port to serve on (defaults to 80)") ) type TokenResponse struct { AccessToken string `json:"access_token"` TokenType string `json:"token_type"` ExpiresIn int `json:"expires_in"` RefreshToken string `json:"refresh_token"` Scope string `json:"scope"` RefreshTokenIssuedAt string `json:"refresh_token_issued_at"` IssueAt string `json:"issued_at"` UsagePointId string `json:"usage_points_id"` } func main() { // Parse the flags flag.Parse() mux := http.NewServeMux() fmt.Println("Server started") mux.HandleFunc("/auth", func(w http.ResponseWriter, r *http.Request) { fmt.Println("*******************") fmt.Println(time.Now().Format("2006-01-02 15:04:05"), "- New auth request") query := r.URL.Query() fmt.Println(time.Now().Format("2006-01-02 15:04:05"), "- Query received - ", query) clientId := query.Get("client_id") state := query.Get("state") cozyOrigin := query.Get("redirect_uri") // here we use the redirect_uri param to transmit our stack url redirectUri := "https://oauth-proxy.wf.alpha.grandlyon.com/" responseType := "code" authReq := "https://gw.hml.api.enedis.fr/dataconnect/v1/oauth2/authorize?client_id="+ clientId +"&duration=P6M&redirect_uri="+ redirectUri +"&response_type="+ responseType +"&state="+ state +"-"+ cozyOrigin fmt.Println(time.Now().Format("2006-01-02 15:04:05"), "- Send request to auth endpoint", authReq) response, err := http.Get(authReq) fmt.Println(time.Now().Format("2006-01-02 15:04:05"), "- Endpoint response with status", response.Status) if err != nil { fmt.Println(err) } else { defer response.Body.Close() contents, err := ioutil.ReadAll(response.Body) if err != nil { fmt.Println(err) } // TO BE REMOVE FOR PROD API // Get the response body as a string pageContentString := string(contents) // Prevent the closure of the opener pageContentString = strings.ReplaceAll(pageContentString, "this.window.opener.location.href = url;", "this.window.location.href = url;") // fmt.Println(pageContentString) // Convert string to byte for response writting newPageContentByte := []byte(pageContentString) if response.StatusCode >= 200 && response.StatusCode <= 299 { w.Write(newPageContentByte) } else { http.Error(w, http.StatusText(response.StatusCode), response.StatusCode) } } }) // To be change by "/redirect" once enedis will have change the redirect uri mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Println("*******************") fmt.Println(time.Now().Format("2006-01-02 15:04:05"), "- New redirect request") query := r.URL.Query() fmt.Println(query) code := query.Get("code") req_state := query.Get("state") splitIndex := strings.Index(req_state, "-") if splitIndex == -1 { fmt.Println("No host found") } state := req_state[0:splitIndex] host := req_state[splitIndex+1:len(req_state)] usagePointId := query.Get("usage_point_id") redir := host + "?code=" + code + "&state="+ state +"&usage_point_id=" + usagePointId fmt.Println(time.Now().Format("2006-01-02 15:04:05"), "- Redirect to -", redir) http.Redirect(w, r, redir, 302) }) mux.HandleFunc("/token", func(w http.ResponseWriter, r *http.Request) { fmt.Println("*******************") fmt.Println(time.Now().Format("2006-01-02 15:04:05"), "- New token request") query := r.URL.Query() fmt.Println(query) clientId := "" clientSecret := "" code := "" grantType := "" refreshToken := "" // For request token params are into query parameters if len(query) == 0 { fmt.Println(time.Now().Format("2006-01-02 15:04:05"), " - No params found in url query - Trying to catch them from body") contents, err := ioutil.ReadAll(r.Body) if err != nil { fmt.Println(err) } pageContent := string(contents) //Check for client_id clientIdStartIndex := strings.Index(pageContent, "client_id=") if clientIdStartIndex == -1 { fmt.Println(time.Now().Format("2006-01-02 15:04:05"), " - Error - No client_id found") http.Error(w, http.StatusText(500), 500) } clientIdStartIndex += 10 clientId = pageContent[clientIdStartIndex:clientIdStartIndex + 36] //Check for client_secret clientSecretStartIndex := strings.Index(pageContent, "client_secret=") if clientSecretStartIndex == -1 { fmt.Println(time.Now().Format("2006-01-02 15:04:05"), " - Error - No client_secret found") http.Error(w, http.StatusText(500), 500) } clientSecretStartIndex += 14 clientSecret = pageContent[clientSecretStartIndex:clientSecretStartIndex + 36] //Check for code codeStartIndex := strings.Index(pageContent, "code=") if codeStartIndex == -1 { fmt.Println(time.Now().Format("2006-01-02 15:04:05"), " - Info - No code found (optionnal param)") } else { codeStartIndex += 5 code = pageContent[codeStartIndex:codeStartIndex + 30] } //Check for grant_type grandTypeStartIndex := strings.Index(pageContent, "grant_type=") if grandTypeStartIndex == -1 { fmt.Println(time.Now().Format("2006-01-02 15:04:05"), " - Error - No grant_type found") http.Error(w, http.StatusText(500), 500) } grandTypeStartIndex += 11 tempGrandTypeString := pageContent[grandTypeStartIndex:len(pageContent)] grandTypeEndIndex := strings.Index(tempGrandTypeString, "&") if grandTypeEndIndex == -1 { fmt.Println(time.Now().Format("2006-01-02 15:04:05"), " - Error - No closing tag for grant_type found") http.Error(w, http.StatusText(500), 500) } grantType = tempGrandTypeString[0:grandTypeEndIndex] //Check for refresh_token refershTokenStartIndex := strings.Index(pageContent, "refresh_token=") if refershTokenStartIndex == -1 { fmt.Println(time.Now().Format("2006-01-02 15:04:05"), " - Error - No refresh_token found") http.Error(w, http.StatusText(500), 500) } refershTokenStartIndex += 14 refreshToken = pageContent[refershTokenStartIndex:refershTokenStartIndex + 46] } else { // Retrieve params from query clientId = query.Get("client_id") clientSecret = query.Get("client_secret") code = query.Get("code") grantType = query.Get("grant_type") refreshToken = query.Get("refresh_token") } // Print out the result fmt.Printf("client_id: %s\n", clientId) fmt.Printf("client_secret: %s\n", clientSecret) fmt.Printf("code: %s\n", code) fmt.Printf("grant_type: %s\n", grantType) fmt.Printf("refresh_token: %s\n", refreshToken) tokenUrl := "https://gw.hml.api.enedis.fr/v1/oauth2/token" data := url.Values{} data.Set("client_id", clientId) data.Set("client_secret", clientSecret) data.Set("code", code) data.Set("grant_type", grantType) if refreshToken != "" { data.Set("refresh_token", refreshToken) data.Set("grant_type", "refresh_token") } client := &http.Client{} req, _ := http.NewRequest("POST", tokenUrl, strings.NewReader(data.Encode())) req.Header.Add("Content-Type", "application/x-www-form-urlencoded") fmt.Println(time.Now().Format("2006-01-02 15:04:05"), "- Send request to token endpoint", tokenUrl) response, err := client.Do(req) fmt.Println(time.Now().Format("2006-01-02 15:04:05"), "- Endpoint response with status", response.Status) if err != nil { fmt.Println(err) } else { defer response.Body.Close() if response.StatusCode >= 200 && response.StatusCode <= 299 { // Set Content-Type in response header w.Header().Add("Content-Type", "application/json") // Decode response Body using the defined type "TokenResponse" data := TokenResponse{} decodeError := json.NewDecoder(response.Body).Decode(&data) if decodeError != nil { http.Error(w, decodeError.Error(), 500) return } // Response with json data jsonError := json.NewEncoder(w).Encode(data) if jsonError != nil { http.Error(w, jsonError.Error(), 500) return } } else { http.Error(w, http.StatusText(response.StatusCode), response.StatusCode) } } }) http.ListenAndServe(":"+strconv.Itoa(*httpPort), mux) }