Access to Shared iOS Keychain with WatchOS

Hi,

I'm crurently unable to access my app keychain after a long search these are the steps that I've tryed so far

First of All I'm running on "real" devices not in simulators


1. Key chain is enabled for a group, in here I will go for this group "appbundle.sharedkeychain" and the app prefix I'll say that's "1A2B3C4D5E"

2. The keychain code is currently implemented on a Framework

3. The Framework is a Pod that I've downloaded and tweaked so that worked with a shared keychain witch so far I was unable to.


So I created a variable called kSAAGroup witch contains the following string "1A2B3C4D5E.appbundle.sharedkeychain"

In the addKeychainFunction I have the following code


private func addKeychainItem(withAttributes attributes: [String: AnyObject]) throws -> Data {
    var mutableAttributes = attributes
    mutableAttributes[kSecClass as String] = kSecClassGenericPassword
    mutableAttributes[kSecReturnPersistentRef as String] = kCFBooleanTrue
    mutableAttributes[kSecAttrSynchronizable as String] = kCFBooleanTrue
    mutableAttributes[kSecAttrAccessible as String] = kSecAttrAccessibleAlways
    mutableAttributes[kSecAttrAccessGroup as String] = kSAAGroup as AnyObject?
    /
    /
    if mutableAttributes[kSecAttrAccount as String] == nil {
        mutableAttributes[kSecAttrAccount as String] = UUID().uuidString as NSString
    }
    var result: AnyObject?
    let resultCode: OSStatus = withUnsafeMutablePointer(to: &result) {
        SecItemAdd(mutableAttributes as CFDictionary, $0)
    }
    guard resultCode == errSecSuccess else {
        throw Keychain.Error.systemError(resultCode)
    }
    guard let persistentRef = result as? Data else {
        throw Keychain.Error.incorrectReturnType
    }
    return persistentRef
}


And to retrieve all the keychain items

private func allKeychainItems() throws -> [NSDictionary] {
    let queryDict: [String : AnyObject] = [
        kSecClass as String:                kSecClassGenericPassword,
        kSecMatchLimit as String:           kSecMatchLimitAll,
        kSecReturnPersistentRef as String:  kCFBooleanTrue,
        kSecReturnAttributes as String:     kCFBooleanTrue,
        kSecReturnData as String:           kCFBooleanTrue,
        kSecAttrSynchronizable as String:   kCFBooleanTrue,
        kSecAttrAccessible as String: kSecAttrAccessibleAlways,
        kSecAttrAccessGroup as String: kSAAGroup as AnyObject,
    ]
    var result: AnyObject?
    let resultCode = withUnsafeMutablePointer(to: &result) {
        SecItemCopyMatching(queryDict as CFDictionary, $0)
    }
    if resultCode == errSecItemNotFound {
        /
        return []
    }
    guard resultCode == errSecSuccess else {
        throw Keychain.Error.systemError(resultCode)
    }
    guard let keychainItems = result as? [NSDictionary] else {
        throw Keychain.Error.incorrectReturnType
    }
    return keychainItems
}


I add the item to the keychain on the iPhone and if I close the app and reopen all the items are still there, so I assume everything it's working on the local level, I can add, delete, update and fetch all items.


Now on the watchOS I get nothing, as if the keychain is empty.


Any ideas?

Historically it was possible to share a keychain access group between your phone app and your watch extension because they both ran on the same device (the phone). This is no longer the case. Modern versions of watchOS run your watch extension on the watch, which is a different device from the phone app (the phone), and there’s no keychain access group sharing between devices.

One option here is to push your keychain items up to iCloud Keychain via the

kSecAttrSynchronizable
option.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

As you can see I have this line in there

kSecAttrSynchronizable as String:   kCFBooleanTrue,


Witch means that should be syncronizable, but still nothing, do I have to add something in the entitlements file?

As you can see I have this line in there …

Ah, yes, sorry I missed that.

Do you have iCloud Keychain turned on?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

On my phone, Yes

On my phone, Yes

OK. I’m at a loss as to why this doesn’t work. I recommend that you open a DTS tech support incident so you can talk to DTS’s keychain expert.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks for your help.

I will do what you sugested

I was attempting to do the same thing. And I think that iCloud Synchronizing could do that. However according to these Apple Docs, in the notes under the Storing Data Securely in the Keychain.

NOTE


The kSecAttrSynchronizable key is not available in watchOS.

Without that, the WatchOS can't get the keychain data you've stored over on the iOS side.

So I don't believe that's possible at this time. Unless something has changed with `kSecAttrSynchronizable`

Have there been any developments in bringing keychain to watch?

Have there been any developments in bringing keychain to watch?

I don’t know.

If you really need this answered, and no one else chimes in, open a DTS tech support incident so that I can allocate the time to research this properly [1].

Share and Enjoy

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

[1] Since this post, “DTS’s keychain expert” has retired, mean that I’m now handling that technology.

Did anyone get an answer on this? If someone get a DTS is the answer shared anywhere? Would really like to know best practice on this. thx!

Access to Shared iOS Keychain with WatchOS
 
 
Q