I'm developing an iOS app that utilizes Universal Links and ASWebAuthenticationSession to deep-link from a website to the app itself. This implementation adheres to the recommendations outlined in RFC 8252, ensuring that the app opening the ASWebAuthenticationSession is the same app that is launched via the Universal Link.
Problem:
While most users can successfully launch the app via Universal Links,a few percent of users experience instances where the app fails to launch, and the user is redirected to the browser.
What I've Tried:
ASWebAuthenticationSession Configuration: I've double-checked the configuration of callbackURLScheme and presentationContextProvider.
Universal Links: Verified the apple-app-site-association file and associated domains entitlement.
Network Conditions: Tested on various network environments (Wi-Fi, cellular) and devices.
Questions:
What are the potential causes for this behavior?
Has anyone else encountered a similar issue and found a solution?
Are there any debugging techniques or ways to generate more detailed logs?
I haven't been able to determine which device or OS version is causing this problem.
Thank you.
General
RSS for tagPrioritize 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
Activity
I am trying to setup remote Java debugging between two machines running macOS (15.6 and 26).
I am able to get the Java program to listen on a socket. However, I can connect to that socket only from the same machine, not from another machine on my local network. I use nc to test the connection. It reports Connection refused when trying to connect from the other machine.
This issue sounds like it could be caused by the Java program lacking Local Network system permission. I am familiar with that issue arising when a program attempts to connect to a port on the local network. In that case, a dialog is displayed and System Settings can be used to grant Local Network permission to the client program. I don't know whether the same permission is required on the program that is receiving client requests. If it is, then I don't know how to grant that permission. There is no dialog, and System Settings does not provide any obvious way to grant permission to a program that I specify.
Note that a Java application is a program run by the java command, not a bundled application. The java command contains a hard-wired Info.plist which, annoyingly, requests permission to use the microphone, but not Local Network access.
I’m using a custom Installer plug-in (InstallerPane) to collect sensitive user input (username/password) during install. After the payload is laid down, I need to send those values to a newly installed agent (LaunchAgent) to persist them.
What I tried
I expose an XPC Mach service from the agent and have the plug-in call it.
On the agent side I validate the XPC client using the audit token → SecCodeCopyGuestWithAttributes → SecCodeCheckValidity.
However, the client process is InstallerRemotePluginService-* (Apple’s view service that hosts all plug-ins), so the signature I see is Apple’s, not mine. I can’t distinguish which plug-in made the call.
Any suggestion on better approach ?
I am new to swift development, and it's possible that I'm missing something fundamental/obvious. If so, I apologize in advance. My team is developing an application for iPadOS using SwiftUI, and I'm trying to accomplish something similar to what the original inquirer is asking for in this thread: https://developer.apple.com/forums/thread/725152. The only difference is that I'm trying to use a PIV smart card to achieve authentication to a server rather than digitally sign a document.
Unfortunately, I'm getting stuck when attempting to run the list() function provided in the accepted answer to the post mentioned above. When attempting to call SecItemCopyMatching(), I'm getting a -34018 missing entitlement error. I've attempted to add the com.apple.token to my app's keychain-access-groups entitlements, but this does not resolve the issue. I have checked the entitlements in my built app, per the recommendation in the troubleshooting guide here: https://developer.apple.com/forums/thread/114456. The entitlement for com.apple.token is indeed present in the plist. Based on other documentation I've read, however, it seems that the explicit declaration of com.apple.token should not even be required in the entitlements.
Is there something obvious that I'm missing here that would prevent my app from accessing the token access group?
I have a binary executable which needs to be given Accessibility Permissions so it can inject keypresses and mouse moves. This was always possible up to macOS 15 - when the first keypress arrived the Accessibility Permissions window would open and allow me to add the executable. However this no longer works in macOS 26: the window still opens, I navigate to the executable file and select it but it doesn't appear in the list. No error message appears.
I'm guessing that this may be due to some tightening of security in Tahoe but I need to figure out what to change with my executable to allow it to work.
While working with Platform SSO on macOS, I’m trying to better understand how the system handles cases where a user’s local account password becomes unsynchronized with their Identity Provider (IdP) password—for example, when the device is offline during a password change.
My assumption is that macOS may store some form of persistent token during the Platform SSO user registration process (such as a certificate or similar credential), and that this token could allow the system to unlock the user’s login keychain even if the local password no longer matches the IdP password.
I’m hoping to get clarification on the following:
Does macOS actually use a persistent token to unlock the login keychain when the local account password is out of sync with the IdP password? If so, how is that mechanism designed to work?
If such a capability exists, is it something developers can leverage to enable a true passwordless authentication experience at the login window and lock screen (i.e., avoiding the need for a local password fallback)?
I’m trying to confirm what macOS officially supports so I can understand whether passwordless login is achievable using the persistent-token approach.
Thanks in advance for any clarification.
I have filed bug reports on this to no avail, so I am bringing it up here hoping someone at Apple will address this. Since the first beta of 26.3, with voice control enabled there are now two icons in the menu bar (*plus an orange dot in full screen) that never go away. That orange microphone isn't serving its intended purpose to notify me that something is accessing my microphone if it is always displayed. I use voice control extensively, so it is nearly always on. In every prior version of macOS, the orange icon was not on for voice control. Even if voice control is not listening but simply enabled in system settings, the orange icon will be there. And there is no need for this icon to be on for a system service that is always listening. This orange icon in the menu bar at all times is incredibly irritating, as it takes up valuable space to the right of the notch, and causes other actual useful menu bar items to be hidden. As well, if some other application on my system were to turn on the mic and start recording me I would never know since that orange icon is always on. It also places an orange dot next to the control center icon taking up even more of the precious little menu bar real estate. Please fix this! Either exempt voice control (as Siri is always listening and it doesn't get the orange icon) or exempt all system services, or give me a way to turn this off. If you cannot tell, I find this incredibly annoying and frustrating.
Topic:
Privacy & Security
SubTopic:
General
I’m implementing a custom Authorization right with the following rule:
<key>authenticate-user</key>
<true/>
<key>allow-root</key>
<true/>
<key>class</key>
<string>user</string>
<key>group</key>
<string>admin</string>
The currently logged-in user is a standard user, and I’ve created a hidden admin account, e.g. _hiddenadmin, which has UID≠0 but belongs to the admin group.
From my Authorization Plug-in, I would like to programmatically satisfy this right using _hiddenadmin’s credentials, even though _hiddenadmin is not the logged-in user.
My question:
Is there a way to programmatically satisfy an authenticate-user right from an Authorization Plug-in using credentials of another (non-session) user?
FB18383742
Setup
🛠️ Xcode 16.4 (16F6)
📱 iPhone 13 mini (iOS 18.0.1)
⌚️ Apple Watch Series 10 (watchOS 11.3.1)
Observations
As AccessorySetupKit does not request "Core Bluetooth permissions", when a watchOS companion app is installed after having installed the iOS app, the toggle in the watch settings for Privacy & Security > Bluetooth is turned off and disabled
After removing the iPhone associated with the Apple Watch, Bluetooth works as expected in the watchOS app
Upon reinstalling the iOS app, there's a toggle for Bluetooth in the iOS ASK app's settings and the ASK picker cannot be presented 🤨
From ASK Documentation:
AccessorySetupKit is available for iOS and iPadOS. The accessory’s Bluetooth permission doesn’t sync to a companion watchOS app.
But this doesn't address not being able to use Core Bluetooth in a watch companion app at all 🥲
Reproducing the bug
Install the iOS + watchOS apps
Launch iOS app, tap "start scan", observe devices can be discovered (project is set up to find heart rate monitors)
Launch watchOS, tap allow on Bluetooth permission pop-up
watchOS app crashes 💥
Meanwhile, in the iOS app, there should be a log entry for 💗 CBCentralManager state: poweredOff and the ASK picker is no longer able to discover any devices
The state of the device permissions:
iOS app has no paired accessories or Bluetooth permission
watchOS app's Bluetooth permission shown as turned off & disabled
Remove the iOS app
Relaunch the watchOS app
Notice the CBCentralManager state is unauthorized
Remove and reinstall the watchOS app
Tap allow on Bluetooth permission pop-up
watchOS app does not crash and CBCentralManager state is poweredOn
The state of the watch permissions:
Bluetooth is turned on & the toggle is not disabled
Note that at this time the iOS app is not installed, there is no way to remove Bluetooth permission for the watch app.
Reinstall + launch the iOS app
Notice a warning in the log:
[##### WARNING #####] App has companion watch app that maybe affected if using CoreBluetooth framework. Please read developer documentation for AccessorySetupKit.
Notice a log entry for 💗 CBCentralManager state: poweredOn before tapping start scan
Tap start scan and observe another log entry:
Failed to show picker due to: The operation couldn’t be completed. (ASErrorDomain error 550.)
ASErrorDomain 550:
The picker can't be used because the app is in the background.
Is this the expected error? 🤔
The state of the iOS permissions:
The app's settings show a Bluetooth toggle normally associated with Core Bluetooth, but the app never showed a Core Bluetooth pop-up
The iOS ASK app now has Core Bluetooth permission 😵💫
Following up with Apple
This is a known bug that should be fixed in watchOS 26 when Bluetooth permissions for watch apps can be set independently of the iOS app. I've yet to test it with watchOS 26.
See repo for the same post with screenshots of the settings and demo code reproducing the bug:
https://github.com/superturboryan/AccessorySetupKit-CoreBluetooth-watchOS-Demo
Hi, my app is receiving all keyboard events through Input Monitoring preference. It completely stopped to work on macOS 15 Sequoia and I have no idea why. Where can I read what has been changed in Input Monitoring? Thanks!
Topic:
Privacy & Security
SubTopic:
General
I'm trying to export and re-import a P-256 private key that was originally generated via SecKeyCreateRandomKey(), but I keep running into roadblocks. The key is simply exported via SecItemExport() with format formatWrappedPKCS8, and I did set a password just to be sure.
Do note that I must use the file-based keychain, as the data protection keychain requires a restricted entitlement and I'm not going to pay a yearly fee just to securely store some private keys for a personal project. The 7-day limit for unsigned/self-signed binaries isn't feasible either.
Here's pretty much everything I could think of trying:
Simply using SecItemImport() does import the key, but I cannot set kSecAttrLabel and more importantly: kSecAttrApplicationTag. There just isn't any way to pass these attributes upfront, so it's always imported as Imported Private Key with an empty comment. Keys don't support many attributes to begin with and I need something that's unique to my program but shared across all the relevant key entries, otherwise it's impossible to query for only my program's keys. kSecAttrLabel is already used for something else and is always unique, which really only leaves kSecAttrApplicationTag. I've already accepted that this can be changed via Keychain Access, as this attribute should end up as the entry's comment. At least, that's how it works with SecKeyCreateRandomKey() and SecItemCopyMatching(). I'm trying to get that same behaviour for imports.
Running SecItemUpdate() afterwards to set these 2 attributes doesn't work either, as now the kSecAttrApplicationTag is suddenly used for the entry's label instead of the comment. Even setting kSecAttrComment (just to be certain) doesn't change the comment. I think kSecAttrApplicationTag might be a creation-time attribute only, and since SecItemImport() already created a SecKey I will never be able to set this. It likely falls back to updating the label because it needs to target something that is still mutable?
Using SecItemImport() with a nil keychain (i.e. create a transient key), then persisting that with SecItemAdd() via kSecValueRef does allow me to set the 2 attributes, but now the ACL is lost. Or more precise: the ACL does seem to exist as any OS prompts do show the label I originally set for the ACL, but in Keychain Access it shows as Allow all applications to access this item. I'm looking to enable Confirm before allowing access and add my own program to the Always allow access by these applications list. Private keys outright being open to all programs is of course not acceptable, and I can indeed access them from other programs without any prompts.
Changing the ACL via SecKeychainItemSetAccess() after SecItemAdd() doesn't seem to do anything. It apparently succeeds but nothing changes. I also reopened Keychain Access to make sure it's not a UI "caching" issue.
Creating a transient key first, then getting the raw key via SecKeyCopyExternalRepresentation() and passing that to SecItemAdd() via kSecValueData results in The specified attribute does not exist. This error only disappears if I remove almost all of the attributes. I can pass only kSecValueData, kSecClass and kSecAttrApplicationTag, but then I get The specified item already exists in the keychain errors. I found a doc that explains what determines uniqueness, so here are the rest of the attributes I'm using for SecItemAdd():
kSecClass: not mentioned as part of the primary key but still required, otherwise you'll get One or more parameters passed to a function were not valid.
kSecAttrLabel: needed for my use case and not part of the primary key either, but as I said this results in The specified attribute does not exist.
kSecAttrApplicationLabel: The specified attribute does not exist. As I understand it this should be the SHA1 hash of the public key, passed as Data. Just omitting it would certainly be an option if the other attributes actually worked, but right now I'm passing it to try and construct a truly unique primary key.
kSecAttrApplicationTag: The specified item already exists in the keychain.
kSecAttrKeySizeInBits: The specified attribute does not exist.
kSecAttrEffectiveKeySize: The specified attribute does not exist.
kSecAttrKeyClass: The specified attribute does not exist.
kSecAttrKeyType: The specified attribute does not exist.
It looks like only kSecAttrApplicationTag is accepted, but still ignored for the primary key. Even entering something that is guaranteed to be unique still results in The specified item already exists in the keychain, so I think might actually be targeting literally any key. I decided to create a completely new keychain and import it there (which does succeed), but the key is completely broken. There's no Kind and Usage at the top of Keychain Access and the table view just below it shows symmetric key instead of private. The kSecAttrApplicationTag I'm passing is still being used as the label instead of the comment and there's no ACL. I can't even delete this key because Keychain Access complains that A missing value was detected. It seems like the key doesn't really contain anything unique for its primary key, so it will always match any existing key.
Using SecKeyCreateWithData() and then using that key as the kSecValueRef for SecItemAdd() results in A required entitlement isn't present. I also have to add kSecUseDataProtectionKeychain: false to SecItemAdd() (even though that should already be the default) but then I get The specified item is no longer valid. It may have been deleted from the keychain. This occurs even if I decrypt the PKCS8 manually instead of via SecItemImport(), so it's at least not like it's detecting the transient key somehow. No combination of kSecAttrIsPermanent, kSecUseDataProtectionKeychain and kSecUseKeychain on either SecKeyCreateWithData() or SecItemAdd() changes anything.
I also tried PKCS12 despite that it always expects an "identity" (key + cert), while I only have (and need) a private key. Exporting as formatPKCS12 and importing it with itemTypeAggregate (or itemTypeUnknown) does import the key, and now it's only missing the kSecAttrApplicationTag as the original label is automatically included in the PKCS12. The outItems parameter contains an empty list though, which sort of makes sense because I'm not importing a full "identity". I can at least target the key by kSecAttrLabel for SecItemUpdate(), but any attempt to update the comment once again changes the label so it's not really any better than before.
SecPKCS12Import() doesn't even import anything at all, even though it does return errSecSuccess while also passing kSecImportExportKeychain explicitly.
Is there literally no way?
We are interested in using a hardware-bound key in a launch daemon. In a previous post, Quinn explicitly told me this is not possible to use an SE keypair outside of the system context and my reading of the Apple documentation also supports that.
That said, we have gotten the following key-creation and persistence flow to work, so we have some questions as to how this fits in with the above.
(1) In a launch daemon (running thus as root), we do:
let key = SecureEnclave.P256.Signing.PrivateKey()
(2) We then use
key.dataRepresentation
to store a reference to the key in the system keychain as a kSecClassGenericPassword.
(3) When we want to use the key, we fetch the data representation from system keychain and we "rehydrate" the key using:
SecureEnclave.P256.Signing.PrivateKey(dataRepresentation: data)
(4) We then use the output of the above to sign whatever we want.
My questions:
in the above flow, are we actually getting a hardware-bound key from the Secure Enclave or is this working because it's actually defaulting to a non-hardware-backed key?
if it is an SE key, is it that the Apple documentation stating that you can only use the SE with the Data Protection Keychain in the user context is outdated (or wrong)?
does the above work, but is not an approach sanctioned by Apple?
Any feedback on this would be greatly appreciated.
In some crashlog files, there are additional pieces of information related to codesigning.
I can understand what most of themcorresponds to (ID, TeamID, Flags, Validation Category). But there is one I have some doubt about: Trust Level.
As far as I can tell (or at least what Google and other search engines say), this is an unsigned 32 bit integer that defines the trust level with -1 being untrusted, 0, being basically an Apple executable and other potential bigger values corresponding to App Store binaries, Developer ID signature, etc.
Yet, I'm not able to find a corresponding detailed documentation about this on Apple's developer website.
I also had a look at the LightweightCodeRequirements "include" file and there does not seem to be such a field available.
[Q] Is there any official documentation listing the different values for this trust level value and providing a clear description of what it corresponds to?
Hi,
I have a certificate, how can I display the certificate content in my Mac app just like Keychain Access app does. Can I popup the certificate content dialog just like Keychain Access app?
Since Sun 15th Jun 04:30 (UTC+7) we received lots of following error that causes our device test failure. Could Apple please investigate further?
#############################
Operations could not be completed. (com.apple.devicecheck.error error 4.) (serverUnavailable)
I work for Brave, a browser with ~80M users. We want to introduce a new system for automatic updates called Omaha 4 (O4). It's the same system that powers automatic updates in Chrome.
O4 runs as a separate application on users' systems. For Chrome, this works as follows: An app called GoogleUpdater.app regularly checks for updates in the background. When a new version is found, then GoogleUpdater.app installs it into Chrome's installation directory /Applications/Google Chrome.app.
But consider what this means: A separate application, GoogleUpdater.app, is able to modify Google Chrome.app.
This is especially surprising because, for example, the built-in Terminal.app is not able to modify Google Chrome.app. Here's how you can check this for yourself:
(Re-)install Chrome with its DMG installer.
Run the following command in Terminal: mkdir /Applications/Google\ Chrome.app/test. This works.
Undo the command: rm -rf /Applications/Google\ Chrome.app/test
Start Chrome and close it again.
mkdir /Applications/Google\ Chrome.app/test now fails with "Operation not permitted".
(These steps assume that Terminal does not have Full Disk Access and System Integrity Protection is enabled.)
In other words, once Chrome was started at least once, another application (Terminal in this case) is no longer allowed to modify it.
But at the same time, GoogleUpdater.app is able to modify Chrome. It regularly applies updates to the browser. For each update, this process begins with an mkdir call similarly to the one shown above.
How is this possible? What is it in macOS that lets GoogleUpdater.app modify Chrome, but not another app such as Terminal? Note that Terminal is not sandboxed.
I've checked that it's not related to codesigning or notarization issues. In our case, the main application (Brave) and the updater (BraveUpdater) are signed and notarized with the same certificate and have equivalent requirements, entitlements and provisioning profiles as Chrome and GoogleUpdater.
The error that shows up in the Console for the disallowed mkdir call is:
kernel (Sandbox)
System Policy: mkdir(8917) deny(1) file-write-create /Applications/Google Chrome.app/foo
(It's a similar error when BraveUpdater tries to install a new version into /Applications/Brave Browser.app.)
The error goes away when I disable System Integrity Protection. But of course, we cannot ask users to do that.
Any help would be greatly appreciated.
Hi everyone,
I’ve been working on storing keys and passwords in the macOS Keychain using the Keychain Services API. Specifically, I’m leveraging SecAccessControlCreateWithFlags to bind items to access control flags, and overall, it’s been working smoothly.
I have a question regarding the .applicationPassword flag of SecAccessControlCreateWithFlags. While it successfully prompts the user to input a password, there are no apparent password rules, even a simple “1” is accepted.
My questions are:
Is there a way to enforce strong password requirements when using the .applicationPassword flag?
If enforcing strong passwords isn’t possible, is there an alternative approach to provide a predefined strong password during the creation process, bypassing the need for user input?
With SecAccessControlCreateWithFlags, I noticed the item isn’t stored in the traditional file-based Keychain but in an iOS-style Keychain, is there a way to store it in a file-based Keychain while marking it as unexportable?
I appreciate any insights or suggestions.
Thank you!
Neil
Why can’t sandboxed mac app store apps have full disk access available in the system settings for full disk access?
I discovered mac app store apps in release mode cannot access the ai auggie command line program and other command line programs like opengrep on your system. Debug builds fine.
I came up with a workaround: Since I have an ssh client built in for connecting to remote servers, why not connect to ssh on the same local machine… Ask the user for their username and password in a popup.
To do this, you have to enable remote login on your mac in system settings -> sharing.
In addition you must grant full disk access to cli ssh in system settings: add /usr/libexec/sshd-keygen-wrapper
It all works, but I don’t see the cli program in mac settings. To remove the cli program you must run a command line program to remove all full disk access support from all apps. No way to just undo ssh.
So my question is, even though I got CodeFrog all working for a mac app store release, should I not do it because it’s insecure or too complicated with the system settings? Should I instead sell the app off the store like Panic Nova?
Need some advice. I have not implemented in app purchases yet. Should I just have a reality check and sell the app off the store, or try for app store approval?
Bummer…
Maybe I’m ahead of my time, but perhaps Apple could review the source code for apps requesting full disk access and make sure there’s nothing fraudulent in them. Then, developer tools app store apps could be in the store with the user’s assurance that nothing is happening behind the scenes that is scary.
From: https://blog.greenrobot.com/2025/11/10/i-have-a-decision-to-make/
Related post:
https://developer.apple.com/forums/thread/806187
I submitted a code level tech support question for this. They directed me here.
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.
We are facing an issue with Keychain sharing across our apps after our Team ID was updated. Below are the steps we have already tried and the current observations:
Steps we have performed so far:
After our Team ID changed, we opened and re-saved all the provisioning profiles.
We created a Keychain Access Group: xxxx.net.soti.mobicontrol (net.soti.mobicontrol is one bundle id of one of the app) and added it to the entitlements of all related apps.
We are saving and reading certificates using this access group only. Below is a sample code snippet we are using for the query:
[genericPasswordQuery setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];
[genericPasswordQuery setObject:identifier forKey:(id)kSecAttrGeneric];
[genericPasswordQuery setObject:accessGroup forKey:(id)kSecAttrAccessGroup];
[genericPasswordQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
[genericPasswordQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes];
Issues we are facing:
Keychain items are not being shared consistently across apps.
We receive different errors at different times:
Sometimes errSecDuplicateItem (-25299), even when there is no item in the Keychain.
Sometimes it works in a debug build but fails in Ad Hoc / TestFlight builds.
The behavior is inconsistent and unpredictable.
Expectation / Clarification Needed from Apple:
Are we missing any additional configuration steps after the Team ID update?
Is there a known issue with Keychain Access Groups not working correctly in certain build types (Debug vs AdHoc/TestFlight)?
Guidance on why we are intermittently getting -25299 and how to properly reset/re-add items in the Keychain.
Any additional entitlement / provisioning profile configuration that we should double-check.
Request you to please raise a support ticket with Apple Developer Technical Support including the above details, so that we can get guidance on the correct setup and resolve this issue.