Package fitbit: Revoke the access token in addition to deleting it.
[kraftakt.git] / fitbit / fitbit.go
index ef6282e..0d03244 100644 (file)
@@ -11,14 +11,17 @@ import (
        "fmt"
        "io/ioutil"
        "net/http"
+       "net/url"
        "strings"
        "time"
 
        "github.com/octo/kraftakt/app"
+       "github.com/octo/retry"
        "golang.org/x/oauth2"
        oauth2fitbit "golang.org/x/oauth2/fitbit"
        "google.golang.org/appengine"
        "google.golang.org/appengine/log"
+       "google.golang.org/appengine/urlfetch"
 )
 
 func oauthConfig() *oauth2.Config {
@@ -353,8 +356,47 @@ func (c *Client) ListSubscriptions(ctx context.Context, collection string) ([]Su
        return ret, nil
 }
 
+func (c *Client) revokeToken(ctx context.Context) error {
+       tok, err := c.appUser.Token(ctx, "Fitbit")
+       if err != nil {
+               return err
+       }
+
+       httpClient := urlfetch.Client(ctx)
+       httpClient.Transport = retry.NewTransport(httpClient.Transport)
+
+       url := "https://api.fitbit.com/oauth2/revoke?token=" + url.QueryEscape(tok.AccessToken)
+       req, err := http.NewRequest(http.MethodGet, url, nil)
+       if err != nil {
+               return err
+       }
+       req.Header.Set("Authorization", "Basic "+
+               base64.StdEncoding.EncodeToString([]byte(
+                       app.Config.FitbitClientID+":"+app.Config.FitbitClientSecret)))
+
+       res, err := httpClient.Do(req)
+       if err != nil {
+               return fmt.Errorf("GET %s: %v", url, err)
+       }
+       defer res.Body.Close()
+
+       if res.StatusCode != http.StatusOK {
+               if data, err := ioutil.ReadAll(res.Body); err == nil {
+                       return fmt.Errorf("GET %s: %s", url, data)
+               } else {
+                       return fmt.Errorf("GET %s: %s", url, res.Status)
+               }
+       }
+
+       return nil
+}
+
 // DeleteToken deletes the Fitbit OAuth2 token.
 func (c *Client) DeleteToken(ctx context.Context) error {
+       if err := c.revokeToken(ctx); err != nil {
+               log.Warningf(ctx, "revokeToken() = %v", err)
+       }
+
        return c.appUser.DeleteToken(ctx, "Fitbit")
 }