Hi All,
We are developing a hybrid MVNO and want to use Wi-Fi Passpoint to enable offload from our users phones when they are in range of our Wi-Fi network.
The user experience of installing a .mobileconfig file is too many steps and a bad user experience which causes low adoption among our users.
Instead, we want to use the NEHotspotConfigurationManager to configure a HS2.0 network using EAP-TLS. We configure these elements using
Our code to execute above is shown below:
func configureProfile(certificate: String, issuingCa: String, caChain: [String], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
#if !targetEnvironment(simulator)
let keychainQuery = [kSecClass as String: kSecClassCertificate] as [String: Any] as CFDictionary
let status = SecItemDelete(keychainQuery)
print("Delete status \(status)")
let url = Bundle.main.url(forResource: "serverCA", withExtension: "crt")!
let caCert = try! String(contentsOf: url)
_ = addCertToChain(caCert, name: "HeliumMobile CaCert")
caChain.enumerated().forEach { idx, ca in
_ = addCertToChain(ca, name: "HeliumMobile Chain \(idx)")
}
let cert = addCertToChain(certificate, name: "HeliumMobile Cert")
let identity = try! SecIdentity.load(certificate: cert!)
let hs20Settings = NEHotspotHS20Settings(domainName: DOMAIN, roamingEnabled: false)
let eapSettings = NEHotspotEAPSettings()
eapSettings.trustedServerNames = ["radius.dev.wifi.\(DOMAIN)", "radius.wifi.\(DOMAIN)"]
eapSettings.isTLSClientCertificateRequired = true
eapSettings.supportedEAPTypes = [13]
eapSettings.preferredTLSVersion = NEHotspotEAPSettings.TLSVersion._1_2
let identitySuccess = eapSettings.setIdentity(identity)
print("Identity set? \(identitySuccess)")
let config = NEHotspotConfiguration(hs20Settings: hs20Settings, eapSettings: eapSettings)
config.hidden = false
NEHotspotConfigurationManager.shared.getConfiguredSSIDs(completionHandler: { ssids in
for ssid in ssids {
// Remove previous wifi configs
NEHotspotConfigurationManager.shared.removeConfiguration(forSSID: ssid)
}
NEHotspotConfigurationManager.shared.apply(config, completionHandler: { error in
if let error = error {
reject("Error", "Failed to install profile", error)
} else {
resolve(true)
}
})
})
#endif
}
Using this method we have a partial success, but there is a noticeable difference in the performance of this method relative to using a similarly (but not exactly) configured .mobileconfig file.
The main issues we see are:
- The phone is sluggish / not eager to join the Wi-Fi network when in coverage. Relative to a device using a .mobileconfig profile for the same network, the App configured phone will take 2-3minutes longer to connect to the network. During this time you can view in logs numerous EAP attempts that fail. The Failure mode appears to be the phone starting to connect, then going silent and ignoring the Wi-Fi AP for a while (1-2min) before starting a new attempt.
- The App configured phone is more prone disconnection from the Wi-Fi network when in stable coverage area. This often coincides with the phone locking the screen and going to sleep. When waking from the sleep, you see the same EAP attempt and failure behavior as stated above.
- UI differences: Using the API there appears to not be a way to configure the "Provider Display Name" which is shown in the Settings -> Wi-Fi SSID list below the SSID string.
- UI differences: SSID is marked as "hidden SSID" in the Settings -> Wi-Fi SSID list. Note this is despite A) The SSID is not hidden, it is advertised in beacon frames B) We have tried explicitly configuring
"config.hidden = false"
- Differing dependencies between API and .mobileconfig: using Apple configurator I can create a .mobileconfig that enables Roaming Partner connections with my MCC/MNCs configured, but having no NAI Realm. However when I try to enable
isRoamingEnabled = true
in the API I get an error saying I must have an NAI Realm. If/when I add an NAI realm, I get further oddity in connection/EAP behavior when using the API.
Thus far, our examination of the API documentation has not revealed any resolution to the items above.
It really feels like the API and .mobileconfig are doing 2 very different things inside the phone.
Does anyone have guidance or suggestions on how to resolve these issues? Or perhaps example code showing the proper usage of the APIs to configure a passpoint network?
Any help SUPER appreciated.
Unfortunately I don’t have any great answers for you here. There are two two stages within NEHotspotConfigurationManager
:
-
Initially,
NEHotspotConfigurationManager
checks the configuration and commits it to the Wi-Fi subsystem. -
After that, the Wi-Fi subsystem treats the configuration like any other configuration.
I have good insight into 1 but not into 2. Wi-Fi management on iOS is complicated, and quite opaque.
My best advice right now is that you file bug reports about this. Specifically, for points 1 and 2:
-
Install the Wi-Fi for iOS debug profile, from our Bug Reporting > Profiles and Logs page.
-
Install your configuration profile.
-
Immediately take a sysdiagnose log.
-
Remove your configuration profile, then run your your and save that configuration.
-
Immediately take a second sysdiagnose log.
-
Try to replicate each of the specific problems you’re seeing and take a sysdiagnose log immediately after that.
-
File you bug and add all your logs to it. Make sure to incline a rough timeline of the steps you took and when you took each log.
For each of points 3 through 5, file separate bug against NEHotspotConfigurationManager
itself.
Please post your bug numbers, just for the record.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"