11-02-2020 14:33
11-02-2020 14:33
I want to integrate the Fitbit API to my app, which is being distributed on multiple App Stores (Apple (iOS + macOS), Google, Microsoft). Therefore it is very common that the same user uses my app on multiple devices (and wants to connect to his Fitbit account).
I registered one single Fitbit app in the Fitbit developer portal for this.
I now found the following problem: I can connect/authenticate to the same Fitbit account on multiple devices and I get a different access + refresh token every time. I can also refresh the token and is receive a new access + refresh token on one device. However, once I do that on one device, the other device can no longer refresh its token. It seems like refreshing the access token invalidates *all* access + refresh tokens, even though they belong to a totally different device.
Is this by design? I am using OAuth for a while now and never experienced a similar problems with other apps.
11-03-2020 09:23
11-03-2020 09:23
Hi @tipako ... Does your application use the same client ID across all platforms or a different client ID for each platform?
11-03-2020 09:31
11-03-2020 09:31
I registered one single Fitbit app in the Fitbit developer portal for this.
My app uses the same client ID on all platforms so the user only has to consent to give his permission to my app once. Another reason why I created only one Fitbit application is because a user could download my app to multiple devices of the same platform (e.g. to his iPhone + his iPad) and creating multiple client IDs for each platform wouldn't be a working workaround then.
11-03-2020 15:36
11-03-2020 15:36
The way our tokens work is you may have multiple access tokens but only a single refresh token per user per client ID. Therefore, if one application refreshes the tokens, only that application will have the most current refresh token and the other tokens will become invalid. Instead of managing the access token and refresh token in the different applications, try managing the tokens in a centralized server or database. When the tokens get updated, all devices will have access to the most current tokens. If this is not an option, you'll need to have separate client IDs for each device, and send the user through the consent flow as part of the application setup on each device.
11-03-2020 15:45 - edited 11-03-2020 15:48
11-03-2020 15:45 - edited 11-03-2020 15:48
This is very sad news. I do not have (and do not want to have) a server (or user account) involved in my application.
Only being able to have one valid refresh token is a big bummer and I wish to have known the before because now I consider removing the Fitbit integration from my app altogether. As I said in my previous comment, having separate client IDs for each platform is not solving the problem as a user can install the app on multiple of this Android or iOS devices (and many of my users are doing that).
I wish this detail would have been mentioned in the docs. Basically all OAuth systems I have used over the years (Google, Microsoft, Dropbox, Facebook, Instagram, Twitter, Strava, etc. etc.) work differently and allow multiple valid refresh tokens.
Are you considering to change that behavior in the future?
11-04-2020 10:02 - edited 11-04-2020 10:11
11-04-2020 10:02 - edited 11-04-2020 10:11
Thank you for the feedback. We will clarify this in the documentation. We believe we are following the intended interpretation of the OAuth 2.0 RFC 6749. The authorization code grant flow is intended to be used with an authorization server. According to section 6,
"The authorization server MAY issue a new refresh token, in which case the client MUST discard the old refresh token and replace it with the new refresh token. The authorization server MAY revoke the old refresh token after issuing a new refresh token to the client. If a new refresh token is issued, the refresh token scope MUST be identical to that of the refresh token included by the client in the request."
We choose to revoke all previously issued refresh tokens for that user on that client ID to maintain the strictest security possible of our customer's data.
At this time, we do not have plans to change this behavior. As the specification evolves, we will look at other authorization options to implement. If you choose not to use an authorization server, we do support the implicit grant flow. This authorization flow is intended for clients that don't have an authorization server. During authentication, your application is not issued a refresh token. Instead, you'll receive a longer lasting access token (up to 12 months). Consent will still be required on each client. When the access token expires, the users will need to re-authorize the client.
11-05-2020 04:25
11-05-2020 04:25
First, thanks for your quick responses Gordon - highly appreciated!
Thanks for the link to the OAuth specs. I am no native English speaker, but I would interpret the quoted part differently:
The authorization server MAY revoke the old refresh token after issuing a new refresh token to the client.
Wouldn't it say "revoke all old refresh token" if indeed all previously issued refresh tokens should be invalidated? I think the sentence it is specifically and only referring to the refresh token that is being used in this very refresh token call.
I can also not see a security benefit for the user, but I'm no security specialist. If you decided to only keep one valid access/refresh token pair per client ID, why aren't you revoking all previous access token once a new access token has been issued? As it is now, it seems to follow an inconsistent logic. I was also not able to find any resources in the internet that would suggest revoking all refresh token when refreshing the access token.
If the user wants to disconnect an app from accessing his Fitbit data, he can do so in his Fitbit account settings.
As I mentioned before, this OAuth behavior is very new to me and I haven't seen this in any other API using OAuth before (and I have been using a few...). From my experience, there are always multiple valid access/refresh token pairs possible.
Thanks for pointing out that the implicit grant flow can grant access tokens that are valid for up to 12 months, that also hasn't been clear by the Fitbit docs:
Users may specify the lifetime of the access token from the authorization page when an application uses the Implicit Grant Flow. The access token lifetime options are 1 day, 1 week, and 30 days.
I will see if this is an alternative for me, however I would highly appreciate if the refresh token logic could be changed.
PS: the formatting options for this forum are a pain. Sending a comment errors out all the time (Your post has been changed because invalid HTML was found in the message body. The invalid HTML has been removed. Please review the message and submit the message when you are satisfied.). Resubmitting the message then results in a message flood error. No idea what I am doing wrong...