I have a server that uses self-signed SSL certificates for HTTPS. I have the self-signed root cert bundled into my app. I'm able to get NSURLSession
to use and validate the self-signed root cert by using SecTrustSetAnchorCertificates()
in the -URLSession:didReceiveChallenge:completionHandler:
delegate method.
When I try this with AVPlayer
, however, I get an SSL error and playback fails. This is my AVAssetResourceLoader
delegate implementation:
- (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForResponseToAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
if ([challenge.protectionSpace.authenticationMethod isEqual:NSURLAuthenticationMethodServerTrust]) {
SecTrustRef trust = challenge.protectionSpace.serverTrust;
SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)self.secTrustCertificates);
SecTrustResultType trustResult = kSecTrustResultInvalid;
OSStatus status = SecTrustEvaluate(trust, &trustResult);
if (status == errSecSuccess && (trustResult == kSecTrustResultUnspecified || trustResult == kSecTrustResultProceed)) {
[challenge.sender useCredential:[NSURLCredential credentialForTrust:trust] forAuthenticationChallenge:challenge];
return YES;
} else {
[challenge.sender cancelAuthenticationChallenge:challenge];
return YES;
}
}
return NO;
}
The delegate gets called, and the trustResult
equates to kSecTrustResultUnspecified
(which means "trusted, without explicit user override"), as expected. However, playback fails shortly after, with the following AVPlayerItem.error
:
Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, NSUnderlyingError=0x16c35720 {Error Domain=NSOSStatusErrorDomain Code=-1200 "(null)"}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made.}
How can I get AVPlayer
to accept the SSL handshake?
This implementation has worked for me:
- (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader
shouldWaitForResponseToAuthenticationChallenge:(NSURLAuthenticationChallenge *)authenticationChallenge
{
//server trust
NSURLProtectionSpace *protectionSpace = authenticationChallenge.protectionSpace;
if ([protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
[authenticationChallenge.sender useCredential:[NSURLCredential credentialForTrust:authenticationChallenge.protectionSpace.serverTrust] forAuthenticationChallenge:authenticationChallenge];
[authenticationChallenge.sender continueWithoutCredentialForAuthenticationChallenge:authenticationChallenge];
}
else { // other type: username password, client trust...
}
return YES;
}
However, it stopped working as of iOS 10.0.1 for a reason I have yet to discern. So this may or may not be helpful to you. Good luck!
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