import (
"context"
+ "crypto/hmac"
+ "crypto/sha1"
+ "encoding/hex"
"fmt"
"net/http"
"sync"
return u.Email
}
+func (u *User) Sign(payload string) string {
+ mac := hmac.New(sha1.New, []byte(u.ID))
+ mac.Write([]byte(payload))
+
+ return hex.EncodeToString(mac.Sum(nil))
+}
+
type persistingTokenSource struct {
ctx context.Context
t *oauth2.Token
}
}
-const csrfToken = "@CSRFTOKEN@"
-
-func AuthURL() string {
- return oauthConfig().AuthCodeURL(csrfToken, oauth2.AccessTypeOffline)
-}
-
func ParseToken(ctx context.Context, r *http.Request, u *app.User) error {
- if state := r.FormValue("state"); state != csrfToken {
+ if state := r.FormValue("state"); state != u.Sign("Fitbit") {
return fmt.Errorf("invalid state parameter: %q", state)
}
}, nil
}
+func (c *Client) AuthURL(ctx context.Context) string {
+ return oauthConfig().AuthCodeURL(c.appUser.Sign("Fitbit"), oauth2.AccessTypeOffline)
+}
+
func (c *Client) ActivitySummary(ctx context.Context, date string) (*ActivitySummary, error) {
url := fmt.Sprintf("https://api.fitbit.com/1/user/%s/activities/date/%s.json",
c.fitbitUserID, date)
)
const (
- csrfToken = "@CSRFTOKEN@"
- userID = "me"
+ userID = "me"
dataTypeNameCalories = "com.google.calories.expended"
dataTypeNameDistance = "com.google.distance.delta"
}
}
-func AuthURL() string {
- return oauthConfig().AuthCodeURL(csrfToken, oauth2.AccessTypeOffline)
-}
-
func ParseToken(ctx context.Context, r *http.Request, u *app.User) error {
- if state := r.FormValue("state"); state != csrfToken {
+ if state := r.FormValue("state"); state != u.Sign("Google") {
return fmt.Errorf("invalid state parameter: %q", state)
}
}, nil
}
+func (c *Client) AuthURL(ctx context.Context) string {
+ return oauthConfig().AuthCodeURL(c.appUser.Sign("Google"), oauth2.AccessTypeOffline)
+}
+
func (c *Client) DeleteToken(ctx context.Context) error {
return c.appUser.DeleteToken(ctx, "Google")
}
return nil
}
-func fitbitConnectHandler(_ context.Context, w http.ResponseWriter, r *http.Request, _ *app.User) error {
- http.Redirect(w, r, fitbit.AuthURL(), http.StatusTemporaryRedirect)
+func fitbitConnectHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, u *app.User) error {
+ c, err := fitbit.NewClient(ctx, "", u)
+ if err != nil {
+ return err
+ }
+
+ http.Redirect(w, r, c.AuthURL(ctx), http.StatusTemporaryRedirect)
return nil
}
return nil
}
-func googleConnectHandler(_ context.Context, w http.ResponseWriter, r *http.Request, _ *app.User) error {
- http.Redirect(w, r, gfit.AuthURL(), http.StatusTemporaryRedirect)
+func googleConnectHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, u *app.User) error {
+ c, err := gfit.NewClient(ctx, u)
+ if err != nil {
+ return err
+ }
+
+ http.Redirect(w, r, c.AuthURL(ctx), http.StatusTemporaryRedirect)
return nil
}