cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Announcements
Want to learn some quick and useful tips to make your day easier? Check out how Calvin uses Replay to get feedback from other teams at Dropbox 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: 

Re: Implementing refresh tokens for objective-c applications

Implementing refresh tokens for objective-c applications

egurik
Explorer | Level 4
Go to solution

Hello there.

 

So, according to Your reminder: "on September 30th, 2021, the Dropbox OAuth flow will no longer return new long-lived access tokens. It will instead return short-lived access tokens, and optionally return refresh tokens." I have been started to update my existing iOS objective-c application.

 

The first step is to change [DBClientsManager authorizeFromController...] to [DBClientsManager authorizeFromControllerV2].

 

Here is an example of this:

DBScopeRequest *scopeRequest =

        [[DBScopeRequest alloc] initWithScopeType:DBScopeTypeUser

                                           scopes:@[]

                             includeGrantedScopes:NO];

    

    [DBClientsManager authorizeFromControllerV2:[UIApplication sharedApplication]

                                     controller:self

                          loadingStatusDelegate:nil

                                        openURL:^(NSURL *url) {

        NSLog(@"[openURL: %@]", url);

        [[UIApplication sharedApplication] openExternalURL:url];

    }

                                   scopeRequest:scopeRequest];

 

Then I catch the auth-response:

 

[DBClientsManager handleRedirectURL:url

                             completion:^(DBOAuthResult * __nullable authResult) {

        

        NSLog(@"[authResult: %@]", authResult);

    }];

 

The authResult contains not nil 'refreshToken' and 'tokenExpirationTimestamp' what is a good sign. However, the 'tokenExpirationTimestamp' has a giant value (as I understand expressed via seconds). It's not clear how I should calculate the expiration date. It might be this huge value was started from some date in the past (1970)? Ok, let's suppose I should not calculate the expiration date of new short-lived access tokens. I have a single place for all my requests to/from Dropbox. I decided that in this place I will check the requestError (networkError) and perform refreshing if the Dropbox returns Auth-error. Is it correct? And the second question: how can I check this code? When refresh tokens should expire on average? I was waiting for ~1-2 hours BUT the Dropbox did not return Auth errors.

 

- (BOOL)doInternalWorkSynchronously {

    

    BOOL done = NO;

    

    do

    {

        done = [self doInternalTaskSynchronously];

        

        NSLog(@"[requestError: %@]", _requestError);

        

        if ([_requestError isRateLimitError]) {

            

            [self waitBeforeMakingAnyAdditionalRequests];

        }

        else if ([_requestError isAuthError]) {

            

            DBRequestAuthError *authError = [_requestError asAuthError];

            

            NSLog(@"[authError: %@]", authError);

            

            [self refreshAccessToken];

        }

        else {

            

            // Skip processing of other types the request error.

            break;

        }

        

    } while (!_isCancelled);

    

    return done;

}

 

- (void)refreshAccessToken {

    

    dispatch_semaphore_t refreshTokenSemaphore = dispatch_semaphore_create(0);

    

    DBOAuthManager *dbOAuthManager = [DBOAuthManager sharedOAuthManager];

    

    DBAccessToken *accessToken = [dbOAuthManager retrieveFirstAccessToken];

    

    [dbOAuthManager refreshAccessToken:accessToken

                                scopes:@[]

                                queue:nil

                            completion:^(DBOAuthResult * __nullable authResult) {

        

        dispatch_semaphore_signal(refreshTokenSemaphore);

    

        KPLog(@"[authResult: %@]", authResult);

    }];

    

    dispatch_semaphore_wait(refreshTokenSemaphore, DISPATCH_TIME_FOREVER);

}

 

 

 

 

 

 

1 Accepted Solution

Accepted Solutions

kylea
Dropbox Staff
Go to solution

The tokenExpirationTimestamp is a unix timestamp.  Parsing it should show ~4 hours until expiration, but expiration time is subject to change and should not be hardcoded. 

 

The SDK should be handling requesting an updated access token from a refresh token for you.

 

Refresh tokens don't expire; though end users can revoke the authentication.

View solution in original post

4 Replies 4

kylea
Dropbox Staff
Go to solution

The tokenExpirationTimestamp is a unix timestamp.  Parsing it should show ~4 hours until expiration, but expiration time is subject to change and should not be hardcoded. 

 

The SDK should be handling requesting an updated access token from a refresh token for you.

 

Refresh tokens don't expire; though end users can revoke the authentication.

egurik
Explorer | Level 4
Go to solution

Thanks for the reply!

 

The tokenExpirationTimestamp is a unix timestamp.  Parsing it should show ~4 hours until expiration, but expiration time is subject to change and should not be hardcoded. 

Thanks. Good to know. Although it wouldn't be bad if this fact was reflected in the documentation (with measure units + examples).

 

Refresh tokens don't expire; though end users can revoke the authentication.

Yes, sorry. I meant a short-lived access token.

 

The SDK should be handling requesting an updated access token from a refresh token for you.

It's of course very cool. Thanks. Just to confirm that we are on the same page: I should not call DBOAuthManager.

refreshAccessToken explicitly? If a user does not sign out by himself then the SDK will not return the error 401?

 

 

Greg-DB
Dropbox Staff
Go to solution

That's correct, you don't need to call refreshAccessToken yourself. As long as you set things up as instructed, the SDK will handle all of that for you.

 

And yes, as long as nothing specifically happens to invalidate the refresh token (such as the user unlinking the app, deleting their account, etc.) the refresh token will continue to be usable.

egurik
Explorer | Level 4
Go to solution

Thanks a lot!

Need more support?