4 Authenticate with Native Applications
Eric Marchand edited this page 2016-10-21 11:35:58 +02:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Some providers like Facebook and Dropbox support authentication by launching into their iOS app directly rather than using Safari or other web views.

Add specifics schemes

iOS 9 requires your app to pre-register application schemes it intends to call. For each provider, youll need to add specifics schemes to your list of allowed schemes

  • For Dropbox: dbapi-2, db-<APP_KEY>
  • For Facebook: fbauth2, fb<APP_KEY>

Open your YourApp-Info.plist file and add the key, LSApplicationQueriesSchemes.

Under LSApplicationQueriesSchemes, add a new item with the value dbapi-2(resp. fbauth2) It should look like this in the source code for your Info.plist file:

<key>LSApplicationQueriesSchemes</key>
<array>
  <string>dbapi-2</string>
</array>

This will allow to call the native app as part of the authentication flow.

Choose authorizeURLHandler

Use OAuthSwiftOpenURLExternally instance to open authorize url in the native app

oauthswift.authorizeURLHandler = OAuthSwiftOpenURLExternally.sharedInstance

Check native app installed

Then before authentificate you can test is the native app is installed by doing for instance for dropbox on iOS

var isDropboxAppInstalled: Bool = {
    let appUrl = URL(string: "dbapi-2://app")
    return UIApplication.shared.canOpenURL(appUrl!)
}()

Define an authorize Url

Then you can use an authorizeUrl like this :

  • for dropbox: "dbapi-2://1/connect?k=(dropboxAppId)&s=&state=oauth2:(nonce)" where nonce is random state string. Dropbox example uses UUID().uuidString.
  • for facebook "fbauth2://authorize?response_type=token&client_id=(facebookAppId)&redirect_uri=fb(facebookAppId)&scope=public_profile" with OAuth2Swift

Handle callback url

The native app will call back into your app using the fb<APP_KEY> or db<APP_KEY>- url scheme defined before and used as callbackURL with the appropriate token:

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
    if (url.host == "oauth-callback") || (url.scheme == "fb<APP_KEY>) { // probably check source too
        OAuthSwift.handle(url: url)
    }
    return true
}

⚠️ For dropbox the callback does not match what OAuthSwift/OAuth expectations though - it is almost more closely appears like an OAuth v1 response with oauth_token_secret being the important value: db-<APP_KEY>://1/connect?oauth_token_secret=<MY_SECRET>&state=oauth2%3A&uid=<DROPBOX_USER_ID>&oauth_token=oauth2%3A (Note that the %3A is just : url encoded.)

So you would need to either rewrite the url query before passing it into OAuthSwift.handle(url: url), ie. change oauth_token_secret by code

Special Thanks

@mikegray for #300 and words