Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion flutter_inappwebview/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ dependencies:
sdk: flutter
flutter_inappwebview_platform_interface: ^1.3.0
flutter_inappwebview_android: ^1.1.3
flutter_inappwebview_ios: ^1.1.2
flutter_inappwebview_ios:
git:
url: https://github.com/relution-io/flutter_inappwebview
ref: feature/ios_without_server_auth_challenge
path: flutter_inappwebview_ios
flutter_inappwebview_macos: ^1.1.2
flutter_inappwebview_web: ^1.1.2
flutter_inappwebview_windows: ^0.6.0
Expand Down
265 changes: 0 additions & 265 deletions flutter_inappwebview_ios/ios/Classes/InAppWebView/InAppWebView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1975,235 +1975,6 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
inAppBrowserDelegate?.didFailNavigation(url: url, error: error)
}

public func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
var completionHandlerCalled = false
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic ||
challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodDefault ||
challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPDigest ||
challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodNegotiate ||
challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodNTLM {
let host = challenge.protectionSpace.host
let prot = challenge.protectionSpace.protocol
let realm = challenge.protectionSpace.realm
let port = challenge.protectionSpace.port

let callback = WebViewChannelDelegate.ReceivedHttpAuthRequestCallback()
callback.nonNullSuccess = { (response: HttpAuthResponse) in
if let action = response.action {
completionHandlerCalled = true
switch action {
case 0:
InAppWebView.credentialsProposed = []
// used .performDefaultHandling to maintain consistency with Android
// because .cancelAuthenticationChallenge will call webView(_:didFail:withError:)
completionHandler(.performDefaultHandling, nil)
//completionHandler(.cancelAuthenticationChallenge, nil)
break
case 1:
let username = response.username
let password = response.password
let permanentPersistence = response.permanentPersistence
let persistence = (permanentPersistence) ? URLCredential.Persistence.permanent : URLCredential.Persistence.forSession
let credential = URLCredential(user: username, password: password, persistence: persistence)
completionHandler(.useCredential, credential)
break
case 2:
if InAppWebView.credentialsProposed.count == 0 {
for (protectionSpace, credentials) in CredentialDatabase.credentialStore.allCredentials {
if protectionSpace.host == host && protectionSpace.realm == realm &&
protectionSpace.protocol == prot && protectionSpace.port == port {
for credential in credentials {
InAppWebView.credentialsProposed.append(credential.value)
}
break
}
}
}
if InAppWebView.credentialsProposed.count == 0, let credential = challenge.proposedCredential {
InAppWebView.credentialsProposed.append(credential)
}

if let credential = InAppWebView.credentialsProposed.popLast() {
completionHandler(.useCredential, credential)
}
else {
completionHandler(.performDefaultHandling, nil)
}
break
default:
InAppWebView.credentialsProposed = []
completionHandler(.performDefaultHandling, nil)
}
return false
}
return true
}
callback.defaultBehaviour = { (response: HttpAuthResponse?) in
if !completionHandlerCalled {
completionHandlerCalled = true
completionHandler(.performDefaultHandling, nil)
}
}
callback.error = { [weak callback] (code: String, message: String?, details: Any?) in
print(code + ", " + (message ?? ""))
callback?.defaultBehaviour(nil)
}

let runCallback = {
if let channelDelegate = self.channelDelegate {
channelDelegate.onReceivedHttpAuthRequest(challenge: HttpAuthenticationChallenge(fromChallenge: challenge), callback: callback)
} else {
callback.defaultBehaviour(nil)
}
}

if windowId != nil, !windowCreated {
windowBeforeCreatedCallbacks.append(runCallback)
} else {
runCallback()
}
}
else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
guard let serverTrust = challenge.protectionSpace.serverTrust else {
completionHandler(.performDefaultHandling, nil)
return
}

if let scheme = challenge.protectionSpace.protocol, scheme == "https" {
// workaround for ProtectionSpace SSL Certificate
// https://github.com/pichillilorenzo/flutter_inappwebview/issues/1678
DispatchQueue.global(qos: .background).async {
if let sslCertificate = challenge.protectionSpace.sslCertificate {
DispatchQueue.main.async {
InAppWebView.sslCertificatesMap[challenge.protectionSpace.host] = sslCertificate
}
}
}
}

let callback = WebViewChannelDelegate.ReceivedServerTrustAuthRequestCallback()
callback.nonNullSuccess = { (response: ServerTrustAuthResponse) in
if let action = response.action {
completionHandlerCalled = true
switch action {
case 0:
InAppWebView.credentialsProposed = []
completionHandler(.cancelAuthenticationChallenge, nil)
break
case 1:
// workaround for https://github.com/pichillilorenzo/flutter_inappwebview/issues/1924
DispatchQueue.global(qos: .background).async {
let exceptions = SecTrustCopyExceptions(serverTrust)
SecTrustSetExceptions(serverTrust, exceptions)
let credential = URLCredential(trust: serverTrust)
completionHandler(.useCredential, credential)
}
break
default:
InAppWebView.credentialsProposed = []
completionHandler(.performDefaultHandling, nil)
}
return false
}
return true
}
callback.defaultBehaviour = { (response: ServerTrustAuthResponse?) in
if !completionHandlerCalled {
completionHandlerCalled = true
completionHandler(.performDefaultHandling, nil)
}
}
callback.error = { [weak callback] (code: String, message: String?, details: Any?) in
print(code + ", " + (message ?? ""))
callback?.defaultBehaviour(nil)
}

let runCallback = {
if let channelDelegate = self.channelDelegate {
channelDelegate.onReceivedServerTrustAuthRequest(challenge: ServerTrustChallenge(fromChallenge: challenge), callback: callback)
} else {
callback.defaultBehaviour(nil)
}
}

if windowId != nil, !windowCreated {
windowBeforeCreatedCallbacks.append(runCallback)
} else {
runCallback()
}
}
else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate {
let callback = WebViewChannelDelegate.ReceivedClientCertRequestCallback()
callback.nonNullSuccess = { (response: ClientCertResponse) in
if let action = response.action {
completionHandlerCalled = true
switch action {
case 0:
completionHandler(.cancelAuthenticationChallenge, nil)
break
case 1:
let certificatePath = response.certificatePath
let certificatePassword = response.certificatePassword ?? "";

var path: String = certificatePath
do {
if let plugin = self.plugin {
path = try Util.getAbsPathAsset(plugin: plugin, assetFilePath: certificatePath)
}
} catch {}

if let PKCS12Data = NSData(contentsOfFile: path),
let identityAndTrust: IdentityAndTrust = self.extractIdentity(PKCS12Data: PKCS12Data, password: certificatePassword) {
let urlCredential: URLCredential = URLCredential(
identity: identityAndTrust.identityRef,
certificates: identityAndTrust.certArray as? [AnyObject],
persistence: URLCredential.Persistence.forSession);
completionHandler(.useCredential, urlCredential)
} else {
completionHandler(.performDefaultHandling, nil)
}

break
case 2:
completionHandler(.cancelAuthenticationChallenge, nil)
break
default:
completionHandler(.performDefaultHandling, nil)
}
return false
}
return true
}
callback.defaultBehaviour = { (response: ClientCertResponse?) in
if !completionHandlerCalled {
completionHandlerCalled = true
completionHandler(.performDefaultHandling, nil)
}
}
callback.error = { [weak callback] (code: String, message: String?, details: Any?) in
print(code + ", " + (message ?? ""))
callback?.defaultBehaviour(nil)
}

let runCallback = {
if let channelDelegate = self.channelDelegate {
channelDelegate.onReceivedClientCertRequest(challenge: ClientCertChallenge(fromChallenge: challenge), callback: callback)
} else {
callback.defaultBehaviour(nil)
}
}

if windowId != nil, !windowCreated {
windowBeforeCreatedCallbacks.append(runCallback)
} else {
runCallback()
}
}
else {
completionHandler(.performDefaultHandling, nil)
}
}

struct IdentityAndTrust {
var identityRef: SecIdentity
var trust: SecTrust
Expand Down Expand Up @@ -2572,42 +2343,6 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
return windowWebView
}

public func webView(_ webView: WKWebView,
authenticationChallenge challenge: URLAuthenticationChallenge,
shouldAllowDeprecatedTLS decisionHandler: @escaping (Bool) -> Void) {
var decisionHandlerCalled = false
let callback = WebViewChannelDelegate.ShouldAllowDeprecatedTLSCallback()
callback.nonNullSuccess = { (action: Bool) in
decisionHandlerCalled = true
decisionHandler(action)
return false
}
callback.defaultBehaviour = { (action: Bool?) in
if !decisionHandlerCalled {
decisionHandlerCalled = true
decisionHandler(false)
}
}
callback.error = { [weak callback] (code: String, message: String?, details: Any?) in
print(code + ", " + (message ?? ""))
callback?.defaultBehaviour(nil)
}

let runCallback = {
if let channelDelegate = self.channelDelegate {
channelDelegate.shouldAllowDeprecatedTLS(challenge: challenge, callback: callback)
} else {
callback.defaultBehaviour(nil)
}
}

if windowId != nil, !windowCreated {
windowBeforeCreatedCallbacks.append(runCallback)
} else {
runCallback()
}
}

public func webViewDidClose(_ webView: WKWebView) {
channelDelegate?.onCloseWindow()
}
Expand Down