Essayer d'utiliser Facebook OAuth avec SafariViewController. D'abord j'ouvre l'authURL avec SafariViewController, qui si l'utilisateur est connecté à Facebook sur Safari, les redirigera et renverra un OAuth URL avec le jeton pour ce service spécifique, par exemple Instagram
Lorsque SafariViewController a redirigé je veux récupérer l'URL de réponse et la stocker afin de pouvoir récupérer le jeton. Voici mon 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
}
}
Il ouvre l'authURL et redirige vers l'URL de réponse correcte, mais l'observateur ne déclenche pas la fonction safariLogin pour récupérer l'URL. Toute aide serait très appréciée!
Merci beaucoup!
iOS 12 Beta déprécie déjà SFAuthenticationSession (voir ci-dessous) au profit de ASWebAuthenticationSession . Il semble qu'il soit utilisé exactement de la même manière mais nécessite le nouveau framework AuthenticationServices .
iOS 11 a introduit SFAuthenticationSession qui est tellement plus facile à gérer. Compte tenu de sa nature, cette API bêta peut encore changer, mais il existe déjà quelques exemples ( 1 , 2 ) sur Internet. Tout d'abord, vous avez besoin d'un gestionnaire d'achèvement qui est appelé avec le résultat de la demande d'authentification:
let completion : SFAuthenticationSession.CompletionHandler = { (callBack:URL?, error:Error?) in
guard error == nil, let successURL = callBack else {
return
}
let oauthToken = NSURLComponents(string: (successURL.absoluteString))?.queryItems?.filter({$0.name == "oauth_token"}).first
// Do what you have to do...
}
Il vous suffit ensuite de créer une session SFAuthenticationSession et de la démarrer.
let authURL = "https://the.service.you/want/toAuthorizeWith?..."
let scheme = "YOURSCHEME://"
let authSession = SFAuthenticationSession(url: authURL, callbackURLScheme: scheme, completionHandler: completion)
authSession.start()
Comme certains l'ont noté dans les commentaires, la réponse acceptée est incomplète et ne fonctionnera pas d'elle-même. Lorsque vous vous promenez dans le blog de Strawberry Code, vous pouvez trouver un lien vers le projet GitHub associé . Le README.MD
De ce projet explique une partie cruciale de la configuration, à savoir l'ajout de l'URI de redirection à Info.plist
. Donc, tout se passe comme suit:
AppDelegate.Swift
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
if let sourceApplication = options[.sourceApplication] {
if (String(describing: sourceApplication) == "com.Apple.SafariViewService") {
NotificationCenter.default.post(name: Notification.Name("CallbackNotification"), object: url)
return true
}
}
return false
}
ViewController.Swift
Inscrivez-vous à la notification pour appeler votre gestionnaire dans un endroit raisonnable. Je recommande de ne pas le faire dans viewDidLoad()
mais seulement avant de présenter réellement le SFSafariViewController
.
NotificationCenter.default.addObserver(self, selector: #selector(safariLogin(_:)), name: Notification.Name("CallbackNotification"), object: nil)
let safariVC = SFSafariViewController(URL: authURL)
safariVC.delegate = self
self.present(safariVC, animated: true, completion: nil)
Et puis supprimez l'observance dans le gestionnaire:
@objc func safariLogin(_ notification : Notification) {
NotificationCenter.default.removeObserver(self, name: Notification.Name("CallbackNotification"), object: nil)
guard let url = notification.object as? URL else {
return
}
// Parse url ...
}
N'oubliez pas que l'utilisateur peut ignorer le SFSafariViewController
en appuyant sur le bouton Done
, assurez-vous donc d'adopter le protocole SFSafariViewControllerDelegate
et de supprimer également l'observation comme ceci:
func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
NotificationCenter.default.removeObserver(self, name: Notification.Name("CallbackNotification"), object: nil)
}
Info.plist
Pour que tout fonctionne, vous devez ajouter votre schéma d'URI de redirection à Info.plist
:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>com.YOUR.BUNDLE.IDENTIFIER</string>
<key>CFBundleURLSchemes</key>
<array>
<string>YOURSCHEME</string>
</array>
</dict>
</array>
Bien sûr, YOURSCHEME doit correspondre au schéma de l'URI de redirection que vous avez enregistré avec le service Web avec lequel vous essayez d'autoriser.