Я пытаюсь аутентифицировать приложение iOS с помощью API Spotify, используя OAuth2.Для этого я использую OAuthSwift .
Когда мое приложение загружается, я перенаправлен на Spotify, я могу войти и разрешить моему приложению доступ к моей учетной записи.
КогдаЯ перенаправлен обратно в мое приложение, однако WebView
отклоняется, однако сразу же открывается на предыдущей странице, закрывается и снова открывается.
Это продолжается в цикле бесконечно.
Я задавался вопросом, что это как-то связано с тем, что моя initAuthFlow
функция вызывается в viewDidAppear
, однако перемещение этого в viewDidLoad
жалуется на
Warning: Attempt to present <OAuthKeyChainApp.WKWebViewController: 0x7fb42b505160> on <OAuthKeyChainApp.HomeController: 0x7fb42b50cf30> whose view is not in the window hierarchy!
и контроллер никогда не отображается.
HomeController.swift
class HomeController: OAuthViewController {
let oauthSwift = OAuth2Swift(
consumerKey: "xxxxxx",
consumerSecret: "xxxxxx",
authorizeUrl: "https://accounts.spotify.com/en/authorize",
accessTokenUrl: "https://accounts.spotify.com/api/token",
responseType: "code"
)
lazy var internalWebViewController: WKWebViewController = {
let controller = WKWebViewController()
controller.view = UIView(frame: UIScreen.main.bounds)
controller.loadView()
controller.viewDidLoad()
return controller
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .purple
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
initAuthFlow()
}
fileprivate func initAuthFlow() -> Void {
oauthSwift.authorizeURLHandler = internalWebViewController
guard let callbackURL = URL(string: "oauthkeychainapp://oauthkeychain-callback") else { return }
oauthSwift.authorize(
withCallbackURL: callbackURL,
scope: "user-library-modify",
state: generateState(withLength: 20),
success: { (credential, response, params) in
print(credential)
}) { (error) in
print(error.localizedDescription)
}
}
}
extension HomeController: OAuthWebViewControllerDelegate {
func oauthWebViewControllerDidPresent() { }
func oauthWebViewControllerDidDismiss() { }
func oauthWebViewControllerWillAppear() { }
func oauthWebViewControllerDidAppear() { }
func oauthWebViewControllerWillDisappear() { }
func oauthWebViewControllerDidDisappear() { oauthSwift.cancel() }
}
WKWebViewController.swift
import UIKit
import WebKit
import OAuthSwift
class WKWebViewController: OAuthWebViewController {
var webView: WKWebView!
var targetURL: URL?
override func viewDidLoad() {
super.viewDidLoad()
}
override func handle(_ url: URL) {
targetURL = url
super.handle(url)
loadAddressURL()
}
func loadAddressURL() {
guard let url = targetURL else { return }
let req = URLRequest(url: url)
self.webView?.load(req)
}
}
extension WKWebViewController: WKUIDelegate, WKNavigationDelegate {
override func loadView() {
let webConfiguration = WKWebViewConfiguration()
webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.allowsBackForwardNavigationGestures = true
webView.uiDelegate = self
webView.navigationDelegate = self
view = webView
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("loaded")
}
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
// Check for OAuth Callback
if let url = navigationAction.request.url, url.scheme == "oauthkeychainapp" {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
self.dismiss(animated: true, completion: nil)
decisionHandler(.cancel)
return
}
// Restrict URL's a user can access
if let host = navigationAction.request.url?.host {
if host.contains("spotify") {
decisionHandler(.allow)
return
} else {
// open link outside of our app
UIApplication.shared.open(navigationAction.request.url!)
decisionHandler(.cancel)
return
}
}
decisionHandler(.cancel)
}
}