Created
January 13, 2017 16:33
-
-
Save celian-m/8da09ad293507940a0081507f057def5 to your computer and use it in GitHub Desktop.
Perform client side certificate check
This file contains 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
import Foundation | |
public struct IdentityAndTrust { | |
public var identityRef:SecIdentity | |
public var trust:SecTrust | |
public var certArray:NSArray | |
} | |
public func extractIdentity(certData:NSData, certPassword:String) -> IdentityAndTrust { | |
var identityAndTrust:IdentityAndTrust! | |
var securityError:OSStatus = errSecSuccess | |
var items: CFArray? | |
let certOptions: Dictionary = [ kSecImportExportPassphrase as String : certPassword ]; | |
// import certificate to read its entries | |
securityError = SecPKCS12Import(certData, certOptions as CFDictionary, &items); | |
if securityError == errSecSuccess { | |
let certItems:CFArray = items as CFArray!; | |
let certItemsArray:Array = certItems as Array | |
let dict:AnyObject? = certItemsArray.first; | |
if let certEntry:Dictionary = dict as? Dictionary<String, AnyObject> { | |
// grab the identity | |
let identityPointer:AnyObject? = certEntry["identity"]; | |
let secIdentityRef:SecIdentity = identityPointer as! SecIdentity!; | |
// grab the trust | |
let trustPointer:AnyObject? = certEntry["trust"]; | |
let trustRef:SecTrust = trustPointer as! SecTrust; | |
// grab the certificate chain | |
var certRef: SecCertificate? | |
SecIdentityCopyCertificate(secIdentityRef, &certRef); | |
let certArray:NSMutableArray = NSMutableArray(); | |
certArray.add(certRef as SecCertificate!); | |
identityAndTrust = IdentityAndTrust(identityRef: secIdentityRef, trust: trustRef, certArray: certArray); | |
} | |
} | |
return identityAndTrust; | |
} | |
public class SessionDelegate : NSObject, URLSessionDelegate { | |
public func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { | |
if let localCertPath = Bundle.main.url(forResource: "{YOUR_CERT_NAME}", withExtension: "{YOUR_CERT_EXTENSION}"), | |
let localCertData = try? Data(contentsOf: localCertPath) | |
{ | |
let identityAndTrust:IdentityAndTrust = extractIdentity(certData: localCertData as NSData, certPassword: "{YOUR_CERT_PWD}") | |
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate { | |
let urlCredential:URLCredential = URLCredential( | |
identity: identityAndTrust.identityRef, | |
certificates: identityAndTrust.certArray as [AnyObject], | |
persistence: URLCredential.Persistence.forSession); | |
completionHandler(URLSession.AuthChallengeDisposition.useCredential, urlCredential); | |
return | |
} | |
} | |
challenge.sender?.cancel(challenge) | |
completionHandler(URLSession.AuthChallengeDisposition.rejectProtectionSpace, nil) | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
If you have more than one certificate (SecCertificate) use this:
I used it for MBWAY authentication.