diff --git a/cli/src/tasks/copy.ts b/cli/src/tasks/copy.ts index 6943677ab..ce1179e01 100644 --- a/cli/src/tasks/copy.ts +++ b/cli/src/tasks/copy.ts @@ -65,7 +65,11 @@ export async function copy(config: Config, platformName: string, inline = false) } let usesSSLPinning = false; - if (allPlugins.filter((plugin) => plugin.id === '@ionic-enterprise/ssl-pinning').length > 0) { + if ( + allPlugins.filter( + (plugin) => plugin.id === '@ionic-enterprise/ssl-pinning' || plugin.id === '@capacitor/ssl-pinning', + ).length > 0 + ) { usesSSLPinning = true; } diff --git a/ios/Capacitor/Capacitor/CAPPlugin.h b/ios/Capacitor/Capacitor/CAPPlugin.h index 11bb9bda2..944bb3500 100644 --- a/ios/Capacitor/Capacitor/CAPPlugin.h +++ b/ios/Capacitor/Capacitor/CAPPlugin.h @@ -38,6 +38,11 @@ * Returning nil will defer to the default Capacitor policy */ - (NSNumber* _Nullable)shouldOverrideLoad:(WKNavigationAction* _Nonnull)navigationAction; +/** + * Allows plugins to hook into and respond to the WebView's URL authentication challenge. + * Returning false will defer to the default response of [.rejectProtectionSpace](https://developer.apple.com/documentation/Foundation/URLSession/AuthChallengeDisposition/rejectProtectionSpace). + */ +- (BOOL)handleWKWebViewURLAuthenticationChallenge:(NSURLAuthenticationChallenge* _Nonnull)challenge completionHandler:(void (^_Nonnull)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler; // Called after init if the plugin wants to do // some loading so the plugin author doesn't diff --git a/ios/Capacitor/Capacitor/CAPPlugin.m b/ios/Capacitor/Capacitor/CAPPlugin.m index 4ce7e5b0c..afa7c9a8b 100644 --- a/ios/Capacitor/Capacitor/CAPPlugin.m +++ b/ios/Capacitor/Capacitor/CAPPlugin.m @@ -171,5 +171,10 @@ - (NSNumber*)shouldOverrideLoad:(WKNavigationAction*)navigationAction { return nil; } +- (BOOL)handleWKWebViewURLAuthenticationChallenge:(NSURLAuthenticationChallenge* _Nonnull)challenge completionHandler:(void (^_Nonnull)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler { + return NO; +} + + @end diff --git a/ios/Capacitor/Capacitor/WebViewDelegationHandler.swift b/ios/Capacitor/Capacitor/WebViewDelegationHandler.swift index d0870ad1e..2b4a256d0 100644 --- a/ios/Capacitor/Capacitor/WebViewDelegationHandler.swift +++ b/ios/Capacitor/Capacitor/WebViewDelegationHandler.swift @@ -161,6 +161,26 @@ open class WebViewDelegationHandler: NSObject, WKNavigationDelegate, WKUIDelegat webView.reload() } + open func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping @MainActor (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { + guard let bridge = bridge else { + completionHandler(.rejectProtectionSpace, nil) + return + } + + for pluginObject in bridge.plugins { + let plugin = pluginObject.value + let selector = NSSelectorFromString("handleWKWebViewURLAuthenticationChallenge:completionHandler:") + if plugin.responds(to: selector) { + if plugin.handleWKWebViewURLAuthenticationChallenge(challenge, completionHandler: completionHandler) { + return + } + } + } + + completionHandler(.rejectProtectionSpace, nil) + return + } + // MARK: - WKScriptMessageHandler open func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {