Newer
Older
httpPort = flag.Int("http_port", LookupEnvOrInt("HTTP_PORT", 80), "HTTP port to serve on (defaults to 80)")
logLevel = flag.String("loglevel", LookupEnvOrString("LOGLEVEL", "debug"), "log level (debug, info, warning, error) (defaults to debug)")
cozyDomain = flag.String("cozy_domain", LookupEnvOrString("COZY_DOMAIN", "cozy.wf.alpha.grandlyon.com"), "Cozy domain (defaults to cozy.wf.alpha.grandlyon.com)")
cozyRedirectURI = flag.String("cozy_redirect_uri", LookupEnvOrString("COZY_REDIRECT_URI", "/accounts/enedisgrandlyon/redirect"), "Cozy redirect URI (defaults to /accounts/enedisgrandlyon/redirect)")
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 LookupEnvOrString(key string, defaultVal string) string {
if val, ok := os.LookupEnv(key); ok {
return val
}
return defaultVal
}
func LookupEnvOrInt(key string, defaultVal int) int {
if val, ok := os.LookupEnv(key); ok {
v, err := strconv.Atoi(val)
if err != nil {
log.Fatalf("LookupEnvOrInt[%s]: %v", key, err)
}
return v
}
return defaultVal
}
func findItem(arrayType interface{}, item interface{}) bool {
arr := reflect.ValueOf(arrayType)
if arr.Kind() != reflect.Array {
panic("Invalid data-type")
}
for i := 0; i < arr.Len(); i++ {
if arr.Index(i).Interface() == item {
return true
}
}
return false
}
func main() {
// Parse the flags
flag.Parse()
// Init logging
log.SetOutput(os.Stdout)
log.SetFormatter(&log.TextFormatter{
PadLevelText: true,
ForceQuote: true,
DisableTimestamp: false,
FullTimestamp: true,
TimestampFormat: "2006-01-02 15:04:05",
})
// Configure log level
switch strings.ToLower(*logLevel) {
case "error":
log.SetLevel(log.ErrorLevel)
case "warning":
log.SetLevel(log.WarnLevel)
case "info":
log.SetLevel(log.InfoLevel)
case "debug":
log.SetLevel(log.DebugLevel)
default:
log.SetLevel(log.DebugLevel)
log.Fatalf("Unknown logging level %s. Choose between debug, info, warning or error.", *logLevel)
}
log.Infof("Starting Server on port %d\n", *httpPort)
mux.HandleFunc("/healthcheck", func(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "OK\n")
})
mux.HandleFunc("/auth", func(w http.ResponseWriter, r *http.Request) {
clientId := query.Get("client_id")
state := query.Get("state")
// here we use the redirect_uri param to transmit our stack url
// We keep only the instance name to not reach the 100 max char of redirectUrl
cozyOrigin := query.Get("redirect_uri")
splitIndexStart := strings.Index(cozyOrigin, ":")
if splitIndexStart == -1 {
log.Error("redirect_uri bad format " + cozyOrigin)
http.Error(w, http.StatusText(500), 500)
}
splitIndexEnd := strings.Index(cozyOrigin, ".")
if splitIndexEnd == -1 {
log.Error("redirect_uri bad format " + cozyOrigin)
http.Error(w, http.StatusText(500), 500)
}
instanceName := cozyOrigin[splitIndexStart+3:splitIndexEnd]
// authURL := "https://gw.hml.api.enedis.fr/dataconnect/v1/oauth2/authorize"
authURL := "https://mon-compte-particulier.enedis.fr/dataconnect/v1/oauth2/authorize"
redirectUrl := authURL + "?client_id=" + clientId + "&duration=P6M&response_type=" + responseType + "&state=" + state + "-" + instanceName
http.Redirect(w, r, redirectUrl, 302)
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
// GRDF ADICT ACCESS_TOKEN ENDPOINT
mux.HandleFunc("/grdfAccess", func(w http.ResponseWriter, r *http.Request) {
log.Debug("New grdf auth request")
query := r.URL.Query()
log.Debug("Query received - ", query)
clientId := query.Get("client_id")
state := query.Get("state")
scope := "/adict/v1"
// here we use the redirect_uri param to transmit our stack url
// We keep only the instance name to not reach the 100 max char of redirectUrl
cozyOrigin := query.Get("redirect_uri")
splitIndexStart := strings.Index(cozyOrigin, ":")
if splitIndexStart == -1 {
log.Error("redirect_uri bad format " + cozyOrigin)
http.Error(w, http.StatusText(500), 500)
}
splitIndexEnd := strings.Index(cozyOrigin, ".")
if splitIndexEnd == -1 {
log.Error("redirect_uri bad format " + cozyOrigin)
http.Error(w, http.StatusText(500), 500)
}
instanceName := cozyOrigin[splitIndexStart+3:splitIndexEnd]
// DEV API
// authURL := "https://gw.hml.api.enedis.fr/dataconnect/v1/oauth2/authorize"
// PROD API
authURL := "https://mon-compte-particulier.enedis.fr/dataconnect/v1/oauth2/authorize"
redirectUrl := authURL + "?client_id=" + clientId + "&duration=P6M&response_type=" + responseType + "&state=" + state + "-" + instanceName
log.Debug("Redirect to - ", redirectUrl)
http.Redirect(w, r, redirectUrl, 302)
})
//ENEDIS REDIRECT ENDPOINT
mux.HandleFunc("/redirect", func(w http.ResponseWriter, r *http.Request) {
req_state := query.Get("state")
statusCodes := [4]string{"400", "403", "500", "503"}
if (findItem(statusCodes, code)) {
intCode, err := strconv.Atoi(code)
if err != nil {
log.Print("status code string to int error: ", err)
}
log.Print("status code error : ", code)
http.Error(w, http.StatusText(intCode), intCode)
} else {
splitIndex := strings.Index(req_state, "-")
if splitIndex == -1 {
log.Warning("No host found")
}
state := req_state[0:splitIndex]
host := req_state[splitIndex+1:]
usagePointId := query.Get("usage_point_id")
cozyURL := "https://" + host + "." + *cozyDomain + *cozyRedirectURI
redir := cozyURL + "?code=" + code + "&state=" + state + "&usage_point_id=" + usagePointId
log.Debug("Redirect to -", redir)
http.Redirect(w, r, redir, 302)
}
mux.HandleFunc("/token", func(w http.ResponseWriter, r *http.Request) {
clientId := ""
clientSecret := ""
code := ""
grantType := ""
refreshToken := ""
// For request token params are into query parameters
log.Warn("No params found in url query - Trying to catch them from body")
contents, err := ioutil.ReadAll(r.Body)
if err != nil {
}
pageContent := string(contents)
//Check for client_id
clientIdStartIndex := strings.Index(pageContent, "client_id=")
if clientIdStartIndex == -1 {
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 {
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 {
log.Info("No code found (optional param)")
} else {
codeStartIndex += 5
}
//Check for grant_type
grandTypeStartIndex := strings.Index(pageContent, "grant_type=")
if grandTypeStartIndex == -1 {
http.Error(w, http.StatusText(500), 500)
}
grandTypeStartIndex += 11
grandTypeEndIndex := strings.Index(tempGrandTypeString, "&")
if grandTypeEndIndex == -1 {
http.Error(w, http.StatusText(500), 500)
}
grantType = tempGrandTypeString[0:grandTypeEndIndex]
//Check for refresh_token
refershTokenStartIndex := strings.Index(pageContent, "refresh_token=")
if refershTokenStartIndex == -1 {
}
refershTokenStartIndex += 14
refreshToken = pageContent[refershTokenStartIndex : refershTokenStartIndex+46]
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
log.WithFields(log.Fields{
"client_id": clientId,
"client_secret": clientSecret,
"code": code,
"grant_type": grantType,
"refresh_token": refreshToken,
}).Debug("result")
// tokenUrl := "https://gw.hml.api.enedis.fr/v1/oauth2/token"
tokenUrl := "https://gw.prd.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")
}
log.Debug("Send request to token endpoint: ", tokenUrl)
response, err := http.PostForm(tokenUrl, data)
log.Debug("Endpoint response with status", response.Status)
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)
log.Fatal(http.ListenAndServe(":"+strconv.Itoa(*httpPort), mux))