package main import ( "bufio" "bytes" "encoding/json" "io" "io/ioutil" "net/http" "os" ) type OAuth struct { Access_token string `"json:access_token"` Created_at int `"json:created_at"` Expires_in int64 `"json:Expires_in"` Refresh_token string `"json:refresh_token"` } type authError struct { msg string } func (e *authError) Error() string { return e.msg } func register_client(endpoint string, o *RunningInstance) error { requestBodymap, _ := json.Marshal(map[string]string{ "client_name": "Tusky", // Hard-coded in for now... "scopes": "read write follow push", "redirect_uris": "urn:ietf:wg:oauth:2.0:oob", }) requestBodybytes := bytes.NewBuffer(requestBodymap) api_base_apps := "https://" + endpoint + "/api/v1/apps" resp, err := o.client.Post(api_base_apps, "application/json", requestBodybytes) if err != nil { logErr.Print("Unable to connect to "+api_base_apps+" ", err) return err } body, err := ioutil.ReadAll(resp.Body) if err != nil { logErr.Print("Unable to read HTTP response: ", err) o.client_id = "" o.client_secret = "" return err } defer resp.Body.Close() bodymap := make(map[string]string) err = json.Unmarshal(body, &bodymap) if err != nil { logErr.Print("Unable to parse response from "+endpoint+": ", err) o.client_id = "" o.client_secret = "" return err } client_file := "clients/" + endpoint f, err := os.Create("clients/" + endpoint) if err != nil { logErr.Print("Unable to create "+client_file+": ", err) o.client_id = "" o.client_secret = "" return err } defer f.Close() _, err = io.WriteString(f, bodymap["client_id"]+"\n") if err != nil { logErr.Print("Unable to write client_id line to file "+client_file+": ", err) o.client_id = bodymap["client_id"] o.client_secret = bodymap["client_secret"] return nil } _, err = io.WriteString(f, bodymap["client_secret"]+"\n") if err != nil { logErr.Print("Unable to write client_secret to file "+client_file+": ", err) o.client_id = bodymap["client_id"] o.client_secret = bodymap["client_secret"] return nil } o.client_id = bodymap["client_id"] o.client_secret = bodymap["client_secret"] return nil } func get_client(endpoint string, o *RunningInstance) error { var err error client_file := "clients/" + endpoint _, err = os.Stat(client_file) if os.IsNotExist(err) == false { // The file exists f, err := os.Open(client_file) if err != nil { logErr.Print("Unable to open " + client_file + ", creating new client") return err } defer f.Close() rd := bufio.NewReader(f) client_id_bin, _, err := rd.ReadLine() o.client_id = string(client_id_bin) if err != nil { logErr.Print("Unable to read client_id line of " + client_file + ", building new client") return err } client_secret_bin, _, err := rd.ReadLine() o.client_secret = string(client_secret_bin) if err != nil { logErr.Print("Unable to read client_secret line of " + client_file + ", building new client") return err } return nil } else { return register_client(endpoint, o) } return nil } func oauth_login(endpoint string, o *RunningInstance, username string, password string) (OAuth, error) { authMap, err := json.Marshal(map[string]string{ "username": username, "password": password, "redirect_uri": "urn:ietf:wg:oauth:2.0:oob", "grant_type": "password", "client_name": "Tusky", "scope": "read write follow push", "client_id": o.client_id, "client_secret": o.client_secret, }) if err != nil { logErr.Print("Unable to create Authentication map for "+endpoint) return OAuth{}, err } authMapbytes := bytes.NewBuffer(authMap) resp, err := http.Post("https://"+endpoint+"/oauth/token", "application/json", authMapbytes) if err != nil { logErr.Print("Cannot connect to "+endpoint+": ", err) return OAuth{}, err } body, err := ioutil.ReadAll(resp.Body) if err != nil { logErr.Print("Unable to read response data for "+endpoint+": ", err) return OAuth{}, err } if resp.StatusCode == 400 { logErr.Print("Unable to authenticate to " + endpoint) return OAuth{}, &authError{"Authentication error"} } oauthData := OAuth{} err = json.Unmarshal(body, &oauthData) if err != nil { logErr.Print("Unable to parse json data for "+endpoint+": ", err) return OAuth{}, err } return oauthData, nil } func oauth_refresh(endpoint string, client_id string, client_secret string, refresh_token string) (OAuth, error) { authMap, _ := json.Marshal(map[string]string{ "redirect_uri": "urn:ietf:wg:oauth:2.0:oob", "grant_type": "refresh_token", "scope": "read write follow push", "refresh_token": refresh_token, "client_id": client_id, "client_secret": client_secret, }) authMapbytes := bytes.NewBuffer(authMap) resp, err := http.Post("https://"+endpoint+"/oauth/token", "application/json", authMapbytes) if err != nil { logErr.Print("Unable to connect to "+endpoint+": ", err) return OAuth{}, err } body, err := ioutil.ReadAll(resp.Body) if err != nil { logErr.Print("Unable to read response data for "+endpoint+": ", err) return OAuth{}, err } oauthData := OAuth{} err = json.Unmarshal(body, &oauthData) if err != nil { logErr.Print("Unable to parse json data for "+endpoint+": ", err) return oauthData, err } return oauthData, nil }