I have a service in the local network with uses custom signed certificate for HTTPS connection. I have the certificate (cer, p12, der, whatever, they are all convertible to each other). Question is what should I write in didReceiveChallenge when receiveing a chellenge of NSURLAuthenticationMethodClientCertificate?
And NO, I don't want to use NSAllowsArbitraryLoads, that would be a security breach. I'm about to use NSAllowsLocalNetworking so far.
- (void)URLSession:(NSURLSession*)session
didReceiveChallenge:(NSURLAuthenticationChallenge*)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential* _Nullable))completionHandler {
bool handled = false;
// Always trust any server name (which is an IP address actually)
NSLog(@"method: %@", challenge.protectionSpace.authenticationMethod);
if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
SecTrustRef trust = challenge.protectionSpace.serverTrust;
if (trust != nullptr) {
completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:trust]);
handled = true;
}
}
else if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate) {
NSString* cerFile = [NSBundle.mainBundle pathForResource:@"dev" ofType:@"der"];
NSData* data = [NSData dataWithContentsOfFile:cerFile];
SecCertificateRef cert = SecCertificateCreateWithData(nil, (CFDataRef)data);
// here I have to somehow validate using existing certificate...
}
if (!handled) {
completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
}
}
Have a look in TrustKit https://github.com/datatheorem/TrustKit. It is the defacto standard for certificate validation and pinning.
For example code will be something like this:
func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
let validator = configureTrustKit().pinningValidator
if(!validator.handle(challenge, completionHandler: completionHandler)){
completionHandler(URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil)
}
}
func configureTrustKit()->TrustKit{
let config = [kTSKPinnedDomains:
[URLRepository.baseURL.host: [kTSKIncludeSubdomains: true,
kTSKEnforcePinning: true,
kTSKPublicKeyHashes:
URLRepository.pinForCurrentStage
]
]
]
return TrustKit(configuration: config)
}
URLSession or frameworks like Alamofire have similar callbacks.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With