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
NEHotspotConfiguration
NEHotspotHS20Settings
NEHotspotEAPSettings
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.