Problem with accessing keychain after update

Hi, I have an existing Mac app that stores some important values in the keychain. I am working on an update for the app, which was working fine while I was testing with debug builds. But when I build the app for Release and test the update using TestFlight, on trying to access the keychain item, I get prompted by the system:

"MyApp wants to use your confidential information stored in "SyncSettingsValue" in your keychain"

And the user now has to enter their password and click on "Allow", "Always Allow" or Deny. Obviously this is a really bad experience, and clicking on Deny will stop many features for the user.

Why is this happening? I've updated the app 100s of times before and I've never had this problem. I don't believe I'm messing around with any certificate or provisioning profile since the last update, which was only a few weeks ago.

How do I find out what is causing the problem here? Or is this a TestFlight issue that won't happen to users when they update through the App Store?

Replies

That specific alert is raised by the file-based keychain. See TN3137 On Mac keychain APIs and implementations for a definition of that term.

The file-based keychain uses your app’s designated requirement (DR) to enforce access control. See TN3127 Inside Code Signing: Requirements for an explanation of that.

TestFlight had a bug that was causing this all the time. See this thread for the details. AFAIK that’s been fixed.

How are you testing this? You can get into problems if you run an Apple Development signed version of your app and then switch to a TestFlight (or Developer ID) signed version. I recommend that you:

  1. Set up a fresh context. Ideally this should be a fresh machine, either real or virtual, but in this case a new user account should do fine.

  2. Delete your app.

  3. Install it from the App Store.

  4. Do something that saves a keychain item.

  5. Now install your TestFlight version.

  6. Do something that access the keychain item from step 4.

I don’t think you’ll hit the alert in this case, but please do post back if you see anything wonky.


Regardless of the above, I recommend that you move to the data protection keychain. As I explained in TN3137, it’s the future of keychain on the Mac. It also has a much easier to understand access control mechanism (-:

Share and Enjoy

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

Thank you for the detailed response! So I have recreated this on 3 different systems ... my own, a macOS Sonoma partition, plus my spouse's machine. In each case, I downloaded the app from the App Store (so in Release configuration), then wrote something to the keychain, then downloaded the updated app through TestFlight (again, Release configuration) and tried to access the same item. I do use the file-based keychain, since I haven't been using the kSecUseDataProtectionKeychain. In fact, part of the update is to first read the values without the Data Protection flag, and then save it again with the flag so that it can use the data protection keychain.

Can you check if the TestFlight fix is still in place, or it was it overwritten? I'm using TestFlight 3.3.0, on macOS 13.4.

Should I expect to run into this if I use a Developer-ID signed app (just to test if it was indeed a TestFlight issue)?

I've ran the 'codesign -d -r -' tool on both the App Store and the TestFlight builds, and there's some difference there that I don't understand:

App Store:

Executable=/Applications/Contacts Journal CRM.app/Contents/MacOS/Contacts Journal CRM designated => (anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists / or anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] / exists / and certificate leaf[field.1.2.840.113635.100.6.1.13] / exists */ and certificate leaf[subject.OU] = <teamID>) and identifier "com.zaal.cjournalmac"

TestFlight:

Executable=/Applications/Contacts Journal CRM.app/Contents/MacOS/Contacts Journal CRM designated => anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.25.1] /* exists */ and identifier "com.zaal.cjournalmac"

Is this expected / unrelated to the problem, Or is there something to this that might explain the issue I'm having?

I also filed a feedback with the sysdiagnose attached: FB12482242

Can you check if the TestFlight fix is still in place … ?

No. I don’t have that level of access.

I've ran the codesign -d -r - tool on both the App Store and the TestFlight builds, and there's some difference there that I don't understand

This is much easier to understand if you apply the formatting and abbreviations I outline in TN3127. Your current build looks like this:

(
    anchor apple generic and LeafIsMacAppStore
    or anchor apple generic and IssuerIsDeveloperID 
        and LeafIsDeveloperIDApp 
        and certificate leaf[subject.OU] = <teamID>
)
and identifier "com.zaal.cjournalmac"

and your TestFlight build looks like this:

anchor apple generic
and certificate leaf[field.1.2.840.113635.100.6.1.25.1]
and identifier "com.zaal.cjournalmac"

The 1.2.840.113635.100.6.1.25.1 OID is not listed in TN3127 but according to section 4.11.15 of the Worldwide Developer Relations Certification Practice Statement, which you can download from the Apple PKI page, it’s associated with TestFlight.

So, yeah, the above all kinda makes sense.

I also filed a feedback with the sysdiagnose attached: FB12482242

Good. I think that’s the best path forward here.

Share and Enjoy

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

A couple of weeks in, and no one has replied to the Feedback I filed. I know there's no guarantees when filing these, but it really puts the brakes on any progress I can make with my development.

Some more findings:

  • after running into this issue with the TestFlight build, I create a Developer-ID (notarized) copy of the app, export it and save it in Applications (overwriting the TestFlight build). When I run this, I don't get any prompts, and it runs as expected.

  • if I run the app from Xcode with the debugger (using Mac Developer identity), I do run into the same prompts, but that's probably because the code signing is very different between a debug build and an App Store / DeveloperID build.

So it just looks like a TestFlight issue to me. But I can't really properly confirm it myself, and I'm a bit hesitant to test it out by releasing the update on the App Store, because it would lead to a lot of problems and confusion for my users if it ended up prompting them to enter in their credentials.

Your feedback here would be really valuable.

A couple of weeks in, and no one has replied to the Feedback I filed.

Indeed. Your bug seems to have gotta little lost in our system. I’m hoping it’ll be back on track soon.

When I run [the Developer ID version], I don't get any prompts, and it runs as expected.

Right. I explain the mechanics of this in gory detail in TN3127 Inside Code Signing: Requirements.

So it just looks like a TestFlight issue to me.

Yep.

I'm a bit hesitant to test it out by releasing the update on the App Store, because it would lead to a lot of problems and confusion for my users if it ended up prompting them to enter in their credentials.

Understood.

I believe you can get some assurance on this front by using promo codes. So, something along the lines of:

  1. Approve the app for distribution but set the release date far in the future.

  2. Generate a promo code for that version.

  3. Redeeming that code will then install that version.

However, App Store Connect isn’t really my forte, so I recommend that you do your own research before committing to that path.

Share and Enjoy

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

Hi Quinn, Thank you for the feedback! Since my app is already in the App Store, and this is happening on an update, this isn't the option for me. But I'm planning to release it now with as 'phased update' so that it rolls out slowly, and I can directly check against my own App Store installations once it rolls out. In case there's a problem I can pause the update, that'll give me 30 days to come up with another solution. Not the best way to move forward, but I do strongly believe that this is just a TestFlight issue so it hopefully shouldn't be a problem.

I'll update the thread when I get the update approved and tested.

Thanks!