We´re developing a HTTP-streaming iOS app that requires us to receive playlists from a secured site. This site requires us to authenticate using a self signed SSL certificate.
We read the credentials from a .p12 file before we use NSURLConnection with a delegate to react to the authorization challenge.
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
[[challenge sender] useCredential: self.credentials forAuthenticationChallenge:challenge];
}
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
return YES;
}
By doing this initial connection to the URL where we´re getting the .m3u8 playlist we´re able to play back the playlist using AVPlayer. The problem is that this method only works in the simulator.
NOTE: We´re able to download the playlist using the NSURLConnection on device. This must mean that the AVPlayer somehow can´t continue using the trust established during this initial connection.
We have also tried adding the credentials to the [NSURLCredentialStorage sharedCredentialStorage] without any luck.
Below follows our shotgun approach for that:
NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
initWithHost:host
port:443
protocol:@"https"
realm:nil
authenticationMethod:NSURLAuthenticationMethodClientCertificate];
[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:creds
forProtectionSpace:protectionSpace];
NSURLProtectionSpace *protectionSpace2 = [[NSURLProtectionSpace alloc]
initWithHost:host
port:443
protocol:@"https"
realm:nil
authenticationMethod:NSURLAuthenticationMethodServerTrust];
[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:creds
forProtectionSpace:protectionSpace2];
EDIT: According to this question: the above method doesn´t work with certificates.
Any hint to why it doesn´t work on device, or an alternate solution is welcome!
From iOS 6 onwards AVAssetResourceLoader can be used for retrieving an HTTPS secured playlist or key file.
Please find the sample code below.
You will need to handle the resourceLoader:shouldWaitForLoadingOfRequestedResource:delegate method which will be called when there is an authentication need and you can use NSURLConnection to request for the secured resource.
Hope this helps!
P.S : The proxy approach using CocoaHTTPServer works well but using an AVAssetResourceLoader is a more elegant solution.
It seems that until Apple lets us control what NSURLConnections the AVPlayer uses the only answer seems to be to implement a HTTP loopback server.
To quote the apple representative that answered our support question:
EDIT: I managed to implement a loopback server using custom implemenations of the HTTPResponse and HTTPConnection classes found in CocoaHTTPServer
I can´t disclose the source, but I used NSURLConnection together with a mix of the AsyncHTTPResponse and DataHTTPResponse demonstration responses.
EDIT: Remember to set
myHttpServerObject.interface = @"loopback";
EDIT: WARNING!!! This approach does not seem to work with airplay since the airplay device will ask 127.1.1.1 for encryption keys. The correct approach seems to be defined here: https://developer.apple.com/library/content/documentation/AudioVideo/Conceptual/AirPlayGuide/EncryptionandAuthentication/EncryptionandAuthentication.html#//apple_ref/doc/uid/TP40011045-CH5-SW1
"Specify the keys in the .m3u8 files using an application-defined URL scheme."
EDIT: An apple TV and iOS update has resolved the issue mentioned in the edit above!