You might see that the Dropbox Community team have been busy working on some major updates to the Community itself! So, here is some info on what’s changed, what’s staying the same and what you can expect from the Dropbox Community overall.
Forum Discussion
Robert S.138
9 years agoHelpful | Level 7
iOS Exception: "Dropbox client already authorized"
While developing my code for using the new Objective-C SDK, I am running on the Xcode emulator. The first time I tried OAuth, it worked and brought up the Dropbox login web page. NSLog verified that the OAuth result was success. The second time I ran it there was an exception thrown saying "A Dropbox client is already authorized". How can I properly ensure there is no authorized client before I start to create a new one, or otherwise avoid this exception? The call stack is:
2016-09-12 14:39:54.755 TuneLab[1303:57987] *** Assertion failure in +[DropboxClientsManager authorizeFromController:controller:openURL:browserAuth:], /Users/robertscott/Documents/iOS Proj/TuneLab/Pods/ObjectiveDropboxOfficial/Source/ObjectiveDropboxOfficial/PlatformDependent/iOS/DropboxClientsManager+MobileAuth.m:32
2016-09-12 14:39:54.760 TuneLab[1303:57987] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'A Dropbox client is already authorized'
*** First throw call stack:
(
0 CoreFoundation 0x04017494 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x03ad1e02 objc_exception_throw + 50
2 CoreFoundation 0x0401732a +[NSException raise:format:arguments:] + 138
3 Foundation 0x00599322 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 118
4 TuneLab 0x001bb1d1 +[DropboxClientsManager(MobileAuth) authorizeFromController:controller:openURL:browserAuth:] + 881
5 TuneLab 0x0003ef99 -[DBxfer buttonPressed:] + 290
6 libobjc.A.dylib 0x03ae60b5 -[NSObject performSelector:withObject:withObject:] + 84
7 UIKit 0x00944e38 -[UIApplication sendAction:to:from:forEvent:] + 118
8 UIKit 0x00944db7 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 64
9 UIKit 0x00ae8f3b -[UIControl sendAction:to:forEvent:] + 79
10 UIKit 0x00ae92d4 -[UIControl _sendActionsForEvents:withEvent:] + 433
11 UIKit 0x00ae82c1 -[UIControl touchesEnded:withEvent:] + 714
12 UIKit 0x009c552e -[UIWindow _sendTouchesForEvent:] + 1095
13 UIKit 0x009c65cc -[UIWindow sendEvent:] + 1159
14 UIKit 0x00967be8 -[UIApplication sendEvent:] + 266
15 UIKit 0x0093c769 _UIApplicationHandleEventQueue + 7795
16 CoreFoundation 0x03f29e5f __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
17 CoreFoundation 0x03f1faeb __CFRunLoopDoSources0 + 523
18 CoreFoundation 0x03f1ef08 __CFRunLoopRun + 1032
19 CoreFoundation 0x03f1e846 CFRunLoopRunSpecific + 470
20 CoreFoundation 0x03f1e65b CFRunLoopRunInMode + 123
21 GraphicsServices 0x05c15664 GSEventRunModal + 192
22 GraphicsServices 0x05c154a1 GSEventRun + 104
23 UIKit 0x00942eb9 UIApplicationMain + 160
24 TuneLab 0x000085c6 main + 230
25 libdyld.dylib 0x04bb2a25 start + 1
26 ??? 0x00000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
- Robert S.138Helpful | Level 7
In the emulator I selected a different device, which causes the iOS to reboot. Then the error went away. So perhaps the exception was a side-effect of stoping the app with Xcode and starting it up again. But that leads me to wonder if there aren't some scenarios in real devices where something like this happens and an inconsistency is generated. In that case I would like to know what addition steps I can take when starting an OAuth to ensure this exception will not occur. I cannot use the presence or absence of a stored Access Token, but my data state might be inconsistent with the Dropbox system and I might not have a stored Access Token even though the SDK thinks I should have one.
**** Edit: I tried rebooting the emulator and the exception in OAuth remains. There is something persistent in the iOS the remembers there was a successful authorization, but it has nothing to do with my app. I just saw [DropboxClientsManager unlinkClients]; in the example app. Will this do it, and is it safe and reasonable to call this every time, just before authorizeFromController, even if there is no existing authorized client?
- Greg-DBDropbox Staff
Hi Robert, that assertion is actually easy enough to hit if you call authorizeFromController more than once (if you do link an account the first time). The DropboxClientsManager class is meant as a convenience for the standard single account case, so you can use the following to check if you're already linked:
if ([DropboxClientsManager authorizedClient] != nil) {
// already linked, use authorizedClient to make API callsThat's the same thing the SDK checks for that assertion, and it's set by checking the SDK's own access token storage, so you shouldn't have to worry about inconsistency there. (If you're doing your own access token storage for some reason though, you should just construct DropboxClient objects directly.)
- Greg-DBDropbox Staff
Also, in response to your edit, you don't need to call unlinkClients each time, though that will clear out authorizedClient if that's what you want to do.
You can re-use the tokens the SDK stores for you without having the user go through the app authorization flow each time (authorizeFromController).
- Robert S.138Helpful | Level 7
I think the confusion comes from my trying to persist the Access Token myself instead of letting DBKeychain do it. In the Android version, I don't think there was any choice. If we wanted the Access Token to persist between sessions, we had to store it ourselves in the app Preferences. But for the iOS version, it appears the only reason to deal with an Access Token in my code is if the Access Token were manually generated externally. If I understand correctly, the SDK for iOS will automatically persist the Access Token upon a successful OAuth2. (I was actually getting the Access Token from the DBAuthResult.accessToken.accessToken. But apparently that is unnecessary?) Let me know if I should eliminate all explicit references to an Access Token in my application code, as long as I only intend to use Access Tokens that have been generated through the OAuth flow in that app itself.
- Greg-DBDropbox Staff
That's correct. The Android SDK doesn't do it for you, but the iOS SDK does automatically store access tokens in the keychain for you, so you don't have to.
- trinigatoNew member | Level 2
How to decline automatic store in keychain? I don't want to be authorized after app's reinstallation
- Greg-DBDropbox Staff
trinigato The Dropbox Objective-C SDK doesn't have an option to disable the automatic token storage, but I'll pass this along as a feature request. (You can explicitly call unlinkAndResetClients when desired though.)
About Dropbox API Support & Feedback
Find help with the Dropbox API from other developers.
5,915 PostsLatest Activity: 7 hours agoIf 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!