We are aware of the issue with the badge emails resending to everyone, we apologise for the inconvenience - learn more here.

Forum Discussion

blobwriter's avatar
blobwriter
Explorer | Level 4
4 years ago

OAuth2 w/ refresh tokens for hybrid apps

I have a little Cordova (I know react-native is cool now, but I strongly prefer Vue) app for Android+browser that uses Dropbox for sync, and for both platforms does auth by getting an OAuth2 bearer token using the javascript SDK (calling getAuthenticationUrl() w/ the appropriate callback, and navigating to the result).

 

From what I gather, the new API changes towards short-lived tokens mean that a) no matter what, browser apps will have to do a manual relogin every 4 hrs (though it might just be an insta-redirect with no manual user re-entry of credentials).

DropBoxInc's intent is that mobile apps that want long-lived access also request a refresh token, with which you can request future short-lived tokens.

 

But will the Javascript SDK (which I imagine is what most hybrid apps use) support this? I tried manually appending  

token_access_type=offline to the authentication URL returned by getAuthenticationUrl, but at the page: 

 

https://www.dropbox.com/oauth2/authorize?response_type=token&token_access_type=offline&client_id=$myclientid&redirect_uri=$myworkingredirect

 

I get 'Offline access disallowed for OAuth2 token flow ("response_type" can't be "token").'

 

But this would seem to mean that any cordova/capacitor/phonegap/hybrid apps (that rely on the javascript sdk for low-friction access to the dropbox API) are doomed with asking users to re-auth every 4hrs?

  • No, such apps are not forced to have the user re-authorize every four hours. Client-side apps like this can request "offline" access to get refresh tokens if needed. There's an example of requesting offline access from a client-side app (a front-end browser app, in this sample) using the official Dropbox API v2 JavaScript SDK here.

     

    The issue with the authorization URL you constructed is that the PKCE flow (which is how client-side apps can get offline access) is a form of the "response_type=code" flow, not "response_type=token".

     

    I recommend letting the SDK build that URL for you, like in the example here. If you do want to build that directly though, you can find the full authorization documentation here.

  • Greg-DB's avatar
    Greg-DB
    Icon for Dropbox Staff rankDropbox Staff

    No, such apps are not forced to have the user re-authorize every four hours. Client-side apps like this can request "offline" access to get refresh tokens if needed. There's an example of requesting offline access from a client-side app (a front-end browser app, in this sample) using the official Dropbox API v2 JavaScript SDK here.

     

    The issue with the authorization URL you constructed is that the PKCE flow (which is how client-side apps can get offline access) is a form of the "response_type=code" flow, not "response_type=token".

     

    I recommend letting the SDK build that URL for you, like in the example here. If you do want to build that directly though, you can find the full authorization documentation here.

    • blobwriter's avatar
      blobwriter
      Explorer | Level 4

      Thanks for the response Greg, always impressed with your responsiveness here.

       

      So I got this working (the PKCE flow). However, having cached the access token in a local storage medium, requests to the Dropbox API  the next day  are rejected with a 401 error and "expired_access_token".

       

      Ok, so I just have to write a little handler to catch it and ask for a new access_token using the refresh token (also stored). Simple enough. But how do I test this code? Can I request very-short-life-tokens (around 60s) just to test this handler? I know you can manually revoke access_tokens using authTokenRevoke(), but doing that seems to also revoke the associated refresh_token, so doesn't allow for testing of the (expired_access_token+valid_refresh_token) code path.

       

      Edit: it seems that one should just pass the refresh token to the DropboxAuth object (which is, in turn, passed to the Dropbox object at instantiation), and DropboxAuth should(?) magically refresh access_tokens for me without having to write my own code. But just to clarify:

      1. the refresh_token is not itself single-use right? I don't have to somehow figure out when the DropboxAuth does a token refresh, in order to pull the (possibly new) refresh_token back out and overwrite the old refresh_token in storage?
      2. Instead, the actual case is that a new refresh_token is only received when you make the dbxAuth.getAccessTokenFromCode() call, using a valid pkce code?

       

       

       

      • Greg-DB's avatar
        Greg-DB
        Icon for Dropbox Staff rankDropbox Staff

        There isn't a way to force an access token to expire soon or immediately, but I'll pass this along as a feature request. I can't promise if or when that might be implemented though. So, to test the actual 'expired_access_token' error for any particular new short-lived access token, you would need to wait four hours. (You don't need to wait to test the refresh flow itself though; you can perform a refresh at any point.)

         

        And yes, that's correct, the SDK code will handle the refresh for you, and refresh tokens are not single-use and Dropbox does not return a new refresh token on every refresh, so you don't need to retrieve and store and new refresh token every time. You only get a refresh token once per authorization flow, from getAccessTokenFromCode.

About Discuss Dropbox Developer & API

Node avatar for Discuss Dropbox Developer & API

Make connections with other developers

795 PostsLatest Activity: 7 days ago
192 Following

If you need more help you can view your support options (expected response time for an email or ticket is 24 hours), or contact us on X or Facebook.

For more info on available support options for your Dropbox plan, see this article.

If you found the answer to your question in this Community thread, please 'like' the post to say thanks and to let us know it was useful!