I am working on improving Keychain item storage secured with Face ID using SecAccessControlCreateWithFlags. The implementation uses the .biometryAny flag as shown below:
SecAccessControlCreateWithFlags(
kCFAllocatorDefault,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
.biometryAny,
&error
)
While this approach generally works as expected, I encountered a specific edge case during testing. On iOS 18.3.1 with Xcode 15.4, the following sequence causes the Keychain item to become inaccessible:
Navigate to Settings > Face ID & Passcode and select Reset Face ID.
Before setting up a new Face ID, tap the Back button to exit the setup process.
Reopen the Face ID setup and complete the enrollment.
Return to the app—previously stored Keychain items protected by .biometryAny are no longer available.
This behavior appears to be a change introduced in recent iOS versions. In versions prior to iOS 15, resetting or deleting Face ID entries did not invalidate existing Keychain items protected by .biometryAny.
This difference in behavior between iOS versions raises questions about the changes to biometric protection handling.
Any suggestions are welcomed that might shine a light on what the best practice to use keychain access control and prevent the data to become unavailable.
Prioritize user privacy and data security in your app. Discuss best practices for data handling, user consent, and security measures to protect user information.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Created
We recently transferred two applications to a different account, both of which utilize Keychain and shared app containers. Before transferring the first application, we anticipated losing access to the Keychain and took proactive measures by backing up data to the app’s private container in the final release prior to the transfer.
During the app transfer process, we removed the shared container group ID from the old account and recreated it under the new account. In our testing, Keychain restoration from the local backup was successful, and users experienced no disruptions. However, after releasing the application, we observed that approximately 25% of our users not only lost their Keychain data as expected but also their shared app container data.
As we have been unable to reproduce this issue internally, we are seeking your guidance on how to prevent a similar situation when transferring our second application. At this stage, we have not yet released any updates from the new account, and the Keychain data remains backed up in the app’s private container.
We would appreciate any insights or recommendations you can provide to ensure a smooth transition for our users and make sure we can keep the data in shared container.
Topic:
Privacy & Security
SubTopic:
General
Hello, I have created an app for both iOs and Android where upon speaking two trigger words, the listening app sends a text and then calls to an inputted designated phone contact. The Android version works perfectly. The iOs version also works perfectly but the iOs app emiits a PopUp for each, the text and then the call asking "Do you really want to send the text -or- make the call". Basically, I input the contact info and I spoke the trigger words. So, yes I want to send the text and make the call. So, I have to click the two PopUps then the device sends and calls.
Is there a way to suppress the PopUps in any way? The app is designed for emergencies. So, a dely to anser a popup is not at all good.
Maybe by telling the device to allow auto calls and texts from my app?
Any and all help on this issue will be very welcomed...
Thanks :)
We have 2 developers:
Developer A created a Bundle ID and configured Sign in with Apple, but didn't create a corresponding App. This Bundle ID is only used for login on our official website.
Developer B created a Bundle ID, configured Sign in with Apple, and has a corresponding App.
The issue we're encountering is that because these two Bundle IDs are under different teams, when using the same Apple ID to log into these two applications, different accounts are generated. (We've tested that when creating Service IDs under the same team, logging in with Bundle IDs under the same team generates the same account.)
Since Developer A's Bundle ID doesn't have a created app, it cannot be transferred to Developer B. Therefore, we'd like to know if there's any way to make the accounts generated from logging in with the same Apple ID be identical across these two teams?
Topic:
Privacy & Security
SubTopic:
General
Tags:
Sign in with Apple REST API
Sign in with Apple
Sign in with Apple JS
Our app uses Face ID to optionally secure access to the app for device owner. This not the new 'Require Face ID' feature of iOS 18 - this is our own custom implementation that has some other related logic for authentication handling.
Starting in iOS 18.3.1, starting the app results in multiple Face Id checks being fired - sometimes just a couple but sometimes many more.
Curiously, this is happening even when I completely disable any code we have that prompts for Face ID. It appears to come from nowhere.
This does not happen on prior iOS 18 releases so, while I might be doing something improper in the code, something specific has changed in iOS 18.3.1 to cause this issue to manifest.
I'm looking for advice as to what could be occurring here, how to debug a Face Id check that appears to come from nowhere, and what, if any, workarounds exist.
An ITMS-91061: Missing privacy manifest rejection email looks as follows:
ITMS-91061: Missing privacy manifest- Your app includes
"<path/to/SDK>", which includes , an SDK that was identified in the documentation as a privacy-impacting third-party SDK. Starting February 12, 2025, if a new app includes a privacy-impacting SDK, or an app update adds a new privacy-impacting SDK, the SDK must include a privacy manifest file. Please contact the provider of the SDK that includes this file to get an updated SDK version with a privacy manifest. For more details about this policy, including a list of SDKs that are required to include signatures and manifests, visit: https://developer.apple.com/support/third-party-SDK-requirements.
Glossary
ITMS-91061: Missing privacy manifest: An email that includes the name and path of privacy-impacting SDK(s) with no privacy manifest files in your app bundle. For more information, see https://developer.apple.com/support/third-party-SDK-requirements.
: The specified privacy-impacting SDK that doesn't include a privacy manifest file.
If you are the developer of the rejected app, gather the name of the SDK from the email you received from Apple, then contact the SDK's provider for an updated version that includes a valid privacy manifest. After receiving an updated version of the SDK, verify the SDK includes a valid privacy manifest file at the expected location. For more information, see Adding a privacy manifest to your app or third-party SDK.
If your app includes a privacy manifest file, make sure the file only describes the privacy practices of your app. Do not add the privacy practices of the SDK to your app's privacy manifest.
If the email lists multiple SDKs, repeat the above process for all of them.
If you are the developer of an SDK listed in the email, publish an updated version of your SDK that includes a privacy manifest file with valid keys and values.
Every privacy-impacting SDK must contain a privacy manifest file that only describes its privacy practices.
To learn how to add a valid privacy manifest to your SDK, see the Additional resources section below.
Additional resources
Privacy manifest files
Describing data use in privacy manifests
Describing use of required reason API
Adding a privacy manifest to your app or third-party SDK
TN3182: Adding privacy tracking keys to your privacy manifest
TN3183: Adding required reason API entries to your privacy manifest
TN3184: Adding data collection details to your privacy manifest
TN3181: Debugging an invalid privacy manifest
Topic:
Privacy & Security
SubTopic:
General
Tags:
App Store Connect
Privacy
App Submission
App Review
Hi everyone,
I’m currently facing an issue while trying to submit an update for my app to the App Store. The review process is blocking the update due to a "Privacy - Data Use and Sharing" warning, stating that our app requests "tracking purchase history for tracking purposes."
However, we have already removed this functionality and deleted the NSUserTrackingUsageDescription key from our latest build. Despite this, the warning persists, and we are unable to proceed with the update.
I have already contacted Apple Support, but in the meantime, I wanted to ask the community:
Has anyone else encountered this issue, and if so, how did you resolve it?
Is there a way to force a refresh of privacy-related settings in App Store Connect?
Are there any additional steps we need to take to completely remove this tracking flag from our app submission?
Any insights or guidance would be greatly appreciated! Thanks in advance for your help.
I have my custom Authplugin implemented at login (system.login.console), and I want to remove password requirement validation/authentication from system.login.console authorization right. Do you see any functionality loss in completely removing password need at login. And is there any reference which can help me here to acheive this?
I have a small command-line app I've been using for years to process files. I have it run by an Automator script, so that I can drop files onto it. It stopped working this morning.
At first, I could still run the app from the command line, without Automator. But then after I recompiled the app, now I cannot even do that. When I run it, it's saying 'zsh: killed' followed by my app's path. What is that?
The app does run if I run it from Xcode.
How do I fix this?
Topic:
Privacy & Security
SubTopic:
General
We are working with an iOS app where we have enabled the “Generate Debug Symbols” setting to true in Xcode. As a result, the .dSYM files are generated and utilized in Firebase Crashlytics for crash reporting.
However, we received a note in our Vulnerability Assessment report indicating a potential security concern. The report mentions that the .ipa file could be reverse-engineered due to the presence of debug symbols, and that such symbols should not be included in a released app. We could not find any security-related information about this flag, “Generate Debug Symbols,” in Apple’s documentation.
Could you please clarify if enabling the “Generate Debug Symbols” flag in Xcode for a production app creates any security vulnerabilities, such as the one described in the report?
The report mentions the following vulnerability: TEST-0219: Testing for Debugging Symbols
The concern raised is that debugging symbols, while useful for crash symbolication, may be leveraged to reverse-engineer the app and should not be present in a production release.
Your prompt confirmation on this matter would be greatly appreciated. Thank you in advance for your assistance.
Our business model is to identify Frauds using our advanced AI/ML model. However, in order to do so we need to collect many device information which seems to be ok according to https://developer.apple.com/app-store/user-privacy-and-data-use/
But it's also prohibited to generate a fingerprint, so I need more clarification here.
Does it mean I can only use the data to identify that a user if either fraud or not but I cannot generate a fingerprint to identify the device?
If so, I can see many SKD in the market that generates Fingerprints like https://fingerprint.com/blog/local-device-fingerprint-ios/
and https://shield.com/?
Topic:
Privacy & Security
SubTopic:
General
Tags:
Analytics & Reporting
DeviceCheck
Device Activity
Privacy
I am experiencing an issue with Apple Sign-In on Vision Pro. When I build and run the app from Xcode, everything works fine—after signing in, the app returns to the foreground as expected.
However, when I launch the app directly on Vision Pro (not from Xcode), after completing the sign-in process, the app does not reopen from the background automatically. Instead, it closes, and I have to manually tap the app icon to reopen it.
Has anyone else encountered this issue? Is there a way to ensure the app properly resumes after sign-in without requiring manual intervention?
Hi,
I develop a Mac application, initially on Catalina/Xcode12, but I recently upgrade to Monterey/Xcode13. I'm about to publish a new version: on Monterey all works as expected, but when I try the app on Sequoia, as a last step before uploading to the App Store, I encountered some weird security issues:
The main symptom is that it's no longer possible to save any file from the app using the Save panel, although the User Select File entitlement is set to Read/Write.
I've tried reinstalling different versions of the app, including the most recent downloaded from TestFlight. But, whatever the version, any try to save using the panel (e.g. on the desktop) results in a warning telling that I don't have authorization to record the file to that folder.
Moreover, when I type spctl -a -t exec -v /Applications/***.app in the terminal, it returns rejected, even when the application has been installed by TestFlight.
An EtreCheck report tells that my app is not signed, while codesign -dv /Applications/***.app returns a valid signature. I'm lost...
It suspect a Gate Keeper problem, but I cannot found any info on the web about how this system could be reset. I tried sudo spctl --reset-default, but it returns This operation is no longer supported...
I wonder if these symptoms depend on how the app is archived and could be propagated to my final users, or just related to a corrupted install of Sequoia on my local machine. My feeling is that a signature problem should have been detected by the archive validation, but how could we be sure?
Any idea would be greatly appreciated, thanks!
I'm working on a Password Manager app that integrates with the AutoFill Credential Provider to provide stored passwords and OTPs to the user within Safari and other apps.
Password AutoFill works perfectly.
I'm unable to get iOS to register that the app supports OTPs though.
I've followed the Apple documentation here: https://developer.apple.com/documentation/authenticationservices/providing-one-time-passcodes-to-autofill and added "ProvidesOneTimeCodes" to the AutoFill extension's Info.plist, but iOS just doesn't seem to notice the OTP support.
<key>ASCredentialProviderExtensionCapabilities</key>
<dict>
<key>ProvidesOneTimeCodes</key>
<true/>
<key>ProvidesPasswords</key>
<true/>
</dict>
Any help would be greatly appreicated!
Topic:
Privacy & Security
SubTopic:
General
Tags:
Extensions
Entitlements
Autofill
Authentication Services
The Passwords App is accessing websites found in the ASCredentialIdentityStore associated with a 3rd Party password management app (SamuraiSafe). This behaviour appears to be associated with looking up website favicons in order to display in Passwords. However the websites contacted are not stored in the Passwords App/iCloud KeyChain - only the 3rd Party password management app (SamuraiSafe). This is effectively leaking website information stored in the 3rd Party password management app.
I first noticed this behaviour on macOS, and it appears to happen every 8 days. Today it was seen on iOS.
The behaviour is revealed through the App Privacy Report on iOS (and LittleSnitch on macOS).
I would not be surprised to see the Passwords App do this for websites saved in the Passwords App/iCloud KeyChain, however I believe it should not be arbitrarily testing every website found in the ASCredentialIdentityStore as reference to that website url should be entirely under the control of the end user.
See attached screenshots from App Privacy Report.
Filed bug with Apple: FB16682423
We are using ASWebAuthenticationSession with apps on IoS to achieve SSO between apps. The IdP for authentication (OIDC) is an on-premise and trusted enterprise IdP based on one of the leading products in the market. Our problem is that the user is prompted for every login (and logouts) with a consent dialogue box:
“AppName” wants to use “internal domain-name” to Sign In
This allows the app and website to share information about you.
Cancel Continue”
I have read in various places that Apple has a concept of “Trusted domains” where you can put an “Apple certified” static web-page on the IdP. This page needs to contain specific metadata that iOS can verify. Once a user logs in successfully a few times, and if the IdP is verified as trusted, subsequent logins would not prompt the consent screen.
Question: I struggle to find Apple documentation on how to go about a process that ends with this “Apple certified web-page” on our IdP”. Anyone who has experience with this process, or who can point me in some direction to find related documentation?
I am developing a custom authorization plugin for macOS, and I’ve encountered an issue where the auth plugin view remains visible on the home screen for a few seconds after login.
Issue Details:
After entering valid credentials, I call setResult(.allow) in my plugin to proceed with login.
The authentication succeeds, and macOS starts transitioning to the home screen.
However, for a few seconds after login, the authorization plugin view is still visible on the home screen before it disappears.
I have observed this issue even when using Apple's sample authorization plugin.
Observation:
This issue occurs without an external monitor (on a single built-in display).
If I manually close the plugin window inside Destroy(AuthPlugin.mechanism), then the auth plugin views do not appear on the home screen, which seems to fix the issue.
However, when I do this, a gray screen appears for about a second before the desktop environment fully loads.
I suspect that the gray screen appears due to the time macOS takes to fully load the home screen environment after login.
Questions:
Why does the authorization plugin view persist on the home screen for a few seconds after login?
Is manually closing the plugin window in Destroy(AuthPlugin.mechanism) the correct way to prevent this, or is there a better approach?
Is my assumption that the gray screen appears due to the home screen not being fully loaded correct?
If the gray screen is caused by home screen loading, is there a system notification or event I can listen to in order to know when the home screen has fully loaded?
Hey there, I used our team's account to configure sign in with Apple, the mode is pop up, my clientId scope redirectUrl state are both correct. I got Failed to verify your identity. Try again., actually my account is valid because I can login to my mac and every apple website. I have tried many apple accounts and still got this error. That was so weird, I didn't find a solution online. Pls help me thanks.
The Core Problem
After Users sign out from the App, the app isn’t properly retrieving the user on second sign in. Instead, it’s treating the user as “Unknown” and saving a new entry in CloudKit and locally. Is there a tutorial aside from 'Juice' that is recent and up to date?
Using personal physical iPhone for simulations. Can't get Keychain to read or store AppleID name/email. I want to avoid hard reseting physical phone.
Logs confirm Keychain is working, but userIdentifier and savedEmail are not being stored correctly.
🔄 Initializing UserManager...
✅ Saved testKeychain to Keychain: Test Value
✅ Retrieved testKeychain from Keychain: Test Value
🔍 Keychain Test - Retrieved Value: Test Value
⚠️ Keychain Retrieve Warning: No stored value found for userIdentifier
⚠️ Keychain Retrieve Warning: No stored value found for savedEmail
🔍 Debug - Retrieved from Keychain: userIdentifier=nil, savedEmail=nil
⚠️ No stored userIdentifier in Keychain. User needs to sign in.
📦 Converting User to CKRecord: Unknown, No Email
✅ User saved locally: Unknown, No Email
✅ User saved to CloudKit: Unknown, No Email
Below UserManager.swift if someone can help troubleshoot. Or step by step tutorial to configure a project and build a User Login & User Account creation for Apple Only app.
import Foundation
import CloudKit
import AuthenticationServices
import SwiftData
@MainActor
class UserManager: ObservableObject {
@Published var user: User?
@Published var isLoggedIn = false
@Published var errorMessage: String?
private let database = CKContainer.default().publicCloudDatabase
init() {
print("🔄 Initializing UserManager...")
// 🔍 Keychain Debug Test
let testKey = "testKeychain"
KeychainHelper.shared.save("Test Value", forKey: testKey)
let retrievedValue = KeychainHelper.shared.retrieve(forKey: testKey)
print("🔍 Keychain Test - Retrieved Value: \(retrievedValue ?? "nil")")
fetchUser() // Continue normal initialization
}
// ✅ Sign in & Save User
func handleSignIn(_ authResults: ASAuthorization) {
guard let appleIDCredential = authResults.credential as? ASAuthorizationAppleIDCredential else {
errorMessage = "Error retrieving Apple credentials"
print("❌ ASAuthorization Error: Invalid credentials received")
return
}
let userIdentifier = appleIDCredential.user
let fullName = appleIDCredential.fullName?.givenName ?? retrieveSavedName()
var email = appleIDCredential.email ?? retrieveSavedEmail()
print("🔍 Apple Sign-In Data: userIdentifier=\(userIdentifier), fullName=\(fullName), email=\(email)")
// 🔄 If Apple doesn't return an email, check if it exists in Keychain
if appleIDCredential.email == nil {
print("⚠️ Apple Sign-In didn't return an email. Retrieving saved email from Keychain.")
}
// ✅ Store userIdentifier & email in Keychain
KeychainHelper.shared.save(userIdentifier, forKey: "userIdentifier")
KeychainHelper.shared.save(email, forKey: "savedEmail")
let newUser = User(fullName: fullName, email: email, userIdentifier: userIdentifier)
saveUserToCloudKit(newUser)
}
func saveUserToCloudKit(_ user: User) {
let record = user.toRecord()
Task {
do {
try await database.save(record)
DispatchQueue.main.async {
self.user = user
self.isLoggedIn = true
self.saveUserLocally(user)
print("✅ User saved to CloudKit: \(user.fullName), \(user.email)")
}
} catch {
DispatchQueue.main.async {
self.errorMessage = "Error saving user: \(error.localizedDescription)"
print("❌ CloudKit Save Error: \(error.localizedDescription)")
}
}
}
}
// ✅ Fetch User from CloudKit
func fetchUser() {
let userIdentifier = KeychainHelper.shared.retrieve(forKey: "userIdentifier")
let savedEmail = KeychainHelper.shared.retrieve(forKey: "savedEmail")
print("🔍 Debug - Retrieved from Keychain: userIdentifier=\(userIdentifier ?? "nil"), savedEmail=\(savedEmail ?? "nil")")
guard let userIdentifier = userIdentifier else {
print("⚠️ No stored userIdentifier in Keychain. User needs to sign in.")
return
}
let predicate = NSPredicate(format: "userIdentifier == %@", userIdentifier)
let query = CKQuery(recordType: "User", predicate: predicate)
Task { [weak self] in
guard let self = self else { return }
do {
let results = try await self.database.records(matching: query, resultsLimit: 1).matchResults
if let (_, result) = results.first {
switch result {
case .success(let record):
DispatchQueue.main.async {
let fetchedUser = User(record: record)
self.user = User(
fullName: fetchedUser.fullName,
email: savedEmail ?? fetchedUser.email,
userIdentifier: userIdentifier
)
self.isLoggedIn = true
self.saveUserLocally(self.user!)
print("✅ User loaded from CloudKit: \(fetchedUser.fullName), \(fetchedUser.email)")
}
case .failure(let error):
DispatchQueue.main.async {
print("❌ Error fetching user from CloudKit: \(error.localizedDescription)")
}
}
}
} catch {
DispatchQueue.main.async {
print("❌ CloudKit fetch error: \(error.localizedDescription)")
}
}
}
}
// ✅ Save User Locally
private func saveUserLocally(_ user: User) {
if let encoded = try? JSONEncoder().encode(user) {
UserDefaults.standard.set(encoded, forKey: "savedUser")
UserDefaults.standard.set(user.fullName, forKey: "savedFullName")
UserDefaults.standard.set(user.email, forKey: "savedEmail")
print("✅ User saved locally: \(user.fullName), \(user.email)")
} else {
print("❌ Local Save Error: Failed to encode user data")
}
}
// ✅ Retrieve Previously Saved Name
private func retrieveSavedName() -> String {
return UserDefaults.standard.string(forKey: "savedFullName") ?? "Unknown"
}
// ✅ Retrieve Previously Saved Email
private func retrieveSavedEmail() -> String {
return KeychainHelper.shared.retrieve(forKey: "savedEmail") ?? UserDefaults.standard.string(forKey: "savedEmail") ?? "No Email"
}
// ✅ Sign Out
func signOut() {
isLoggedIn = false
user = nil
UserDefaults.standard.removeObject(forKey: "savedUser")
print("🚪 Signed Out")
}
}
Topic:
Privacy & Security
SubTopic:
General
Tags:
Sign in with Apple
Authentication Services
iCloud Keychain Verification Codes