Trying to use Facebook OAuth with the SafariViewController. First I open the authURL with SafariViewController, which if the user is logged in to Facebook on Safari, will redirect them and return an OAuth URL with the token for that specific service, e.g. Instagram
When SafariViewController has redirected I want to grab the response URL and store it so I can grab the token. Here is my code:
import SafariServices
let kSafariViewControllerCloseNotification = "kSafariViewControllerCloseNotification"
import UIKit
// facebook OAuth URL for service
let authURL = NSURL(string: "https://www.facebook.com/dialog/oauth?client_id=3627644767&redirect_uri=https://www.facebook.com/connect/login_success.html&scope=basic_info,email,public_profile,user_about_me,user_activities,user_birthday,user_education_history,user_friends,user_interests,user_likes,user_location,user_photos,user_relationship_details&response_type=token")
class ViewController: UIViewController, SFSafariViewControllerDelegate {
var safariVC: SFSafariViewController?
@IBOutlet weak var loginButton: UIButton!
@IBAction func loginButtonTapped(sender: UIButton) {
safariVC = SFSafariViewController(URL: authURL!)
safariVC!.delegate = self
self.presentViewController(safariVC!, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
// not firing the safariLogin function below
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ViewController.safariLogin(_:)), name: kSafariViewControllerCloseNotification, object: nil)
}
func safariLogin(notification: NSNotification) {
print("Safari Login call")
// get the url form the auth callback
let url = notification.object as! NSURL
print(url)
self.safariVC!.dismissViewControllerAnimated(true, completion: nil)
}
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
print("application call")
// just making sure we send the notification when the URL is opened in SFSafariViewController
if (sourceApplication == "com.application.SafariViewTest") {
NSNotificationCenter.defaultCenter().postNotificationName(kSafariViewControllerCloseNotification, object: url)
return true
}
return true
}
}
It opens the authURL and redirects to the correct response URL, but the observer does not fire the safariLogin function to grab the URL. Any help would be much appreciated!
Thanks so much!
Figured it out. Some of the methods were pre iOS 9 and now deprecated. I also had the
application
function in the ViewController I created when it should have been defined in theAppDelagate.swift
. For exampleAdded at end of AppDelegate.swift
ViewController.swift
iOS 12
iOS 12 Beta already deprecates SFAuthenticationSession (see below) in favor of ASWebAuthenticationSession. It looks like it is used exactly the same way but requires the new AuthenticationServices framework.
iOS 11
iOS 11 introduced SFAuthenticationSession which is so much easier to handle. Given its nature this beta API may still change but there already are a couple of examples (1, 2) on the internet. First, you need a completion handler that is called with the result of the authentication request:
Then you simply create a SFAuthenticationSession and start it.
iOS 10 and before
As some have noted in the comments, the accepted answer is incomplete and won't work on its own. When strolling through Strawberry Code's blog post one can find a link to the related GitHub project. That project's
README.MD
explains a crucial part of the setup, namely adding the redirect URI toInfo.plist
. So the whole thing goes down like this:AppDelegate.swift
ViewController.swift
Register for the notification to call your handler in some sensible place. I'd recommend not doing it in
viewDidLoad()
but only before you are actually presenting theSFSafariViewController
.And then remove the observance in the handler:
Remember that the user is able to dismiss the
SFSafariViewController
by tapping theDone
button, so be sure to adopt theSFSafariViewControllerDelegate
protocol and remove the observance like this as well:Info.plist
To make it all work you need to add your redirect URI scheme to
Info.plist
:Of course YOURSCHEME has to match the scheme of the redirect URI you registered with the web service you're trying to oAuthorizing with.