Connecting to Wi-Fi programmatically in iOS version(16) with Swift

I want to connect to Wi-Fi programmatically using swift in my iPad application and I want to create according to bellow flow.

  1. Enter the network name programmatically
  2. Set the programmatically "WAP2-Enterprise" for security.
  3. Set username/password.
  4. A certificate popup will appear, so tap "Trust".
  • "Turn on the following information." otherwise off.
  • Automatic connection
  • Restrict IP address tracking
  1. Set the programmatically IPV4 address below.
  • Configure ID: Manual
  • IP address: 192.***.***.***
  • For tablets, ○○: 1 to 20
  • Subnet mask: 255.255.255.0
  • Router: 192.***.***.***
  1. Configure DNS server(Set the programmatically)
  • Manual
  • Add server: 8.8.8.8
  1. HTTP proxy(Set the programmatically)
  • Configure proxy: off

if anyone you can guide me to proper way much a appreciated!!!

Answered by DTS Engineer in 756629022

You can’t pass certificate data directly to setTrustedServerCertificates(_:). It’s docs are pretty clear about this:

An array of SecCertificate objects …

Your app must store the certificates in keychain access group $(TeamIdentifierPrefix)com.apple.networkextensionsharing. The OS uses SecItemCopyMatching(_:_:) to obtain a persistent reference to each certificate from the application’s keychain and uses it during EAP authentication.

Here’s a snippet of code that illustrates this process:

let eap: NEHotspotEAPSettings = …
let cert: SecCertificate = …

try secCall {
    SecItemAdd([
        kSecValueRef: cert,
        kSecAttrAccessGroup: "TTTTTTTTTT.com.apple.networkextensionsharing",
    ] as NSDictionary, nil)
}

let success = eap.setTrustedServerCertificates([cert])

Some notes:

  • Replace TTTTTTTTTT with your Team ID.

  • Make sure that your app is entitled to use the TTTTTTTTTT.com.apple.networkextensionsharing keychain access group.

  • You can find the secCall(…) helpers here.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Accepted Answer

You can join a Wi-Fi network programmatically using NEHotspotConfigurationManager. See TN3111 iOS Wi-Fi API overview for links.

That API does not let you set a manual IP address or DNS server for the configuration that you create. There’s no way to do that programmatically on iOS.

On the DNS front, you can force the system to use a specific DNS server using the DNS Settings API. This is system-wide though, not for that specific interface.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thank you for the reply. I was bale to connect to Wi-Fi network programmatically using NEHotspotConfigurationManager(using SSID and Password).

i would also like to know is there a specific function that we can use to connect to Wi-Fi using (SSID,Password and Certificate) in NEHotspotConfigurationManager?

i would also like to know is there a specific function that we can use to connect to Wi-Fi using (SSID, Password and Certificate) in NEHotspotConfigurationManager?

If certificates are involved then your Wi-Fi network must be using some of EAP. Given that, check out NEHotspotEAPSettings.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

i tried using NEHotspotEAPSettings in the below code and i and getting some errors.

let eapSettings = NEHotspotEAPSettings()
eapSettings.isTLSClientCertificateRequired = true
eapSettings.ttlsInnerAuthenticationType = .eapttlsInnerAuthenticationEAP
eapSettings.supportedEAPTypes = [NEHotspotEAPSettings.EAPType.EAPTLS.rawValue as NSNumber]

guard let certificateURL = Bundle.main.url(forResource: "certificate-name", withExtension: "crt") else {
    print("Certificate file not found.")
    return
}
do {
    let certificateData = try Data(contentsOf: certificateURL)
    eapSettings.setTrustedServerCertificates([certificateData]) //AA
} catch {
    print("Failed to load certificate data:", error.localizedDescription)
    return
}
configuration = NEHotspotConfiguration(ssid: ssidValue, eapSettings: eapSettings) //BB

NEHotspotConfigurationManager.shared.apply(configuration!) { (error) in
    if let error = error {
        print("Failed to connect to WiFi network: \(error.localizedDescription)") 
    } else 
        print("Successfully connected to WiFi network.")
    }
}

Errors:

2023-06-20 17:44:40.079743+0900 [874:203915] [] NEHotspotEAPSettings invalid certificate data type //(comes from AA)
2023-06-20 17:44:40.080467+0900 [874:203915] [] NEHotspotConfiguration identity not provided //(comes from BB)
2023-06-20 17:44:40.080576+0900 [874:203915] [] NEHotspotConfiguration invalid EAP settings. //(comes from BB)
Failed to connect to WiFi network: invalid EAP settings.

i would like to know if there is a specific certificate datatype that needed to use with NEHotspotEAPSettings?

You can’t pass certificate data directly to setTrustedServerCertificates(_:). It’s docs are pretty clear about this:

An array of SecCertificate objects …

Your app must store the certificates in keychain access group $(TeamIdentifierPrefix)com.apple.networkextensionsharing. The OS uses SecItemCopyMatching(_:_:) to obtain a persistent reference to each certificate from the application’s keychain and uses it during EAP authentication.

Here’s a snippet of code that illustrates this process:

let eap: NEHotspotEAPSettings = …
let cert: SecCertificate = …

try secCall {
    SecItemAdd([
        kSecValueRef: cert,
        kSecAttrAccessGroup: "TTTTTTTTTT.com.apple.networkextensionsharing",
    ] as NSDictionary, nil)
}

let success = eap.setTrustedServerCertificates([cert])

Some notes:

  • Replace TTTTTTTTTT with your Team ID.

  • Make sure that your app is entitled to use the TTTTTTTTTT.com.apple.networkextensionsharing keychain access group.

  • You can find the secCall(…) helpers here.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thank you for the reply. I was able to connect using the above flow that motioned. Now i'm trying to handle the error in the code.When i try even OS Dialog showing with "Cannot connect" response return as Success.

https://forums.developer.apple.com/forums/thread/96834?page=2

I read the above thread and what i can understand from that is it's a bug in the os method. So does this problem fixed on latest iOS version? or is there a way to handle this problem? I wrote my error handling code bellow→

NEHotspotConfigurationManager.shared.removeConfiguration(forSSID: self.ssid)
        let hotspotConfiguration = NEHotspotConfiguration(ssid: self.ssid, eapSettings: eapSetting)
        manager.apply(hotspotConfiguration){ (error) in
            if let error = error {
                print("Error")
                return

            } else {                
                print("Success")
                return
            }
        }
I was able to connect using the above flow that motioned.

Cool.

Regarding your new issue, I recommend that you start a new thread for that [1]. Make sure to reference that old thread.

Use the same topic, subtopic, and tags as this thread; that way I’ll see it go by.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Normally I’d suggest you follow up on that old thread, but it’s really old and it’s probably best to start fresh.

Thank you for the quick reply, Yeah previous thread is really old. So i made a new one with same topic, subtopic, and tags.

New thread: https://developer.apple.com/forums/thread/765186

Connecting to Wi-Fi programmatically in iOS version(16) with Swift
 
 
Q