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: 

Dropbox authentication on iPhone X

Dropbox authentication on iPhone X

Steve L.32
Explorer | Level 4
Go to solution

My App's Dropbox authentication is failing on iPhone X and iOS 11. I still do not know the root cause and am just doing an initial inquiry here to learn if there is a known issue.  What I can say is this:

 

1) authentication fails if the Dropbox App is installed

 

2) authentication succeeeds if I remove the App and authentication goes through mobile Safari

 

Does that ring any bells?

 

Thankss,

Steve

1 Accepted Solution

Accepted Solutions

Greg-DB
Dropbox Staff
Go to solution
Thanks for digging in and tracking this down already! I'm glad to hear you figured this out. Calling authorizeFromController twice would indeed cause this. Enforcing a single call is the right thing to do given the unexpected viewDidAppear behavior.

View solution in original post

7 Replies 7

Steve L.32
Explorer | Level 4
Go to solution

And the log error is:

 

Auth Error: Error:[ErrorType: 6 ErrorDescription: Unable to verify link request

 

Greg-DB
Dropbox Staff
Go to solution

I'm not aware of any other reports like this, so we'll have to investigate. First, can you share:

  • the version number of the Dropbox SDK you're using
  • the version number of the official Dropbox for iOS app you have installed
  • your code snippets for initiating and receiving the app authorization flow
  • if this is only happening on iPhone X

 

The "Unable to verify link request" error comes from here:

 

https://github.com/dropbox/dropbox-sdk-obj-c/blob/6f40607f7d558a04f1330b84d8c8a0c960412409/Source/Ob...

 

This error should indicate that the state value returned on the SDK auth URL doesn't match the one previously generated and stored in NSUserDefaults for this app authorization flow. 

 

To help debug that, you can try running this code inside application:openURL, just before you call handleRedirectURL:

    NSLog(@"handling URL: %@", url);
    static NSString *kDBLinkNonce = @"dropbox.sync.nonce";
    NSString *nonce = (NSString *)[[NSUserDefaults standardUserDefaults] objectForKey:kDBLinkNonce];
    NSLog(@"stored nonce: %@", nonce);

(Just be sure to redact the access token itself, if any, in the output before sharing.)

 

 

Thanks!

Steve L.32
Explorer | Level 4
Go to solution

@Greg-DB wrote:

I'm not aware of any other reports like this, so we'll have to investigate. First, can you share:

  • the version number of the Dropbox SDK you're using

Not sure exactly how to determine that (guessing 3.1.0), I found a plist file in the source, here it is:

 

Screen Shot 2017-11-11 at 10.49.07 AM.png

  • the version number of the official Dropbox for iOS app you have installed

This is a universal App, the Dropbox App version is the same for both iPad Air 2 and iPhone X:  70.2.2

 

  • your code snippets for initiating and receiving the app authorization flow

 

- (BOOL) handleOpenURL:(NSURL *)url {
    
    // From a generic App sending us a document = file://localhost/private/var/mobile/Applications/***/Documents/Inbox/CoronaEarlyAccess-3.pdf
    // From Dropbox, in particular, for authentication = db-***://1/cancel?(null)
    //                                                 = db-***://1/connect?uid=***&oauth_token_secret=***&oauth_token=***
    
#ifdef kDEBUG
    NSLog(@"################ handleOpenURL=%@, absoluteString=%@", url, [url absoluteString]);
#endif
    
    NSString *dropboxKeyURLLeadin = [NSString stringWithFormat:@"db-%@", kDropboxKey];
    if ( [[url absoluteString] hasPrefix:dropboxKeyURLLeadin] ) {

        NSLog(@"handling URL: %@", url);
        static NSString *kDBLinkNonce = @"dropbox.sync.nonce";
        NSString *nonce = [[NSUserDefaults standardUserDefaults] objectForKey:kDBLinkNonce];
        NSLog(@"stored nonce: %@", nonce);
                           
        DBOAuthResult *authResult = [DBClientsManager handleRedirectURL:url];
        if (authResult != nil) {
            if ([authResult isSuccess]) {
                NSLog(@"Success! User is logged into Dropbox.");
                self.canUseDropbox = YES;
                [self performSelector:@selector(refreshDropbox) withObject:nil afterDelay:1.0];
                return YES;
            } else if ([authResult isCancel]) {
                NSLog(@"Authorization flow was manually canceled by user!");
                self.canUseDropbox = NO;
                [[NSNotificationCenter defaultCenter] postNotificationName:kKryptonTurnDropboxOffNotification object:nil];
            } else if ([authResult isError]) {
                NSLog(@"Auth Error: %@", authResult);
                self.canUseDropbox = NO;
                [self synchUserDefaults];
                [[NSNotificationCenter defaultCenter] postNotificationName:kKryptonTurnDropboxOffNotification object:nil];
                [[NSNotificationCenter defaultCenter] postNotificationName:kKryptonUnlinkDropboxNotification object:nil];
            }
        }
        return NO;
        
    } else {
        
        if ( self.openInURLs == nil ) {
            self.openInURLs = [[NSMutableArray alloc] initWithCapacity:10];
        }
        [self.openInURLs addObject:url];
        [self performSelector:@selector(handleOpenURL2) withObject:nil afterDelay:1.0];
        return YES;
        
    }
	
} // end handleOpenURL

 

  • if this is only happening on iPhone X

This is difficult to answer.  In the simulator there is no Dropbox App and authentication works on all devices.  For real devices I have an iPad Air 2 and authentication via web and App works fine.  My iPhone 7 is now gone and all I have is iPhoneX.  Web authentication works for it but not via the Dropbox App. Authentication via the app used to work on the iPhone 7 though.

 

The "Unable to verify link request" error comes from here:

 

https://github.com/dropbox/dropbox-sdk-obj-c/blob/6f40607f7d558a04f1330b84d8c8a0c960412409/Source/Ob...

 

This error should indicate that the state value returned on the SDK auth URL doesn't match the one previously generated and stored in NSUserDefaults for this app authorization flow. 

 

To help debug that, you can try running this code inside application:openURL, just before you call handleRedirectURL:

    NSLog(@"handling URL: %@", url);
    static NSString *kDBLinkNonce = @"dropbox.sync.nonce";
    NSString *nonce = (NSString *)[[NSUserDefaults standardUserDefaults] objectForKey:kDBLinkNonce];
    NSLog(@"stored nonce: %@", nonce);

(Just be sure to redact the access token itself, if any, in the output before sharing.)

 

Ok, here are the log entries and including mine to help trace the authentication flow.  First the iPad Air 2, which works, then iPhone X, which does not.  What stands out to me is that for iPhone X several Dropbox operation appear twice.

 

Also note that you can ignore the log entries concerning biometrics, at least I think you can.  The authentication issue exists with and without Face ID enabled.

 

iPad:


2017-11-11 10:06:22.542097-0500 Krypton[531:143990] DBSDKReachability Flag Status: -R ------- networkStatusForFlags
2017-11-11 10:06:23.712286-0500 Krypton[531:143990] didEnterBackground
2017-11-11 10:06:25.991012-0500 Krypton[531:143990] +[CATransaction synchronize] called within transaction
2017-11-11 10:06:25.991841-0500 Krypton[531:143990] +[CATransaction synchronize] called within transaction
2017-11-11 10:06:25.992537-0500 Krypton[531:143990] +[CATransaction synchronize] called within transaction
2017-11-11 10:06:25.993148-0500 Krypton[531:143990] willEnterForeground
2017-11-11 10:06:26.009576-0500 Krypton[531:143990] DO BIOMETRICS IFF closed voew controller showing=<VaultClosedPadViewController: 0x13fd0b000>
2017-11-11 10:06:26.009722-0500 Krypton[531:143990]   OK DO BIOMETRICS
2017-11-11 10:06:26.033245-0500 Krypton[531:143990] handling URL: db-***://1/connect?oauth_token_secret=***&uid=***&oauth_token=oauth2%3A
2017-11-11 10:06:26.033338-0500 Krypton[531:143990] stored nonce: 56566428-71E4-4DA3-8629-A285598D9E50
2017-11-11 10:06:26.119131-0500 Krypton[531:143990] Success! User is logged into Dropbox.
2017-11-11 10:06:27.106473-0500 Krypton[531:143990] in doBiometrics touchIDInProgress=0
2017-11-11 10:06:27.116687-0500 Krypton[531:143990] evaluatePolicy now ...
2017-11-11 10:06:27.124749-0500 Krypton[531:144030] Biometrics failed, code=-1004, err=Error Domain=com.apple.LocalAuthentication Code=-1004 "User interaction is required." UserInfo={NSLocalizedDescription=User interaction is required.}

 OK, now for iPhone X:

 

iPhone:


2017-11-11 10:08:32.282149-0500 Krypton[3157:759519] DBSDKReachability Flag Status: -R ------- networkStatusForFlags
2017-11-11 10:08:33.093590-0500 Krypton[3157:759519] didEnterBackground
2017-11-11 10:08:33.118068-0500 Krypton[3157:759519] DBSDKReachability Flag Status: -R ------- networkStatusForFlags
2017-11-11 10:08:37.385070-0500 Krypton[3157:759519] willEnterForeground
2017-11-11 10:08:37.445841-0500 Krypton[3157:759519] DO BIOMETRICS IFF closed voew controller showing=<VaultClosedViewController: 0x101f2a9e0>
2017-11-11 10:08:37.445961-0500 Krypton[3157:759519]   OK DO BIOMETRICS
2017-11-11 10:08:37.459372-0500 Krypton[3157:759519] handling URL: db-***://1/connect?oauth_token_secret=***&uid=***&oauth_token=oauth2%3A
2017-11-11 10:08:37.459425-0500 Krypton[3157:759519] stored nonce: 8156E9C8-7C1C-4EA7-9CA7-B6E8D53E113F
2017-11-11 10:08:37.460354-0500 Krypton[3157:759519] Auth Error: Error:[ErrorType: 6 ErrorDescription: Unable to verify link request.]
2017-11-11 10:08:37.461598-0500 Krypton[3157:759519] handling URL: db-***://1/connect?oauth_token_secret=***&uid=***&oauth_token=oauth2%3A
2017-11-11 10:08:37.462183-0500 Krypton[3157:759519] stored nonce: 8156E9C8-7C1C-4EA7-9CA7-B6E8D53E113F
2017-11-11 10:08:37.462264-0500 Krypton[3157:759519] Auth Error: Error:[ErrorType: 6 ErrorDescription: Unable to verify link request.]
2017-11-11 10:08:38.543166-0500 Krypton[3157:759519] in doBiometrics touchIDInProgress=0
2017-11-11 10:08:38.558830-0500 Krypton[3157:759519] evaluatePolicy now ...
2017-11-11 10:08:38.566033-0500 Krypton[3157:759957] Biometrics failed, code=-1004, err=Error Domain=com.apple.LocalAuthentication Code=-1004 "User interaction is required." UserInfo={NSLocalizedDescription=User interaction is required.}

 

Thanks!


Thank you.

Steve L.32
Explorer | Level 4
Go to solution

In the DB code you pointed to there is an if() in function 

 

            if (state.count == 2 && [state[0] isEqualToString:@"oauth2"] && [state[1] isEqualToString:nonce]) {

state.count is == 2, state[0] is == "oauth2", but state[1] is != nonce. Do not know what it means at this point, but that is the failure.

 

 

Steve L.32
Explorer | Level 4
Go to solution

Wasn't finished with last post, continuing:

 

I assume the real problem is that extractfromDAuthURL:url is called twice and thus the stored nonce doesn't match the current nonce. Also, I munged the redaction in the log entries previously, so here they are again.

 

 

2017-11-11 17:32:29.380496-0500 Krypton[3454:894607] DBSDKReachability Flag Status: -R ------- networkStatusForFlags
2017-11-11 17:32:30.189937-0500 Krypton[3454:894607] didEnterBackground
2017-11-11 17:32:30.205156-0500 Krypton[3454:894607] DBSDKReachability Flag Status: -R ------- networkStatusForFlags
2017-11-11 17:32:30.532935-0500 Krypton[3454:894607] [Snapshotting] Snapshotting a view (0x104005c00, UIKeyboardImpl) that is not in a visible window requires afterScreenUpdates:YES.
2017-11-11 17:32:31.573593-0500 Krypton[3454:894607] willEnterForeground
2017-11-11 17:32:31.590287-0500 Krypton[3454:894607] in viewwillappear call randomizecombination
2017-11-11 17:32:31.646979-0500 Krypton[3454:894607] handling URL: db-***://1/connect?oauth_token_secret=***&state=oauth2%3A9C3186A0-0DAF-48F3-8D70-F98E86DBE839&uid=***&oauth_token=oauth2%3A
2017-11-11 17:32:31.647129-0500 Krypton[3454:894607] stored nonce: 9B60EAE8-003D-40D6-AEF7-4BC8620372C8
2017-11-11 17:32:31.647267-0500 Krypton[3454:894607] Auth Error: Error:[ErrorType: 6 ErrorDescription: Unable to verify link request.]
2017-11-11 17:32:31.648096-0500 Krypton[3454:894607] handling URL: db-***://1/connect?oauth_token_secret=***&state=oauth2%3A9C3186A0-0DAF-48F3-8D70-F98E86DBE839&uid=***&oauth_token=oauth2%3A
2017-11-11 17:32:31.648217-0500 Krypton[3454:894607] stored nonce: 9B60EAE8-003D-40D6-AEF7-4BC8620372C8
2017-11-11 17:32:31.648301-0500 Krypton[3454:894607] Auth Error: Error:[ErrorType: 6 ErrorDescription: Unable to verify link request.]

Thus we see that the stored nonce is not the same as what's presented in the URL.  This is on iPhone X only, on iPad Air 2 those data match and authentication succeeds.  I will continue to see if I've broken my own code with iPhone X mods, but it's not obvious that they could have any impact ... famous last words, eh?!

 

Again, I see the log message DBSDKReachability twice for iPhone X but once for iPad.  I also see the call to extractfromDAuthURL:url twice for iPhone X but only once for iPad.

 

And NOW I figured it out: for iPhone X I am calling authorizeFromController:controller:openURL  twice! When I artificially limit the call to just once authentication works. The call in inside viewDidAppear:animated. For iPad the view must not disappear when the Dropbox App is run, but for iPhone X there is a second call to viewDidAppear:animated which I do not understand.

 

Now off to grok some more on what to do ....

 

Thanks!

 

Greg-DB
Dropbox Staff
Go to solution
Thanks for digging in and tracking this down already! I'm glad to hear you figured this out. Calling authorizeFromController twice would indeed cause this. Enforcing a single call is the right thing to do given the unexpected viewDidAppear behavior.

Steve L.32
Explorer | Level 4
Go to solution

I've restructured the Dropbox authentication flow slightly in light of the iPhone / iPad differences I found. I’ve used Dropbox in this App since 2011, so I’m surprised I didn’t see this issue earlier, although I must note that the viewDidAppear:animated code was added 2017.05.22 - this was my great API 1 --> API 2 commit!  This Dropbox App vs. Dropbox web authentication issue might have really existed for the last 6 months and I never noticed it.  I’ll have a definitive answer whenever I can borrow a non-iPhone X and see if viewDidAppear:animated is invoked once or twice.

 

Thanks again for your help.

Need more support?
Who's talking

Top contributors to this post

  • User avatar
    Steve L.32 Explorer | Level 4
  • User avatar
    Greg-DB Dropbox Staff
What do Dropbox user levels mean?