Tag Archives: Instagram

SFSafariViewController and OAuth – the Instagram example

I think, as a developer, I’ve never been so excited and frustrated at the same time by the same thing. Sorry for the non-tech reading that, you can stop here, it’s fine ;) My oh-so-frustrating thing is the brand new SFSafariViewController introduced in WWDC 2015, and especially its interaction with OAuth.

If you are reading this article, you have probably watched WWDC’s session 504: Introduction to Safari View Controller. And you’ve probably browsed through a lot of articles arguing the pros and cons of SFSafariViewController.

Here, I would like to jump straight to the “Web-based authentication” section, when Ricky Mondello showed us the slide below, while saying:

“Because since Safari View Controller has access to a user’s credentials, synced across all of their devices with iCloud Keychain, logging in is going to be a breeze.[…]

It takes two steps.
The first is where you would’ve used your own in-app browser, just present an instance of SFSafariViewController.

And once the user is finished logging in and the third-party web service redirects back to your app with the custom URL scheme that you fed it, you can accept that in your AppDelegate‘s handleOpenURL method.

From there you can inspect the response and dismiss the instance of SFSafariViewController because you know that the authentication is done.

That’s it.
Two steps.”

Source: http://asciiwwdc.com/2015/sessions/504#t=1558.026

WWDC2015 504 SFSafariViewController
WWDC 2015 – Session 504 – SFSafariViewController

Intriguing. Two steps? That sounds nearly too easy. I wanted to see some implementations of it. While searching the web, I found that very interesting article from Rizwan Sattar: How iOS 9’s Safari View Controller could completely change your app’s onboarding experience. All of you who have submitted apps to the AppStore know that Apple doesn’t really like the opening of a third-party app in the login workflow. And the “Safari bounce” is not very user-friendly… So let’s have a look at SFSafariViewController, it may solve our dilemma.

Without further ado, let’s do it!

Two steps, let’s see…

  1. Call the SFSafariViewController with your favorite login URL
  2. In the AppDelegate (application:HandleOpenUrl), when you have parsed the response, dismiss the SFSafariViewController.

That sounds so simple, yet it feels like there a little something missing when you try to implement it. Strangely enough, I couldn’t find any tutorial or example of the implementation of OAuth in SFSafariViewController. I searched the web, GitHub, even Twitter: nothing. So I dug into it, and came to a “viable solution”: a communication via Notification between the AppDelegate and the ViewController. It is not revolutionary, but it works like a charm (if you have any suggestions, please leave a comment below or on Twitter @cath_schwz :)

In your ViewController

Here is the basic setup of your ViewController: import SafariServices, SFSafariViewControllerDelegate and its finish method, declare a name (constant) for our notification. And let’s create an outlet to a button and a SFSafariViewController variable.

Then, let’s create the method called when you tap on the button: the one that will open the SFSafariViewController :

At that point, if your outlet and action are correctly linked to your view, you should be able to display and dismiss manually the SFSafariViewController. Don’t forget to put a URL. Any URL will do for now.

Now let’s add the magic: in viewDidLoad, add an observer that will trigger the safariLogin method when the notification is sent. It’s in your safariLogin method that you will deal with the OAuth response and “automatically” dismiss the SFSafariViewController.

In your AppDelegate

We just saw what happens when the ViewController receives a notification. Now let’s see how the AppDelegate sends it. Easy, no surprises:

What about OAuth?

We just covered the easiest part: displaying and dismissing the SFSafariViewController. Now that you have that running, we can add the OAuth component. And to illustrate my example I’ve chosen Instagram. There is no iOS SDK and no specific way to login via Instagram except by displaying a web view, so it makes the perfect candidate for our study.

I have put the whole project on GitHub: SafariOauthLogin. Don’t hesitate to fork it and to play with it. Just follow the instructions and it should be working out of the box :)

Inside the box

I would like to draw your attention on 2 little things:

  1. The OAuth magic that I’m using for Instagram comes from here. You will find it in the Auth.swift file. It’s pretty short and clean. I like it.
  2. In the safariLogin method, I mention a token called “code” that comes form the response URL. That “code” needs to be extracted in order to be used to “trade” actual information from your third-party API. I do so thanks to the method called extractCode

Further reading

I would love to have a one size fits all for OAuth logins, but something light enough that it could be kept up to date with the third-parties’ APIs and wouldn’t break at each and every update. One can dream…
I know there are pretty cool OAuth tools out there, for example: OAuthSwift, OAuth2, aerogear-ios-oauth2. But none of them is using SFSafariViewController yet, except mwermuth who has forked OAuthSwift to use the SFSafariViewController on Instagram login too. I will definitely keep an eye on that!

Two more words, bear with me:
Reddit has a nice OAuth tutorial. I believe it can be easily tweaked to use the SFSafariViewController instead of the web view.
And finally, if you want a comprehensive OAuth 2 with Swift tutorial, you’ll be in good hands there. You may want to keep it for an other day though, it’s quite a long read too!

That’s all folks! I hope you enjoyed it and that you have found some answers there. Happy coding!

Find the full project on GitHub: SafariOauthLogin