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_old", 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") cozyOrigin := query.Get("redirect_uri") // here we use the redirect_uri param to transmit our stack url state := query.Get("state") authReq := "https://gw.hml.api.enedis.fr/group/espace-particuliers/consentement-linky/oauth2/authorize?client_id="+ clientId +"&duration=P6M&redirect_uri=https://oauth-proxy.wf.alpha.grandlyon.com/&response_type=code&state="+ state +"-"+ cozyOrigin fmt.Println(authReq) response, err := http.Get(authReq) if err != nil { fmt.Println(err) } else { defer response.Body.Close() contents, err := ioutil.ReadAll(response.Body) if err != nil { fmt.Println(err) } // Get the response body as a string pageContent := string(contents) // Find a substr codeStartIndex := strings.Index(pageContent, "?code=") if codeStartIndex == -1 { fmt.Println("No code found") } codeStartIndex += 6 // Find the index of the closing tag codeEndIndex := strings.Index(pageContent, "&state=") if codeEndIndex == -1 { fmt.Println("No closing tag for code found.") } stateStartIndex := strings.Index(pageContent, "&state=") if stateStartIndex == -1 { fmt.Println("No state found") } stateStartIndex += 7 stateEndIndex := strings.Index(pageContent, "&usage_point_id=") if stateEndIndex == -1 { fmt.Println("No closing tag for state found.") } usageStartIndex := strings.Index(pageContent, "&usage_point_id=") if usageStartIndex == -1 { fmt.Println("No usage found") } usageStartIndex += 16 usageEndIndex := strings.Index(pageContent, "&usage_point_id=") if usageEndIndex == -1 { fmt.Println("No closing tag for usage found.") } usageEndIndex += 30 pageCode := string([]byte(pageContent[codeStartIndex:codeEndIndex])) pageState := string([]byte(pageContent[stateStartIndex:stateEndIndex])) pageUsage := string([]byte(pageContent[usageStartIndex:usageEndIndex])) // Print out the result fmt.Printf("Page code: %s\n", pageCode) fmt.Printf("Page state: %s\n", pageState) fmt.Printf("Page usage: %s\n", pageUsage) splitIndex := strings.Index(pageState, "-") if splitIndex == -1 { fmt.Println("No host found") } state := string([]byte(pageState[0:splitIndex])) encodedHost := string([]byte(pageState[splitIndex+1:len(pageState)])) host, err := url.QueryUnescape(encodedHost) if err != nil { fmt.Println("Host cannot be decoded") } redir := host + "?code=" + pageCode + "&state="+ state +"&usage_point_id=" + pageUsage fmt.Println(time.Now().Format("2006-01-02 15:04:05"), "- Redirect to -", redir) http.Redirect(w, r, redir, 302) } }) 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/redirect" responseType := "code" authReq := "https://gw.hml.api.enedis.fr/group/espace-particuliers/consentement-linky/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) } // Define the replyUri // replyUri := "https://oauth-proxy.wf.alpha.grandlyon.com/redirect" // fmt.Println(time.Now().Format("2006-01-02 15:04:05"), "- Reply to - ", replyUri) // Get the response body as a string pageContentString := string(contents) // Replace redirectUri by the host in the body // pageContentString = strings.ReplaceAll(pageContentString, redirectUri, replyUri) // 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) // fmt.Println(r.Host) if response.StatusCode >= 200 && response.StatusCode <= 299 { w.Write(newPageContentByte) } else { http.Error(w, http.StatusText(response.StatusCode), response.StatusCode) } } }) mux.HandleFunc("/redirect", 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 := string([]byte(req_state[0:splitIndex])) host := string([]byte(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 := query.Get("client_id") clientSecret := query.Get("client_secret") code := query.Get("code") grantType := query.Get("grant_type") refreshToken := query.Get("refresh_token") 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) }