Posts under App & System Services topic

Post

Replies

Boosts

Views

Activity

Don’t Try to Get the Device’s IP Address
For important background information, read Extra-ordinary Networking before reading this. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Don’t Try to Get the Device’s IP Address I regularly see questions like: How do I find the IP address of the device? How do I find the IP address of the Wi-Fi interface? How do I identify the Wi-Fi interface? I also see a lot of really bad answers to these questions. That’s understandable, because the questions themselves don’t make sense. Networking on Apple platforms is complicated and many of the things that are ‘obviously’ true are, in fact, not true at all. For example: There’s no single IP address that represents the device, or an interface. A device can have 0 or more interfaces, each of which can have 0 or more IP addresses, each of which can be IPv4 and IPv6. A device can have multiple interfaces of a given type. It’s common for iPhones to have multiple WWAN interfaces, for example. It’s not possible to give a simple answer to any of these questions, because the correct answer depends on the context. Why do you need this particular information? What are you planning to do with it? This post describes the scenarios I most commonly encounter, with my advice on how to handle each scenario. IMPORTANT BSD interface names, like en0, are not considered API. There’s no guarantee, for example, that an iPhone’s Wi-Fi interface is en0. If you write code that relies on a hard-coded interface name, it will fail in some situations. Service Discovery Some folks want to identify the Wi-Fi interface so that they can run a custom service discovery protocol over it. Before you do that, I strongly recommend that you look at Bonjour. This has a bunch of advantages: It’s an industry standard [1]. It’s going to be more efficient on the ‘wire’. You don’t have to implement it yourself, you can just call an API [2]. For information about the APIs available, see TN3151 Choosing the right networking API. If you must implement your own service discovery protocol, don’t think in terms of finding the Wi-Fi interface. Rather, write your code to work with all Wi-Fi interfaces, or perhaps even all Ethernet-like interfaces. That’s what Apple’s Bonjour implementation does, and it means that things will work in odd situations [3]. To find all Wi-Fi interfaces, get the interface list and filter it for ones with the Wi-Fi functional type. To find all broadcast-capable interfaces, get the interface list and filter it for interfaces with the IFF_BROADCAST flag set. If the service you’re trying to discover only supports IPv4, filter out any IPv6-only interfaces. For advice on how to do this, see Interface List and Network Interface Type in Network Interface APIs. When working with multiple interfaces, it’s generally a good idea to create a socket per interface and then bind that socket to the interface. That ensures that, when you send a packet, it’ll definitely go out the interface you expect. For more information on how to implement broadcasts correctly, see Broadcasts and Multicasts, Hints and Tips. [1] Bonjour is an Apple term for: RFC 3927 Dynamic Configuration of IPv4 Link-Local Addresses RFC 6762 Multicast DNS RFC 6763 DNS-Based Service Discovery [2] That’s true even on non-Apple platforms. It’s even true on most embedded platforms. If you’re talking to a Wi-Fi accessory, see Working with a Wi-Fi Accessory. [3] Even if the service you’re trying to discover can only be found on Wi-Fi, it’s possible for a user to have their iPhone on an Ethernet that’s bridged to a Wi-Fi. Why on earth would they do that? Well, security, of course. Some organisations forbid their staff from using Wi-Fi. Logging and Diagnostics Some folks want to log the IP address of the Wi-Fi interface, or the WWAN, or both for diagnostic purposes. This is quite feasible, with the only caveat being there may be multiple interfaces of each type. To find all interfaces of a particular type, get the interface list and filter it for interfaces with that functional type. See Interface List and Network Interface Type in Network Interface APIs. Interface for an Outgoing Connection There are situations where you need to get the interface used by a particular connection. A classic example of that is FTP. When you set up a transfer in FTP, you start with a control connection to the FTP server. You then open a listener and send its IP address and port to the FTP server over your control connection. What IP address should you use? There’s an easy answer here: Use the local IP address for the control connection. That’s the one that the server is most likely to be able to connect to. To get the local address of a connection: In Network framework, first get the currentPath property and then get its localEndpoint property. In BSD Sockets, use getsockname. See its man page for details. Now, this isn’t a particularly realistic example. Most folks don’t use FTP these days [1] but, even if they do, they use FTP passive mode, which avoids the need for this technique. However, this sort of thing still does come up in practice. I recently encountered two different variants of the same problem: One developer was implementing VoIP software and needed to pass the devices IP address to their VoIP stack. The best IP address to use was the local IP address of their control connection to the VoIP server. A different developer was upgrading the firmware of an accessory. They do this by starting a server within their app and sending a command to the accessory to download the firmware from that server. Again, the best IP address to use is the local address of the control connection. [1] See the discussion in TN3151 Choosing the right networking API. Listening for Connections If you’re listening for incoming network connections, you don’t need to bind to a specific address. Rather, listen on all local addresses. In Network framework, this is the default for NWListener. In BSD Sockets, set the address to INADDR_ANY (IPv4) or in6addr_any (IPv6). If you only want to listen on a specific interface, don’t try to bind to that interface’s IP address. If you do that, things will go wrong if the interface’s IP address changes. Rather, bind to the interface itself: In Network framework, set either the requiredInterfaceType property or the requiredInterface property on the NWParameters you use to create your NWListener. In BSD Sockets, set the IP_BOUND_IF (IPv4) or IPV6_BOUND_IF (IPv6) socket option. How do you work out what interface to use? The standard technique is to get the interface list and filter it for interfaces with the desired functional type. See Interface List and Network Interface Type in Network Interface APIs. Remember that their may be multiple interfaces of a given type. If you’re using BSD Sockets, where you can only bind to a single interface, you’ll need to create multiple listeners, one for each interface. Listener UI Some apps have an embedded network server and they want to populate a UI with information on how to connect to that server. This is a surprisingly tricky task to do correctly. For the details, see Showing Connection Information for a Local Server. Outgoing Connections In some situations you might want to force an outgoing connection to run over a specific interface. There are four common cases here: Set the local address of a connection [1]. Force a connection to run over a specific interface. Force a connection to run over a type of interface. Force a connection to run over an interface with specific characteristics. For example, you want to download some large resource without exhausting the user’s cellular data allowance. The last case should be the most common — see the Constraints section of Network Interface Techniques — but all four are useful in specific circumstances. The following sections explain how to tackle these tasks in the most common networking APIs. [1] This implicitly forces the connection to use the interface with that address. For an explanation as to why, see the discussion of scoped routing in Network Interface Techniques. Network Framework Network framework has good support for all of these cases. Set one or more of the following properties on the NWParameters object you use to create your NWConnection: requiredLocalEndpoint property requiredInterface property prohibitedInterfaces property requiredInterfaceType property prohibitedInterfaceTypes property prohibitConstrainedPaths property prohibitExpensivePaths property Foundation URL Loading System URLSession has fewer options than Network framework but they work in a similar way: Set one or more of the following properties on the URLSessionConfiguration object you use to create your session: allowsCellularAccess property allowsConstrainedNetworkAccess property allowsExpensiveNetworkAccess property Note While these session configuration properties are also available on URLRequest, it’s better to configure this on the session. There’s no option that forces a connection to run over a specific interface. In most cases you don’t need this — it’s better to use the allowsConstrainedNetworkAccess and allowsExpensiveNetworkAccess properties — but there are some situations where that’s necessary. For advice on this front, see Running an HTTP Request over WWAN. BSD Sockets BSD Sockets has very few options in this space. One thing that’s easy and obvious is setting the local address of a connection: Do that by passing the address to bind. Alternatively, to force a connection to run over a specific interface, set the IP_BOUND_IF (IPv4) or IPV6_BOUND_IF (IPv6) socket options. Revision History 2025-01-21 Added a link to Broadcasts and Multicasts, Hints and Tips. Made other minor editorial changes. 2023-07-18 First posted.
0
0
2.5k
Jan ’25
Deployment Target for iOS app running on a Mac with Apple Silicon
Currently, I am working on an iOS app with a Deployment Target set to iOS 15.0, and macOS 12.0. The app is allowed to run on Macs with Apple Silicon. A customer with a Mac running macOS Monterey (12) is complaining that in the TestFlight app, they cannot install the app since it shows "Requires OS Update", even though the deployment target is smaller than the installed version of macOS 12. Are there any specifications available on which macOS version is required in order to use iOS apps on Silicon Macs?
2
0
434
Jan ’25
Does the Apple Store support variable recurring payments like Stripe?
Stripe offers variable payment structures, also known as "irregular recurring payments," which include: Usage-based billing: Charges amounts based on usage during the billing cycle (e.g., minutes used or energy consumed). Quantity-based billing: Charges a pre-agreed amount based on quantity (e.g., number of users in a subscription). Is it possible to implement this type of billing in the Apple Store for apps? How would variations in amounts be handled?
0
0
361
Jan ’25
Text Completion Not Working - Macbook Pro M4 Pro
Since updating to M4 Pro MBP running MacOS 15.2 and now 15.3 beta, predictive text and auto completion does not show in any apps on my computer. This all worked on previous M3 Pro MBP. Predictive text/auto completion is not working in any Microsoft apps either, and my settings are missing certain elements that my wife's M3 MBP show in Outlook. Any help would be appreciated.
0
0
271
Jan ’25
watchOS Standalone App Notification Settings Not Appearing
I'm having an issue on my standalone watchOS app where the settings to adjust notifications does not appear anywhere on the iPhone or the Watch. I have successfully requested notifications access from the user and have successfully displayed a local notification to them. However, if the user ever decides to revoke my notification access (or if they deny originally and want to change), the settings pane for notifications does not appear anywhere. I've looked in the following places: On the watch in Settings > Notifications, however it looks like you can no longer edit per app notification settings directly on the watch (none of the installed apps on my watch appear in here). The only options are settings like "tap to show full notification" and "announce notifications" which affect all notifications (Why not? Especially for apps that don't have a iPhone companion app?). On the iPhone in the Watch app (the app you set up your watch in), in Watch > Notification. My app does not appear anywhere in there. On the iPhone in the iPhone Settings app, in Settings > Notifications. My app does not appear anywhere in there. On the iPhone in the iPhone Settings app, in Settings > Apps. My app does not appear anywhere in there I've tried: Adding capabilities in Signing & Capabilities for Push Notification, Time-Sensitive Notifications and Communication Notifications Building the app for release instead of debug My app also requires location access and has successfully appeared in the settings pane directly on the watch in Settings > Privacy & Security > Location Services, however notification settings do not appear anywhere. I have created a stripped down test app to try and that also does not work. This test code successfully asks the user for permission and (from a button in ContentView), successfully schedules a notification and displays it to the user when they're not in the app. Here's the code for my NotificationManager: import UserNotifications class NotificationManager: NSObject, ObservableObject, UNUserNotificationCenterDelegate { static let shared = NotificationManager() @Published var hasAuthorisation = false private override init() { super.init() UNUserNotificationCenter.current().delegate = self requestAuthorisation() } func requestAuthorisation() { UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { authorised, error in DispatchQueue.main.async { if let error = error { print("Error requesting notifications: \(error.localizedDescription)") } self.hasAuthorisation = authorised } } } func scheduleNotification(title: String, body: String, timeInterval: TimeInterval) { let content = UNMutableNotificationContent() content.title = title content.body = body content.sound = .default let trigger = UNTimeIntervalNotificationTrigger(timeInterval: timeInterval, repeats: false) let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger) UNUserNotificationCenter.current().add(request) { error in if let error = error { print("Error scheduling notification: \(error.localizedDescription)") } else { print("Notification scheduled successfully.") } } } } This issue has persisted across two iPhones (recently upgraded) and the watch was wiped when connecting to the new iPhone. Am I missing some code? Am I missing some flag I need to set in my project somewhere? Please can someone with an Apple Watch try this code in a standalone watchOS app and see if the notifications pane appears anywhere for them? I've contacted Apple DTS, but they're taking a while to respond.
1
0
353
Jan ’25
How to Archive iMessages via API with User Authorization Workflow?
I’m working on a solution to archive iMessages by using an API or similar mechanism. Here’s the desired workflow: The user provides their phone number to initiate the archiving process. They receive a text message with a URL link. Clicking on the link authorizes the archiving of their iMessages. Once authorized, their text messages are archived. So far, I’ve researched third-party services and APIs but haven’t found any that offer this capability directly for iMessages. Questions: Are there any APIs or frameworks (Apple or third-party) that support accessing and archiving iMessages programmatically?
0
0
448
Jan ’25
MapKit UseAnnotation
using the UseAnnotation in the map content does not show the blue user location. I added the info.plist info. Error message: CLLocationManager(<CLLocationManager: 0x300e60d40>) for <MKCoreLocationProvider: 0x303e0e6d0> did fail with error: Error Domain=kCLErrorDomain Code=1 "(null)"
0
0
334
Jan ’25
CTCellularDatash kCTCellularDataNotRestricted -1009
Hello, we are processing the first network permission request transaction on iOS. We have found that when the CTCellularData is in the kCTCellularDataNotRestricted state and we attempt to perform a network access in the callback function, an exception is reported. How can we resolve this issue? I’ve seen that some solutions on the internet suggest adding a delay of 1 second. Are there any other methods?
1
0
218
Jan ’25
NESMVPNSession disconnected
Hi, I have a problem with my OpenVPN connection on my app with iOS 14.4. I perform my VPN configuration from an oven file, with a NETunnelProviderManager protocol, but when I perform the startVPNTunnel, it starts connecting and immediately disconnects. The error I see in the logs is the following: NESMVPNSession[Primary Tunnel:OpenVPN Client: -----(null)]: status changed to disconnected, last stop reason Plugin was disabled This happens to me when running my app on a physical iPad. Regards import NetworkExtension import OpenVPNAdapter class VPNConnection {          var connectionStatus = "Disconnected"              var myProviderManager: NETunnelProviderManager?          func manageConnectionChanges( manager:NETunnelProviderManager ) - String {         NSLog("Waiting for changes");         var status = "Disconnected"                  NotificationCenter.default.addObserver(forName: NSNotification.Name.NEVPNStatusDidChange, object: manager.connection, queue: OperationQueue.main, using: { notification in                          let baseText = "VPN Status is "                          switch manager.connection.status {             case .connected:                 status = "Connected"             case .connecting:                 status = "Connecting"             case .disconnected:                 status = "Disconnected"             case .disconnecting:                 status = "Disconnecting"             case .invalid:                 status = "Invalid"             case .reasserting:                 status = "Reasserting"             default:                 status = "Connected"             }                          self.connectionStatus = status                          NSLog(baseText+status)                      });         return status     }          func createProtocolConfiguration() - NETunnelProviderProtocol {         guard             let configurationFileURL = Bundle.main.url(forResource: "app-vpn", withExtension: "ovpn"),             let configurationFileContent = try? Data(contentsOf: configurationFileURL)         else {             fatalError()         }                  let tunnelProtocol = NETunnelProviderProtocol()         tunnelProtocol.serverAddress = ""         tunnelProtocol.providerBundleIdentifier = "com.app.ios"                  tunnelProtocol.providerConfiguration = ["ovpn": String(data: configurationFileContent, encoding: .utf8)! as Any]         tunnelProtocol.disconnectOnSleep = false                  return tunnelProtocol     }          func startConnection(completion:@escaping () - Void){         self.myProviderManager?.loadFromPreferences(completionHandler: { (error) in             guard error == nil else {                 // Handle an occurred error                 return             }                          do {                 try self.myProviderManager?.connection.startVPNTunnel()                 print("Tunnel started")             } catch {                 fatalError()             }         })     }          func loadProviderManager(completion:@escaping () - Void) {                           NETunnelProviderManager.loadAllFromPreferences { (managers, error) in             guard error == nil else {                 fatalError()                 return             }                          self.myProviderManager = managers?.first ?? NETunnelProviderManager()             self.manageConnectionChanges(manager: self.myProviderManager!)                          self.myProviderManager?.loadFromPreferences(completionHandler: { (error) in                 guard error == nil else {                     fatalError()                     return                 }                                  let tunnelProtocol = self.createProtocolConfiguration()                                  self.myProviderManager?.protocolConfiguration = tunnelProtocol                 self.myProviderManager?.localizedDescription = "OpenVPN Client Ubic"                                  self.myProviderManager?.isEnabled = true                                  self.myProviderManager?.isOnDemandEnabled = false                                  self.myProviderManager?.saveToPreferences(completionHandler: { (error) in                     if error != nil  {                         // Handle an occurred error                         fatalError()                     }                     self.startConnection {                         print("VPN loaded")                     }                 })             })         }     } }
14
0
3.2k
Jan ’25
SMJobSubmit works in user domain, but cannot be submitted in system domain
Hi, I'm in the process of creating an App + Helper Tool combo application, and depending on the necessity of root privileges, I'm setting up two paths in the app: If root privileges are not necessary, I'm using SMJobSubmit rather directly: var submissionError: Unmanaged<CFError>? let submissionResult = SMJobSubmit(kSMDomainUserLaunchd, plist, nil, &submissionError) where plist contains these items: Label=com.***.redactedApp.redacted, ProgramArguments=[path/to/helper-tool, commandName, commandArg1, commandArg2] RunAtLoad=1, KeepAlive=0 and it works as necessary, and performs the operations. Now, in the case of privilege escalation being necessary, this call becomes a bit more complex: let authorization = SFAuthorization() var authRef: AuthorizationRef? do { try authorization?.obtain(withRight: kSMRightModifySystemDaemons, flags: [.extendRights, .interactionAllowed]) authRef = authorization?.authorizationRef() } catch let error { // Logging error } var submissionError: Unmanaged<CFError>? let submissionResult = SMJobSubmit(kSMDomainSystemLaunchd, plist, authRef, &submissionError) while using the same plist, same executable at the same path, same Label. However, when using the second path, suddenly SMJobSubmit fails: Error Domain=CFErrorDomainLaunchd Code=2 "(null)" Now, naturally I headed over to system logs in Console.app, and this is the weirdest - there is nothing suspicious near the log item I submit with the above error from the main application. The tool is embedded in the Contents/MacOS folder. However, my problem is that anything that I can think of seems to lead to the same thought: it should be a problem in both cases, not just the privileged one. Is there something extra that must be taken care of when using SMJobSubmit with privileged helper tools?
6
0
728
Jan ’25
"InvalidProviderToken" with APN push service when using code-generated token
Problem We have successfully set up push notifications using Apple APN service, that is push notifications work when using a token generated using the JSON Web Token Generator in the Push Notification console. However, we get an "InvalidProviderToken" error when creating using our own token using the following code. The Key and TeamID is definitely correct (obviously, censored in the below code). When pasting our token in the JSON Web Token Validator in the Push Notification console we get the error „Invalid signing key“. We merely pasted our secret key in our setNewTokenIfNeeded code, separated on four lines using the “““ style. Does anyone know why this error happens? Given that it works when we upload our .p8 file to the JSON Web Token Generator and we simply paste the text of this file (excluding the lines with "-----BEGIN/END PRIVATE KEY-----") I guess our secret key is correct? Code to generate token fileprivate var currentToken: String? fileprivate var currentTokenCreateTime: Date? fileprivate func setNewTokenIfNeeded() { // Ensure, token is at least 20 minutes but at most 60 minutes old if let currentTokenCreateTime = currentTokenCreateTime { let ageOfTokenInSeconds = abs(Int(currentTokenCreateTime.timeIntervalSinceNow)) NSLog("Age of token: \(Int(ageOfTokenInSeconds / 60)) minutes.") if ageOfTokenInSeconds <= 20 * 60 { return } } // Generate new token NSLog("Renewing token.") let secret = """ ABCABCABCABCABCABCABCABCABCABCABCABC+ABCABC+ABCABCABC+ABCABCAB/+ ABCABCABCABCABCABCABCABCABCABCABCABC+ABCABC+ABCABCABC+ABCABCAB/+ ABCABCABCABCABCABCABCABCABCABCABCABC+ABCABC+ABCABCABC+ABCABCAB/+ ABCABCAB """ let privateKey = SymmetricKey(data: Data(secret.utf8)) let headerJSONData = try! JSONEncoder().encode(Header()) let headerBase64String = headerJSONData.urlSafeBase64EncodedString() let payloadJSONData = try! JSONEncoder().encode(Payload()) let payloadBase64String = payloadJSONData.urlSafeBase64EncodedString() let toSign = Data((headerBase64String + "." + payloadBase64String).utf8) let signature = HMAC<SHA256>.authenticationCode(for: toSign, using: privateKey) let signatureBase64String = Data(signature).urlSafeBase64EncodedString() let token = [headerBase64String, payloadBase64String, signatureBase64String].joined(separator: ".") currentToken = token currentTokenCreateTime = Date() } fileprivate struct Header: Encodable { let alg = "ES256" let kid: String = "ABCABCABC" // Key (censored here) } fileprivate struct Payload: Encodable { let iss: String = "ABCABCABC" // Team-ID (censored here) let iat: Int = Int(Date().timeIntervalSince1970) } extension Data { func urlSafeBase64EncodedString() -> String { return base64EncodedString() .replacingOccurrences(of: "+", with: "-") .replacingOccurrences(of: "/", with: "_") .replacingOccurrences(of: "=", with: "") } } Code to send the push notification func SendPushNotification(category: ConversationCategory, conversationID: UUID, title: String, subTitle: String?, body: String, devicesToSendTo: [String]) { // Für alle Felder s. https://developer.apple.com/documentation/usernotifications/generating-a-remote-notification let payload = [ "aps": [ "alert": [ "title": title, "subtitle" : subTitle ?? "", "body": body ], "category" : category.rawValue, "mutable-content": 1 ], "conversationID": conversationID.uuidString ] as [String : Any] // Ggf. Token setzen setNewTokenIfNeeded() guard let currentToken = currentToken else { NSLog("Token not initialized.") return } NSLog(currentToken) // Notification an alle angegebenen Devices schicken let bundleID = "com.TEAMID.APPNAME" for curDeviceID in devicesToSendTo { NSLog("Sending push notification to device with ID \(curDeviceID).") let apnServerURL = "https://api.sandbox.push.apple.com:443/3/device/\(curDeviceID)" var request = URLRequest(url: URL(string: apnServerURL)!) request.httpMethod = "POST" request.allHTTPHeaderFields = [ "authorization": "bearer " + currentToken, "apns-id": UUID().uuidString, "apns-topic": bundleID, "apns-priority": "10", "apns-expiration": "0" ] request.httpBody = try! JSONSerialization.data(withJSONObject: payload, options: .prettyPrinted) URLSession(configuration: .ephemeral).dataTask(with: request) { data, response, error in if let error = error { NSLog(error.localizedDescription) } if let data = data { NSLog(String(data: data, encoding: .utf8)!) } }.resume() } } On a similar note, some people seem to encounter this error when using the prettyPrinted option for the JSON serialization (i.e., in request.httpBody = try! JSONSerialization.data(withJSONObject: payload, options: .prettyPrinted). Could this be the culprit, given our secret key contains „/„ and „+“? Many thanks!
0
0
510
Jan ’25
Identify Apple Watch with non-Apple BLE
We would like to be able to distinguish between iPhones and Apple Watches when scanning for devices using a Laird BLE module. We know that we can identify an Apple device from the manufacturer data returned in the scan report. 0x004C is the registered identifier for Apple. In the remaining data returned is it possible identify the device type? We note that empirically, 4C001005 seems to correlate to an Apple Watch. How reliable is this? It is useful for us, because it means we do not need to connect to this device to see if it is advertising a service that we own. Connecting over BLE is of course an expensive operation. Here is a simple snippet of a Swift App doing a similar thing, to illustrate the question: func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { guard let manufData: Data = advertisementData[CBAdvertisementDataManufacturerDataKey] as? Data else { return } let hexEncodedManufData: String = manufData.map { String(format: "%02hhx", $0) }.joined() print("Manufacturer Data: \(hexEncodedManufData): ") // Manufacturer Data: 4c001007351ff9f9036238: Apple device // Manufacturer Data: 4c001006331ec0640f88: Apple device // Manufacturer Data: 4c0010052b18804eb1: Apple watch? // Manufacturer Data: 4c0010052b18804eb1: Apple watch? }
1
0
358
Jan ’25
App Clip works in TestFlight but not elsewhere
My app is available in TestFlight but has been rejected in App Review with the review feedback that the app clip "just shows a blank screen". However, in the TestFlight app, the App Clip works as expected and brings up the clip. It also works correctly from Xcode testing. Any ideas on what the problem could be? It is using the default App Clip link (appclip.apple.com)
0
0
327
Jan ’25
What are causes of networkURLUnauthorized in a message filter extension
I'm getting ILMessageFilterError.networkURLUnauthorized returned in a message filter extension when calling deferQueryRequestToServer(). Googling for people who have had the same error, they didn't include the associated domain in the containing app. However I have added that. The server is set up at https://something.com:443, it has an apple association file located at https://something.com:443/.well-known/apple-app-site-association I have added associated domains to the app and the app extension of: messagefilter:something.com?mode=developer webcredentials:something.com?mode=developer Side question 1: are both needed or just the messagefilter? Side question 2: should the domain include the port :443? The server isn't publicly hosted hence I've appended ?mode=developer on the end as per the documentation. The extension's info.plist has ILMessageFilterExtensionNetworkURL added as something.com Question 3: Does this need the port adding too? With everything set up according to the documentation, apart from the questions above, what might be the cause of getting networkURLUnauthorized returned?
3
0
318
Jan ’25
Credit card ICC Public Key Certificate retrieval
Hello! I have a requirement to read the ICC Public Key Certificate from an EMV credit card to implement a payment validation flow. Aa far as I understand, I can't use Core NFC for that task since it is not supposed to be used for reading sensitive credit card data and it might be rejected by Apple. I'm trying to use Tap To Pay as it seems to offer some general card details. Since Apple's documentation on this side is pretty limited, I'm struggling to understand what is a PaymentCardReader.Token and how can I create one? Can anyone please help me with setting up Tap to Pay?
2
0
548
Jan ’25
How can I programmatically access the NETunnelProviderManager of a Per-App VPN?
I have an iOS app which contains a Network Extension that subclasses the NEPacketTunnelProvider, acting as a packet-tunnel VPN. After deploying the app on the device as a regular app, it runs the following code fragment: NETunnelProviderManager.loadAllFromPreferences { managers, _ in self.manager = managers?.first ?? NETunnelProviderManager() self.manager.protocolConfiguration = getConfiguration() self.manager.saveToPreferences { error in // Handle errors or show a "Connect" button in the UI } } This asks the user to install the extension as a "Device VPN". I can then use try? self.manager?.connection.startVPNTunnel() to start the VPN (and later stop it when needed). So far, this works fine. Now, I want to deploy the app with an MDM and set it up as the "custom VPN" of a "Per-App VPN". I have tested the setup using a real MDM, AND using the "development" setup described in NETunnelProviderManager. In both cases, the "Per-App VPN" shows up as a VPN in the "Settings" app. However, in both cases I am unable to retrieve, configure or use the "Per-App VPN". The code fragment posted above returns no NETunnelProviderManager at all. When instantiating one on my own and triggering self.manager.saveToPreferences(), it queries the user to install a "Device VPN". While I can control and use the latter, this is clearly not what I want after having gone through the pain of installing the "Per-App VPN". How can I retrieve the NETunnelProviderManager of the "Per-App VPN"? And then use it to configure and control the VPN connection? (Ideally, I would like to use the same app and the same Network Extension for both use cases, leaving the choice of which VPN type to use to the user or the user's MDM administrator.)
6
0
334
Jan ’25