Last active
September 1, 2022 09:41
-
-
Save tempire/1e6191e810636a638d0f203c8240d2b8 to your computer and use it in GitHub Desktop.
WKWebView with client certificate
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ViewController.swift | |
// CertificateRequest | |
// | |
// Created by Glen Hinkle on 3/4/19. | |
// Copyright © 2019 Zombie Dolphin LLC. All rights reserved. | |
// | |
// Works with iOS 12 | |
// | |
import UIKit | |
import WebKit | |
class ViewController: UIViewController { | |
@IBOutlet weak var contentView: UIView! | |
var webView: WKWebView! | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
let webConfiguration = WKWebViewConfiguration() | |
webView = WKWebView(frame: .zero, configuration: webConfiguration) | |
webView.navigationDelegate = self | |
contentView.addSubview(webView) | |
contentView.pinToInside(webView) | |
webView.load( | |
url: URL( | |
string: "https://some-web-server-that-requires-client-certificate-authentication")!) | |
} | |
} | |
extension ViewController: WKNavigationDelegate { | |
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { | |
print(navigation) | |
} | |
func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { | |
let method = challenge.protectionSpace.authenticationMethod | |
switch method { | |
case NSURLAuthenticationMethodClientCertificate: | |
sendClientCertificate(for: challenge, via: completionHandler) | |
default: | |
completionHandler(.performDefaultHandling, .none) | |
} | |
} | |
func sendClientCertificate(for challenge: URLAuthenticationChallenge, via completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { | |
guard let path = Bundle.main.path(forResource: "some-certificate-file", ofType: "p12"), | |
let data = try? Data(contentsOf: URL(fileURLWithPath: path)), | |
let credential = credential(from: data, withPassword: "some-certificate-password") else { | |
challenge.sender?.cancel(challenge) | |
return completionHandler(.rejectProtectionSpace, .none) | |
} | |
return completionHandler(.useCredential, credential); | |
} | |
func credential(from data: Data, withPassword password: String) -> URLCredential? { | |
guard let security = security(from: data, withPassword: password) else { | |
return .none | |
} | |
return URLCredential( | |
identity: security.identity, | |
certificates: security.certificates, | |
persistence: .permanent | |
) | |
} | |
func security(from data: Data, withPassword password: String) -> (identity: SecIdentity, trust: SecTrust, certificates: [SecCertificate])? { | |
var _items: CFArray? | |
let securityError = SecPKCS12Import(data as NSData, | |
[ kSecImportExportPassphrase as String : password ] as CFDictionary, | |
&_items); | |
guard let items = _items as? [Any], | |
let dict = items.first as? [String:Any], | |
securityError == errSecSuccess else { | |
return .none | |
} | |
let identity = dict["identity"] as! SecIdentity | |
let trust = dict["trust"] as! SecTrust; | |
// Certificate chain | |
var certificate: SecCertificate! | |
SecIdentityCopyCertificate(identity, &certificate); | |
return (identity, trust, [certificate]); | |
} | |
} |
I am interested in performing the same. I achieved doing this only using a custom nsurlprotocol, forcing wkwebview using it. It is not the right way and I am looking for something similar
Hi,
in this code you are providing a p12 to perform an SSL client authentication.
If private key is on external token (accessible in some way) is it still possible do to client auth?
Thanks
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi,
in this code you are providing a p12 to perform an SSL client authentication.
If private key is on external token (accessible in some way) is it still possible do to client auth?
Thanks