home-assistant / home-assistant/iOS
Cannot get credentials for non-HA Thread networks that are not marked as the 'preferred' network in user's iCloud Keychain
- Dominant language
- Swift
- Stars
- 2.4k
- Forks
- 520
- Avg merge
- 7h 27m
- Merged PRs (30d)
- 264
Description
**Home Assistant Core Version**
2025.9.4
**Describe the bug**
When the user taps _send credentials to Home Assistant_ on the Thread configuration page, the app calls `retrieveAllCredentials()`, which makes two calls to the ThreadNetwork library:
- Gets the credentials for the user's preferred Thread network by calling [(THClient).preferredCredentials()](https://github.com/home-assistant/iOS/blob/da40045cccc202485f932da35c50c9db4286a309/Sources/Shared/Services/ThreadClientService.swift#L18).
- Gets credentials for all other Thread networks by calling [(THClient).allCredentials()](https://github.com/home-assistant/iOS/blob/da40045cccc202485f932da35c50c9db4286a309/Sources/Shared/Services/ThreadClientService.swift#L22).
Unfortunately, this does not retrieve all credentials as the name suggests. While one would think that calling `allCredentials()` would return all credentials, the [documentation for the method](https://developer.apple.com/documentation/threadnetwork/thclient/retrieveallcredentials(_:)/) says:
> When calling this method, you receive credentials for your team ID only.
In other words, it's only getting credentials for Thread networks that were originally created and stored by the app (or by any other app by the same developer). If the user has a Thread network outside of Home Assistant that they'd like the credentials for, and that network is not marked as the preferred Thread network in their iCloud keychain, Home Assistant iOS will not be able to get those credentials.
**Suggested Solutions**
Change [(THClient).allCredentials()](https://github.com/home-assistant/iOS/blob/da40045cccc202485f932da35c50c9db4286a309/Sources/Shared/Services/ThreadClientService.swift#L22) to [(THClient).allActiveCredentials()](https://developer.apple.com/documentation/threadnetwork/thclient/retrieveallactivecredentials(_:)). This bumps the minimum iOS version for functions used in that file from 15.0 to 16.4. I'm not sure if that's a problem or not. I believe the credentials returned by `allActiveCredentials()` will include the credentials for the preferred network, so the call to `preferredCredentials()` becomes redundant and should be removed to avoid prompting the user for access to thread credentials twice in a row.
Additionally, you could allow users to get credentials on a network-by-network basis using [(THClient).credentials(forBorderAgentID)](https://developer.apple.com/documentation/threadnetwork/thclient/retrievecredentials(forborderagent:completion:)) or [(THClient).credentials(forExtendedPANID)](https://developer.apple.com/documentation/threadnetwork/thclient/retrievecredentials(forextendedpanid:completion:)).
I was able to validate the issue and test my theory on the root cause by signing up for an Apple Developer account and building / running a modified version of the app that would request credentials specifically for the PAN ID of the Thread network I was missing credentials for:
```diff
+ let bytes: [UInt8] = [0xf3, 0x48, 0xb6, 0x10, 0xed, 0x8b, 0x45, 0x0c]
+ let panID: Data = Data(bytes)
+
// Thre preferred credential call is necessary as it triggers a permission dialog
- let preferredCredential = try await client.preferredCredentials()
+ let preferredCredential = try await client.credentials(forExtendedPANID: panID)
```
**To Reproduce**
1. Store Thread network credentials using an app that isn't Home Assistant for iOS. Make sure that network is not marked as preferred.
2. Open Home Assistant iOS, go to the Settings -> Companion App -> Debug -> Thread, and allow it to retrieve thread network credentials.
3. The credentials created in step 1 will not be included in the output.
**Expected behavior**
Tapping on _send credentials to Home Assistant_ sends all credentials to Home Assistant.
**Screenshots**
Here is a screenshot of my Thread configuration page, showing two Thread networks:
- **MyHome1307316849** is the network of an old Apple Home device that I upgraded away from and no longer own. Unbeknownst to me, It happens to be set as my 'preferred' Thread network in my iCloud Keychain. After searching extensively and even resetting my Apple Home, this unused network remains my preferred Thread network.
- **MyHome672859431** is the name of the actual running network, the one I'm trying to get credentials for.

Contributor guide
Assessment
This issue has not been assessed yet.