iosswiftxcodeurlnsapptransportsecurity

How to allow loading png from http via adding NSExceptionDomains in ATS?


in exercise https://github.com/Mairoslav/5networkAndGDC/tree/main/ImageRequest I would like to allow the jpg to be loaded from the web site with "http" scheme by adjusting NSAppTransportSecurity in Info.plist as written below. I do not want to allow any other "http" sites, therefore opted to set NSAllowsArbitraryLoads to false. If you can advice.

<dict>
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <false/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>www.kittenswhiskers.com</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSExceptionMinimumTLSVersion</key>
            <string>TLSv1.0</string>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <false/>
        </dict>
    </dict>
</dict>

Even after these adjustments, there is an error: "The resource could not be loaded because the App Transport Security policy requires the use of a secure connection." I have tried all alternative options for NSExceptionMinimumTLSVersion. The sources I was using were: https://agilie.com/blog/how-to-add-domain-exceptions-to-comply-with-apples-new-ats-requirements, https://cocoacasts.com/how-to-add-app-transport-security-exception-domains and https://developer.apple.com/documentation/bundleresources/information_property_list/nsapptransportsecurity


Solution

  • Here is my test code and Info.plist, that works well for me. Tested on real devices, not Previews.

    The Info.plist

     <?xml version="1.0" encoding="UTF-8"?>
     <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
     <plist version="1.0">
     <dict>
    
         <key>NSAppTransportSecurity</key>
         <dict>
             <key>NSAllowsArbitraryLoads</key>
             <false/>
             <key>NSExceptionDomains</key>
             <dict>
                 <key>www.kittenswhiskers.com</key>
                 <dict>
                     <key>NSIncludesSubdomains</key>
                     <true/>
                     <key>NSExceptionAllowsInsecureHTTPLoads</key>
                     <true/>
                     <key>NSExceptionMinimumTLSVersion</key>
                     <string>TLSv1.0</string>
                     <key>NSExceptionRequiresForwardSecrecy</key>
                     <false/>
                 </dict>
             </dict>
         </dict>
    
     </dict>
     </plist>
     
    

    The test code

    struct ContentView: View {
        @State var image = UIImage()
        
        var body: some View {
            Image(uiImage: image)
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(width: 333, height: 333)
                .cornerRadius(10)
                .task {
                    if let url = URL(string: "http://www.kittenswhiskers.com/wp-content/uploads/sites/23/2014/02/Kitten-playing-with-yarn.jpg") {
                        image = await loadImage(url: url)
                    }
                }
        }
        
        func loadImage(url: URL) async -> UIImage {
            do {
                let (data, _) = try await URLSession.shared.data(from: url)
                if let img = UIImage(data: data) { return img }
            }
            catch { print(error) }
            return UIImage()
        }
    }