iOS icon indicating copy to clipboard operation
iOS copied to clipboard

Cannot get credentials for non-HA Thread networks that are not marked as the 'preferred' network in user's iCloud Keychain

Open teekennedy opened this issue 3 months ago • 3 comments

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:

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 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() to (THClient).allActiveCredentials(). 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) or (THClient).credentials(forExtendedPANID).

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:

+       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.

Image

teekennedy avatar Sep 22 '25 02:09 teekennedy

Reading your report, it looks like a bug that should be reported to Apple no?

Have you validated this as well?

Change (THClient).allCredentials() to (THClient).allActiveCredentials()

bgoncal avatar Sep 22 '25 11:09 bgoncal

@bgoncal My understanding based on reading the documentation is that allCredentials() is working as intended by Apple. It is definitely poorly named though.

No I have not tested allActiveCredentials() but I can do so if you'd like.

teekennedy avatar Sep 22 '25 18:09 teekennedy

It would help me a lot if you could validate so, thanks in advance.

But something that I disagree with you (if I understood correctly) is that, the current implementation CAN fetch the credentials from apple home thread network (from your homepods etc), what I am not certain is regarding third parties, like Aqara, that I think doesnt work on the current implementation.

bgoncal avatar Sep 22 '25 18:09 bgoncal