Usage
All four verbs are async. connect() and disconnect() can throw a
WiDASError; status() never does.
Configure
Create one WiDAS instance and hold onto it wherever your app keeps long-lived services. It ships no
secret, so there's nothing sensitive to protect here.
import WiDAS
let widas = WiDAS(
clientId: "client-acme",
keychainAccessGroup: "<TeamID>.com.apple.networkextensionsharing"
)
| Parameter | Required | Notes |
|---|---|---|
clientId | ✅ | Your Wi-DAS-issued public client identifier. |
keychainAccessGroup | recommended | Shared group so the NetworkExtension can pair the client identity. nil uses the app default. |
Connect
connect() is idempotent. Call it on launch, and again after any expired or revoked status.
requestedValidity is an ISO-8601 duration; Wi-DAS clamps it to policy.
do {
let result = try await widas.connect(user: "user-42", requestedValidity: "P365D")
print("Onboarded. Serial \(result.serial), expires \(result.notAfter)")
} catch let error as WiDASError {
handle(error) // see Error handling
}
ConnectionResult carries the certificate serial and its notAfter expiry.
The first connect() on a device registers a fresh App Attest key; every later call asserts the one
it already has. You don't manage that split. You always just call connect(user:…).
Status
status() is advisory and never throws, so it's safe to call whenever you're rendering UI.
let status = await widas.status()
switch status.state {
case .none:
promptToConnect() // nothing installed yet
case .valid:
showConnected(expiry: status.expiry)
case .expired, .revoked:
try? await widas.connect(user: "user-42", requestedValidity: "P365D") // re-onboard
}
Status gives you state (.none/.valid/.expired/.revoked), the serial, and the expiry.
Remember the network is the real authority here; status() is for the UI.
Disconnect
Remove the installed profile when the user asks, or after a revoked result.
try await widas.disconnect()
The attested App Attest key sticks around, so a later connect() takes the fast assertion path.
A complete launch flow
func onLaunch(userID: String) async {
do {
// Idempotent: first run, renewal or recovery — one call.
_ = try await widas.connect(user: userID, requestedValidity: "P365D")
} catch WiDASError.attestationUnavailable {
showUnsupported() // e.g. Simulator, or App Attest unsupported
} catch let error as WiDASError {
handle(error)
} catch {
// Cancellation / unexpected.
}
render(await widas.status()) // reflect real state in the UI
}
connect() does key generation, attestation, and network I/O. Run it from a background task and
update your UI on the main actor once you have the result.
Next: Error handling.