How to allow AVPlayer to retrieve SSL protected playlist

We are developing an HTTP streaming iOS application that requires us to receive playlists from a secure site. This site requires us to authenticate using a self-signed SSL certificate.

We read the credentials from a .p12 file before using NSURLConnection with a delegate to respond to an authorization call.

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { [[challenge sender] useCredential: self.credentials forAuthenticationChallenge:challenge]; } - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace { return YES; } 

By making this initial connection to the URL where we get the .m3u8 playlist, we can play the playlist using AVPlayer. The problem is that this method only works in the simulator.

NOTE. We can download the playlist using NSURLConnection on the device. This should mean that AVPlayer somehow cannot continue to use the trust established during this initial connection.

We also tried adding credentials to [NSURLCredentialStorage sharedCredentialStorage] with no luck.

The following is our shotgun approach:

 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 does not work with certificates.

Any hint as to why it doesn't work on the device, or an alternative solution is welcome!

+6
source share
2 answers

Starting with iOS 6, AVASsetResourceLoader can be used to retrieve a protected playlist or key file protected by HTTPS.

The AVAssetResourceLoader object mediates resource requests from the AVURLAsset object with the delegation object you provided. When the request arrives, the resource loader will ask your delegate if he can process the request and send the results back to the asset.

Please find the sample code below.

 // AVURLAsset + Loader AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:url options:nil]; AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:asset]; AVAssetResourceLoader *loader = asset.resourceLoader; [loader setDelegate:self queue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)]; // AVPlayer AVPlayer *avPlayer = [AVPlayer playerWithPlayerItem:playerItem]; 

You will need to process the resourceLoader: shouldWaitForLoadingOfRequestedResource: delegate method, which will be called when authentication is needed, and you can use NSURLConnection to request a secure resource.

 (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest { //Handle NSURLConnection to the SSL secured resource here return YES; } 

Hope this helps!

PS: The proxy approach using CocoaHTTPServer works well, but using AVAssetResourceLoader is a more elegant solution.

+6
source

It seems that while Apple does not allow us to control which NSURLConnections AVPlayer uses, the only answer seems to be to implement an HTTP loopback server.

To quote an Apple representative who answered our support question:

Another option is to implement a loopback HTTP server and point client objects. Clients can use HTTP (because their requests never go out of the device), while the loopback HTTP server itself can use HTTPS to connect to the server source. Again, this gives you access to the core NSURLConnections, allowing you to perform an independent client trust check.

Using this technology with UIWebView will be difficult if you do not have full control of the content on the source server. If the source server can return arbitrary content, you need to return HTTP and rewrite all the links, which is not very fun. a similar restriction applies to MPMoviePlayerController / AVPlayer, but in this case it is much more common for managing all content and thus, non-relative relationships can be avoided.

EDIT: I was able to implement a circular server using the custom HTTPResponse and HTTPConnection implementations found in CocoaHTTPServer

I cannot reveal the source, but I used NSURLConnection along with a combination of AsyncHTTPResponse and DataHTTPResponse demonstration responses.

EDIT: Remember to set myHttpServerObject.interface = @"loopback";

EDIT: WARNING !!! This approach does not seem to work with translation, as the translation device will request 127.1.1.1 for encryption keys. The right 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-U5

"Specify the keys in the .m3u8 files using the URL scheme defined by the application.

EDIT: Updating Apple TV and iOS resolved the issue mentioned in the rule above!

+5
source

Source: https://habr.com/ru/post/906833/


All Articles