From 6e353fc58f08533be15182536e7b0c5099c098b8 Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Thu, 11 Jan 2018 08:39:16 +0100 Subject: [PATCH] Package fitbit: Update RefreshToken in Datastore after refreshing OAuth token. --- fitbit/fitbit.go | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/fitbit/fitbit.go b/fitbit/fitbit.go index 6f15027..bdfc3dd 100644 --- a/fitbit/fitbit.go +++ b/fitbit/fitbit.go @@ -123,19 +123,40 @@ type Client struct { } func NewClient(ctx context.Context, fitbitUserID string, u *app.User) (*Client, error) { - tok, err := u.Token(ctx, "Fitbit") + if fitbitUserID == "" { + fitbitUserID = "-" + } + + storedToken, err := u.Token(ctx, "Fitbit") if err != nil { return nil, err } - if fitbitUserID == "" { - fitbitUserID = "-" + // The oauth2 package will refresh the token when it is valid for less + // than 10 seconds. To avoid a race with later calls (which would + // refresh the token but the new RefreshToken wouldn't make it back + // into datastore), we refresh earlier than that. The Fitbit tokens are + // quite long-lived (six hours?); the additional load this puts on the + // backends is negligible. + if storedToken.Expiry.Round(0).Add(-5 * time.Minute).Before(time.Now()) { + storedToken.Expiry = time.Now() + } + + refreshedToken, err := oauth2Config.TokenSource(ctx, storedToken).Token() + if err != nil { + return nil, err + } + + if refreshedToken.RefreshToken != storedToken.RefreshToken { + if err := u.SetToken(ctx, "Fitbit", refreshedToken); err != nil { + return nil, err + } } return &Client{ fitbitUserID: fitbitUserID, appUser: u, - client: oauth2Config.Client(ctx, tok), + client: oauth2Config.Client(ctx, refreshedToken), }, nil } -- 2.11.0