cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Announcements
Share your feedback on the Document Scanning Experience in the Dropbox App right here.

Dropbox API Support & Feedback

Find help with the Dropbox API from other developers.

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Dropbox Java client for Android: how to refresh token?

Dropbox Java client for Android: how to refresh token?

baltasarq
Helpful | Level 5
Go to solution

My app just needs to upload a backup file to a dropbox account from mine, so the access must be off-line (no prompting to the user, that would be confusing). This is carried out when the user finishes inputting data. I previously used the API with the following code (Java SDK):

 

DbxRequestConfig config = DbxRequestConfig.newBuilder( getPackageName() ).build();
DbxClientV2 client = new DbxClientV2( config, getString( R.string.dropbox_token ) );

client.files()
.uploadBuilder( toPath )
.withMode( WriteMode.OVERWRITE )
.uploadAndFinish( in );

 

But now this does not work anymore, or better speaking, it works but the token expires, so it only works once. I've looked the docs for the Java SDK, but there doesn't seem to be a simple example for offline access.

What I tried so far:
- I obtained an access token, that allows the initial authentication.
- I substituted the generated short-lived token with an access token. But this does not work by itself.
- There is a promising method in the client that refreshes a token, so I tried calling it and creating a new client, before uploading the file:

 

try {
    DbxRefreshResult result = client.refreshAccessToken();
    DbxCredential credentials = new DbxCredential(
        getString( R.string.dropbox_token ),
        Long.MAX_VALUE,
        result.getAccessToken(),
        getString( R.string.dropbox_key ),
        getString( R.string.dropbox_secret ) );

client = new DbxClientV2( config, credentials );
} catch (DbxException e) {
    System.err.println( "Error refreshing token: " + e.getMessage());
}

 

The refreshing apparently works (no errors, at least), but then the upload fails with a new error: invalid_access_token.

So, should I create a new client with the refresh token or not? Am I refreshing the token correctly?

 

19 Replies 19

baltasarq
Helpful | Level 5
Go to solution

> @baltasarq Thanks for the feedback!

I found the code in the internal/ folder.

 

> The startOAuth2PKCE method is defined here. If you're not seeing that method in your installation, please make sure you're using a recent version of the SDK. The latest version is currently v5.4.5.

Yep. But, I guess that this initial authorize is only needed once, right? Then I should be able to access with a single token...

 

Thanks,

-- Baltasar

 

Здравко
Legendary | Level 20
Go to solution

@baltasarq wrote:

...

    DbxCredential credentials = new DbxCredential(
        getString( R.string.dropbox_token ),
        Long.MAX_VALUE,
        result.getAccessToken(),
        getString( R.string.dropbox_key ),
        getString( R.string.dropbox_secret ) );

client = new DbxClientV2( config, credentials );

...


@baltasarq, You can correct the above code in following way:

    DbxCredential credentials = new DbxCredential(
        "", // Empty values here to force the initial refresh.
        0, //
        refreshToken,
        appKey,
        appSecret );

client = new DbxClientV2( config, credentials );

Assign to refreshToken, appKey, and appSecret to the values according to the guide here. So you wouldn't need to do anything OAuth related inside your application.

Hope this gives answer to your "main" question. :winking_face:

Good luck.

baltasarq
Helpful | Level 5
Go to solution

> You can correct the above code in following way:

Done, thank you.

> Assign to refreshToken, appKey, and appSecret to the values according to the guide here. So you wouldn't need to do anything OAuth related inside your application. Hope this gives answer to your "main" question. :winking_face:


It works!! But I have a side problem, for some reason, (probably because I entered the curl commands you linked in my computer's console), now my personal Dropbox is connected to the app, while I wanted another specific Dropbox to be linked... I'll probably have to unlink and start the process again, I guess converting all the curl commands to URL's.

 

Also, I want to check tomorrow whether it still works or something is still expiring, which would mean that I'd anyway have to refresh inside my code. Let's see.

 

Many thanks,

-- Baltasar

 

Greg-DB
Dropbox Staff
Go to solution

@baltasarq The account that gets connected is determined by which account you're signed in to in your browser when you authorize the app. If you want to use a different account, you'll need to switch to that account in your browser and process the authorization flow again.

baltasarq
Helpful | Level 5
Go to solution

> @baltasarq The account that gets connected is determined by which account you're signed in to in your browser when you authorize the app. If you want to use a different account, you'll need to switch to that account in your browser and process the authorization flow again.

 

Got it! Thanks, @Greg-DB and specially @Здравко.

 

-- Baltasar

 

baltasarq
Helpful | Level 5
Go to solution

Okay, solved.

I summarized the process in the following notes:

 

Dropbox client API

 

1Cloud backup with the Dropbox API

Until september 2022, it was possible to generate an access token, use it when creating the client, and don’t worry again about authorization. This is not possible anymore, so in order to create a backup system the most similar access system is PKCE for an offline app.

2Refresh token

After creating the app in the App Console, ignore the “generate token” option since this only creates a token valid for about 4 hours (though there is no note about this). Keep the PKCE activated.

 

Now, paste the following line in the address bar of your browser:

 

https://www.dropbox.com/oauth2/authorize?token_access_type=offline&response_type=code&client_id=<App key>

 

You need to substitute <App Key> for the application key that appears in the App Console. Keep the App Secret code near, as well.

 

You will authorize the app only once through that URL, and the answer will be the so called authorization code, an hexadecimal code. You need to take note of this code.

 

3Obtaining the refresh token

Now you have to open a terminal and paste there:

 

curl https://api.dropbox.com/oauth2/token -d code=<Authorization Code> -d grant_type=authorization_code -u <App key>:<App secret>

 

You have to substitute <Authorization Code> with the last obtained token, <App Key> with the App Key and <App Secret> with the App Secret, these latter appearing in the App Console.

 

The answer will be a JSON piece of data similar to the following one:

 

{
    "access_token":"sl...",
    "token_type": "bearer",
    "expires_in": 14400,
    "refresh_token": "oDfT54975DfGh12345KlMnOpQrSt01a",
    "scope": "account_info.read files.content.read ...",
    "uid": "123...",
    "account_id": "dbid:AB..."
}

 

The access token would be valid for the app to access Dropbox for 4 hours (expires_in). Note the “sl.” prefix (Short Lived). The important code here is refresh_token, which is a permanent token that you can access Dropbox with.

 

4Using the Java API

The problem with the API is that it is not always intuitive to use. With the PKCE access system, we only need to change the Dropbox client object in respect to what appears in the documentation.

 

        final String APP_PACKAGE = OWNER.getPackageName();
        final DbxRequestConfig CONFIG = DbxRequestConfig.newBuilder( APP_PACKAGE ).build();
        final DbxCredential CREDENTIALS = new DbxCredential(
                "",
                0L,
                <dropbox refresh token>,
                <app key>,
                <app secret> );

        this.DBOX_CLIENT = new DbxClientV2( this.CONFIG, CREDENTIALS );

 

The remaining code is left untouched.

 

Здравко
Legendary | Level 20
Go to solution

@baltasarq, Just a note: In your web browser you're receiving authorization code, not access token! They are different things. :winking_face:

baltasarq
Helpful | Level 5
Go to solution

Thanks, corrected.

-- Baltasar

 

Dave__K
New member | Level 2

I realize this post is a little old.  My problem was I needed to actually get a refreshed access token because I am doing this in multi-platform Kotlin, and have to keep the backup part more generic than using the android JDK’s (7.0), that will not work on the IOS side.  I spent a week or two trying to get it to actually get a new access token, and couldn't find the last step to make it work.  I thought I would share in case others might need it.  I added this method to DropboxOAuthUtil

 from the example (https://github.com/dropbox/dropbox-sdk-java/blob/main/examples/android/src/main/java/com/dropbox/cor...)

 

I call this refresh before performing the backup and restore in case the token expired.

// Dave Adding this
fun refreshToken(appKey: String, refreshToken: String, appSecret: String): String {
val requestConfig = DbxRequestConfig(dropboxAppConfig.clientIdentifier)
val dbCredential = DbxCredential("", 0L, refreshToken, appKey, appSecret )
dbCredential.refresh(requestConfig)
logMessage.logDebug(TAG, "refreshToken NEW?? dbCredential.accessToken=${dbCredential.accessToken}")

return dbCredential.accessToken
}

Здравко
Legendary | Level 20

@Dave__K, reimplement the class here is you want to.

Need more support?
Who's talking

Top contributors to this post

  • User avatar
    Здравко Legendary | Level 20
  • User avatar
    Dave__K New member | Level 2
  • User avatar
    baltasarq Helpful | Level 5
What do Dropbox user levels mean?