Prioritize user privacy and data security in your app. Discuss best practices for data handling, user consent, and security measures to protect user information.

Posts under General subtopic

Post

Replies

Boosts

Views

Activity

[KeyChain Framework] KeyChain Item is accessible post App Transfer without rebuilding the KeyChain
We have utilised the KeyChain Framework for Adding items into KeyChain. We have Generated KeyPair using 'SecKeyGeneratePair' API as below (OSStatus)generateAssymetricKeyPair:(NSUInteger)bitSize{ OSStatus sanityCheck = noErr; SecKeyRef publicKeyRef = NULL; SecKeyRef privateKeyRef = NULL; NSString *appGrpIdentifier = @"group.com.sample.xyz" // Set the private key attributes. NSDictionary *privateKeyAttr = @{(id)kSecAttrIsPermanent: @YES, (id)kSecAttrApplicationTag: [TAG_ASSYMETRIC_PRIVATE_KEY dataUsingEncoding:NSUTF8StringEncoding], (id)kSecAttrCanEncrypt:@NO, (id)kSecAttrCanDecrypt:@YES, (id)kSecAttrAccessGroup: appGrpIdentifier }; // Set the public key attributes. NSDictionary *publicKeyAttr = @{(id)kSecAttrIsPermanent: @YES, (id)kSecAttrApplicationTag: [TAG_ASSYMETRIC_PUBLIC_KEY dataUsingEncoding:NSUTF8StringEncoding], (id)kSecAttrCanEncrypt:@YES, (id)kSecAttrCanDecrypt:@NO, (id)kSecAttrAccessGroup: appGrpIdentifier }; // Set top level attributes for the keypair. NSDictionary *keyPairAttr = @{(id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, (id)kSecAttrKeySizeInBits: @(bitSize), (id)kSecClass: (id)kSecClassKey, (id)kSecPrivateKeyAttrs: privateKeyAttr, (id)kSecPublicKeyAttrs: publicKeyAttr, // MOBSF-WARNING-SUPPRESS: (id)kSecAttrAccessible: (id)kSecAttrAccessibleAfterFirstUnlock, // mobsf-ignore: ios_keychain_weak_accessibility_value // MOBSF-SUPPRESS-END (id)kSecAttrAccessGroup: appGrpIdentifier }; // Generate Assymetric keys sanityCheck = SecKeyGeneratePair((CFDictionaryRef)keyPairAttr, &publicKeyRef, &privateKeyRef); if(sanityCheck == errSecSuccess){ NSLog(@"[DB_ENCRYPTION] <ALA_INFO> [OS-CCF] CALLED Assymetric keys are generated"); } else{ NSLog(@"[DB_ENCRYPTION] <ALA_ERROR> [OS-CCF] CALLED Error while generating asymetric keys : %d", (int)sanityCheck); } if (publicKeyRef) { CFRelease(publicKeyRef); } if (privateKeyRef) { CFRelease(privateKeyRef); } return sanityCheck; } KeyPair is added into the KeyChain (BOOL)saveSymetricKeyToKeychain:(NSData *)symmetricKeyData keyIdentifier:(NSString *)keyIdentifier { NSString *appGrpIdentifier = [KeychainGroupManager getAppGroupIdentifier]; NSDictionary *query = @{ (__bridge id)kSecClass: (__bridge id)kSecClassKey, (__bridge id)kSecAttrApplicationTag: keyIdentifier, (__bridge id)kSecValueData: symmetricKeyData, (__bridge id)kSecAttrKeyClass: (__bridge id)kSecAttrKeyClassSymmetric, // MOBSF-WARNING-SUPPRESS: (__bridge id)kSecAttrAccessible: (__bridge id)kSecAttrAccessibleAfterFirstUnlock, // mobsf-ignore: ios_keychain_weak_accessibility_value // MOBSF-SUPPRESS-END (__bridge id)kSecAttrAccessGroup: appGrpIdentifier }; // Now add the key to the Keychain status = SecItemAdd((__bridge CFDictionaryRef)query, NULL); if (status == errSecSuccess) { NSLog(@"[DB_ENCRYPTION] Key successfully stored in the Keychain"); return YES; } else { NSLog(@"<ALA_ERROR> [DB_ENCRYPTION] Error storing key in the Keychain: %d", (int)status); return NO; } } Post App Transfer, we are able to retrieve the Public & Private Key Reference without rebuilding the keychain Query:- Is this attribute "kSecAttrAccessGroup" helping us to retrieve the KeyChain items without having to rebuild on App Transfer to New Apple Account as described in this set of guidelines. Could you please explain in detail on this. https://developer.apple.com/help/app-store-connect/transfer-an-app/overview-of-app-transfer Keychain sharing continues to work only until the app is updated. Therefore, you must rebuild the keychain when submitting updates. If your keychain group is defined in the Xcode project, replace it with a group created by the recipient, incorporating their Team ID for continued keychain sharing. After the update, users must re-login once as the app cannot retrieve the authentication token from the keychain.
1
0
121
Apr ’26
App ID Prefix Change and Keychain Access
DTS regularly receives questions about how to preserve keychain items across an App ID change, and so I thought I’d post a comprehensive answer here for the benefit of all. If you have any questions or comments, please start a new thread here on the forums. Put it in the Privacy & Security > General subtopic and tag it with Security. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" App ID Prefix Change and Keychain Access The list of keychain access groups your app can access is determined by three entitlements. For the details, see Sharing Access to Keychain Items Among a Collection of Apps. If your app changes its App ID prefix, this list changes and you’re likely to lose access to existing keychain items. This situation crops up under two circumstances: When you migrate your app from using a unique App ID prefix to using your Team ID as its App ID prefix. When you transfer your app to another team. In both cases you have to plan carefully for this change. If you only learn about the problem after you’ve made the change, consider undoing the change to give you time to come up with a plan before continuing. Note On macOS, the information in this post only applies to the data protection keychain. For more information about the subtleties of the keychain on macOS, see On Mac Keychains. For more about App ID prefix changes, see Technote 2311 Managing Multiple App ID Prefixes and QA1726 Resolving the Potential Loss of Keychain Access warning. Migrate From a Unique App ID Prefix to Your Team ID Historically each app was assigned its own App ID prefix. This is no longer the case. Best practice is for apps to use their Team ID as their App ID prefix. This enables multiple neat features, including keychain item sharing and pasteboard sharing. If you have an app that uses a unique App ID prefix, consider migrating it to use your Team ID. This is a good thing in general, as long as you manage the migration process carefully. Your app’s keychain access group list is built from three entitlements: keychain-access-groups — For more on this, see Keychain Access Groups Entitlement. application-identifier (com.apple.application-identifier on macOS) com.apple.security.application-groups — For more on this, see App Groups Entitlement. Keycahin access groups from the third bullet are call app group identified keychain access groups, or AGI keychain access groups for short. IMPORTANT A macOS app can only use an AGI keychain access group if all of its entitlement claims are validated by a provisioning profile. See App Groups: macOS vs iOS: Working Towards Harmony for more about this concept. Keychain access groups from the first two bullets depend on the App ID prefix. If that changes, you lose access to any keychain items in those groups. WARNING Think carefully before using the keychain to store secrets that are the only way to access irreplaceable user data. While the keychain is very reliable, there are situations where a keychain item can be lost and it’s bad if it takes the user’s data with it. In some cases losing access to keychain items is not a big deal. For example, if your app uses the keychain to manage a single login credential, losing that is likely to be acceptable. The user can recover by logging in again. In other cases losing access to keychain items is unacceptable. For example, your app might manage access to dozens of different servers, each with unique login credentials. Your users will be grumpy if you require them to log in to all those servers again. In such situations you must carefully plan your migration. The key thing to understand is that an app group is tied to your team, not your App ID prefix, and thus your app retains access to AGI keychain access groups across an App ID prefix change. This suggests the following approach: Release a version of your app that moves keychain items from other keychain access groups to an AGI keychain access group. Give your users time to update to this new version, run it, and so move their keychain items. When you’re confident that the bulk of your users have done this, change your App ID prefix. The approach has one obvious caveat: It’s hard to judge how long to wait at step 2. Transfer Your App to Another Team Historically there was no supported way to maintain access to keychain items across an app transfer. That’s no longer the case, but you must still plan the transfer carefully. The overall approach is: Identify an app group ID to transfer. This could be an existing app group ID, but in many cases you’ll want to register a new app group ID solely for this purpose. Use the old team (the transferor) to release a version of your app that moves keychain items from other keychain access groups to the AGI keychain access group for this app group ID. Give your users time to update to this new version, run it, and so move their keychain items. When you’re confident that the bulk of your users have done this, initiate the app transfer. Once that’s complete, transfer the app group ID you selected in step 1. See App Store Connect Help > Transfer an app > Overview of app transfer > Apps using App Groups. Publish an update to your app from the new team (the transferee). When a user installs this version, it will have access to your app group, and hence your keychain items. WARNING Once you transfer the app group, the old team won’t be able to publish a new version of any app that uses this app group. That makes step 1 in the process critical. If you have an existing app group that’s used solely by the app being transferred — for example, an app group that you use to share state between the app and its app extensions — then choosing that app group ID makes sense. On the other hand, choosing the ID of an app group that’s share between this app and some unrelated app, one that’s not being transferred, would be bad, because any updates to that other app will lose access to the app group. There are some other significant caveats: The process doesn’t work for Mac apps because Mac apps that have ever used an app group can’t be transferred. See App Store Connect Help > Transfer an app > App transfer criteria. If and when that changes, you’ll need to choose an iOS-style app group ID for your AGI keychain access group. For more about the difference between iOS- and macOS-style app group IDs, see App Groups: macOS vs iOS: Working Towards Harmony. The current transfer process of app groups exposes a small window where some other team can ‘steal’ your app group ID. We have a bug on file to improve that process (r. 171616887). The process works best when transferring between two teams that are both under the control of the same entity. If that’s not the case, take steps to ensure that the old team transfers the app group in step 5. When you submit the app from the new team (step 6), App Store Connect will warn you about a potential loss of keychain access. That warning is talking about keychain items in normal keychain access groups. Items in an AGI keychain access group will still be accessible as long as you transfer the app group. Alternative Approaches for App Transfer In addition to the technique described in the previous section, there are a some alternative approaches you should at consider: Do nothing Do not transfer your app Get creative Do Nothing In this case the user loses all the secrets that your app stored in the keychain. This may be acceptable for certain apps. For example, if your app uses the keychain to manage a single login credential, losing that is likely to be acceptable. The user can recover by logging in again. Do Not Transfer Another option is to not transfer your app. Instead, ship a new version of the app from the new team and have the old app recommend that the user upgrade. There are a number of advantages to this approach. The first is that there’s absolutely no risk of losing any user data. The two apps are completely independent. The second advantage is that the user can install both apps on their device at the same time. This opens up a variety of potential migration paths. For example, you might ship an update to the old app with an export feature that saves the user’s state, including their secrets, to a suitably encrypted file, and then match that with an import facility on the new app. Finally, this approach offers flexible timing. The user can complete their migration at their leisure. However, there are a bunch of clouds to go with these silver linings: Your users might never migrate to the new app. If this is a paid app, or an app with in-app purchase, the user will have to buy things again. You lose the original app’s history, ratings, reviews, and so on. Get Creative Finally, you could attempt something creative. For example, you might: Publish a new version of the app that supports exporting the user’s state, including the secrets. Tell your users to do this, with a deadline. Transfer the app and then, when the deadline expires, publish the new version with an import feature. Frankly, this isn’t very practical. The problem is with step 2: There’s no good way to get all your users to do the export, and if they don’t do it before the deadline there’s no way to do it after. Test Before You Ship Once you have a new version of your app, with the new App ID prefix, it’s time to test. To run a day-to-day test: On a test device, install the existing version of the app from the App Store. Use the app to generate keychain items as a normal user would. For example, if you store login credentials in the keychain, use the app to save such a credential. In Xcode, run the new version of your app. Check that the keychain items you created in step 2 still work. After you upload this new version to App Store Connect, use TestFlight to run an internal test: On a test device, install the existing version of the app from the App Store. Use the app to generate keychain items as a normal user. For example, if you store login credentials in the keychain, use the app to save such a credential. Use TestFlight to update the app to your new version. Check that the keychain items you created in step 2 still work. Do this before you release the app to your beta testers and then again before releasing it to customers. WARNING These TestFlight test are your last chance to ensure that everything works. If you detect an error at this stage, you still have a chance to fix it. Revision History 2026-04-07 Added the Test Before You Ship section. 2026-03-31 Rewrote the Transfer Your App to Another Team section to describe a new approach for preserving access to keychain items across app transfers. Moved the previous discussion into a new Alternative Approaches for App Transfer section. Clarified that a macOS program can now use an app group as a keychain access group as long as its entitlements are validated. Made numerous editorial changes. 2022-05-17 First posted.
0
0
8.8k
Apr ’26
DCDevice last_update_time issue
We are currently experiencing an unexpected issue with the DeviceCheck query_two_bits endpoint. According to the official documentation (Accessing and Modifying Per-Device Data), the last_update_time field should represent the month and year when the bits were last modified. The Issue: For several specific device tokens, our server is receiving a last_update_time value that is set in the future. Current Date: April 2026 Returned last_update_time: 2026-12 (December 2026) Here is a response: { "body": "{\"bit0\":false,\"bit1\":true,\"last_update_time\":\"2026-12\"}", "headers": { "Server": ["Apple"], "Date": ["Thu, 02 Apr 2026 06:05:23 GMT"], "Content-Type": ["application/json; charset=UTF-8"], "Transfer-Encoding": ["chunked"], "Connection": ["keep-alive"], "X-Apple-Request-UUID": ["53e16c38-d9f7-4d58-a354-ce07a4eaa35b"], "X-Responding-Instance": ["af-bit-store-56b5b6b478-k8hnh"], "Strict-Transport-Security": ["max-age=31536000; includeSubdomains"], "X-Frame-Options": ["SAMEORIGIN"], "X-Content-Type-Options": ["nosniff"], "X-XSS-Protection": ["1; mode=block"] }, "statusCode": "OK", "statusCodeValue": 200 } Technical Details: Endpoint: https://api.development.devicecheck.apple.com/v1/query_two_bits (also occurring in Production) Response Body Example: JSON { "bit0": true, "bit1": false, "last_update_time": "2026-12" } Observations: This occurs even when our server has not sent an update_two_bits request for that specific device in the current month. Questions: Is there a known issue with the timestamp synchronization or regional database propagation for DeviceCheck? Does the last_update_time field ever represent an expiration date or any value other than the "last modified" month? Best regards,
1
0
146
Apr ’26
DeviceCheck query_two_bits returns last_update_time in the future — what could cause this?
Hi everyone, I'm integrating Apple's DeviceCheck API into my app and have run into a strange issue that I can't find documented anywhere. The Problem When I call Apple's DeviceCheck query endpoint (POST https://api.devicecheck.apple.com/v1/query_two_bits), the response occasionally returns a last_update_time value that is in the future — ahead of the current server time. Example response: { "bit0": true, "bit1": false, "last_update_time": "2026-05" // future month, not yet reached } What I've Checked My server's system clock is correctly synced via NTP The JWT token I generate uses the current timestamp for the iat field This doesn't happen on every device — only on some specific devices The issue is reproducible on the same device across multiple calls Questions Is last_update_time sourced from the device's local clock at the time update_two_bits was called? Or is it stamped server-side by Apple? Could a device with an incorrectly set system clock (set to the future) cause Apple's servers to record a future last_update_time? Is there a recommended way to validate or sanitize last_update_time on the server side to handle this edge case? Has anyone else encountered this behavior? Any known workarounds? Any insight would be greatly appreciated. Thanks!
1
0
140
Apr ’26
Clarification on attestKey API in Platform SSO
Hi, We are implementing Platform SSO and using attestKey during registration via ASAuthorizationProviderExtensionLoginManager. Could you clarify whether the attestKey flow involves sending attestation data to an Apple server for verification (similar to App Attest in the DeviceCheck framework), or if the attestation certificate chain is generated and signed entirely on-device without any Apple server interaction? The App Attest flow is clearly documented as using Apple’s attestation service, but the Platform SSO process is less clearly described. Thank you.
6
0
696
Apr ’26
ASAuthorizationProviderExtensionAuthorizationRequest.complete(httpAuthorizationHeaders:) custom header not reaching endpoint
I’m implementing a macOS Platform SSO extension using ASAuthorizationProviderExtensionAuthorizationRequest. In beginAuthorization, I intercept an OAuth authorize request and call: request.complete(httpAuthorizationHeaders: [ "x-psso-attestation": signedJWT ]) I also tested: request.complete(httpAuthorizationHeaders: [ "Authorization": "Bearer test-value" ]) From extension logs, I can confirm the request is intercepted correctly and the header dictionary passed into complete(httpAuthorizationHeaders:) contains the expected values. However: the header is not visible in browser devtools the header does not appear at the server / reverse proxy So the question is: Does complete(httpAuthorizationHeaders:) support arbitrary custom headers, or only a restricted set of authorization-related headers ? Is there something that I might be missing ? And if custom headers are not supported, is there any supported way for a Platform SSO extension to attach a normal HTTP header to the continued outbound request ?
1
0
343
Apr ’26
How to store certificate to `com.apple.token` keychain access group.
I’m developing an iOS application and aiming to install a PKCS#12 (.p12) certificate into the com.apple.token keychain access group so that Microsoft Edge for iOS, managed via MDM/Intune, can read and use it for client certificate authentication. I’m attempting to save to the com.apple.token keychain access group, but I’m getting error -34018 (errSecMissingEntitlement) and the item isn’t saved. This occurs on both a physical device and the simulator. I’m using SecItemAdd from the Security framework to store it. Is this the correct approach? https://developer.apple.com/documentation/security/secitemadd(::) I have added com.apple.token to Keychain Sharing. I have also added com.apple.token to the app’s entitlements. Here is the code I’m using to observe this behavior: public static func installToTokenGroup(p12Data: Data, password: String) throws -> SecIdentity { // First, import the P12 to get the identity let options: [String: Any] = [ kSecImportExportPassphrase as String: password ] var items: CFArray? let importStatus = SecPKCS12Import(p12Data as CFData, options as CFDictionary, &items) guard importStatus == errSecSuccess, let array = items as? [[String: Any]], let dict = array.first else { throw NSError(domain: NSOSStatusErrorDomain, code: Int(importStatus), userInfo: [NSLocalizedDescriptionKey: "Failed to import P12: \(importStatus)"]) } let identity = dict[kSecImportItemIdentity as String] as! SecIdentity let addQuery: [String: Any] = [ kSecClass as String: kSecClassIdentity, kSecValueRef as String: identity, kSecAttrLabel as String: kSecAttrAccessGroupToken, kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlock, kSecAttrAccessGroup as String: kSecAttrAccessGroupToken ] let status = SecItemAdd(addQuery as CFDictionary, nil) if status != errSecSuccess && status != errSecDuplicateItem { throw NSError(domain: NSOSStatusErrorDomain, code: Int(status), userInfo: [NSLocalizedDescriptionKey: "Failed to add to token group: \(status)"]) } return identity }
3
0
609
Apr ’26
Entitlement values for the Enhanced Security and the Additional Runtime Platform Restrictions
I recently turned on the enhanced security options for my macOS app in Xcode 26.0.1 by adding the Enhanced Security capability in the Signing and Capabilities tab. Then, Xcode adds the following key-value sets (with some other key-values) to my app's entitlements file. <key>com.apple.security.hardened-process.enhanced-security-version</key> <integer>1</integer> <key>com.apple.security.hardened-process.platform-restrictions</key> <integer>2</integer> These values appear following the documentation about the enhanced security feature (Enabling enhanced security for your app) and the app works without any issues. However, when I submitted a new version to the Mac App Store, my submission was rejected, and I received the following message from the App Review team via the App Store Connect. Guideline 2.4.5(i) - Performance Your app incorrectly implements sandboxing, or it contains one or more entitlements with invalid values. Please review the included entitlements and sandboxing documentation and resolve this issue before resubmitting a new binary. Entitlement "com.apple.security.hardened-process.enhanced-security-version" value must be boolean and true. Entitlement "com.apple.security.hardened-process.platform-restrictions" value must be boolean and true. When I changed those values directly in the entitlements file based on this message, the app appears to still work. However, these settings are against the description in the documentation I mentioned above and against the settings Xcode inserted after changing the GUI setting view. So, my question is, which settings are actually correct to enable the Enhanced Security and the Additional Runtime Platform Restrictions?
6
0
1.4k
Apr ’26
Production-Grade Implementation Guidance: DCError Matrices, Retry Strategies, and Simulator Testing for App Attest APIs
Hi there, We're implementing Apple's DeviceCheck App Attest for production iOS authentication. The public documentation defines DCError cases but doesn't specify which errors are expected per API method or recommend retry/remediation strategies. We need Apple's guidance to implement robust, production-aligned error handling before rollout. 1. Error Surface per API Method Question: Can you confirm the complete, officially expected set of DCError values for each method? We understand the following errors are possible across App Attest APIs: invalidKey invalidInput featureUnsupported serverUnavailable unknownSystemFailure Specifically, please confirm which errors can occur for: DCAppAttestService.generateKey() DCAppAttestService.attestKey(_:clientData:) DCAppAttestService.generateAssertion(keyID:clientData:) Are there any additional undocumented or edge-case errors we should handle? 2. Retry Strategy & Remediation Matrix Question: For each API method and error code, please help us with proposal around which errorCode is retriable, whats the remediation pre retry, retry cap and backoff strategy: Kindly also help with errors that are not covered here: Specific sub-questions: invalidKey handling: When this error occurs: Should the app delete the key and call generateKey again? Or should it fail the entire flow? serverUnavailable handling: Should we retry immediately, or wait before retrying? Is exponential backoff recommended? What's the recommended max retry count? Backoff strategy: Which errors (if any) qualify for exponential backoff? Recommended base delay, max delay, and jitter approach? When should we give up and fail the request? unknownSystemFailure: Is this retriable or should we fail? Any known causes or mitigations? 3. Simulator Testing Questions: Simulator API behavior: Can App Attest APIs be called normally on iOS Simulator? If not, is there a way to simulate for testing. Do they complete successfully with simulated attestations, or do they fail? Thanks, Nirekshitha
0
0
329
Apr ’26
launch ASWebAuthenticationSession from single sign on extenstion
I need to launch ASWebAuthenticationSession from single sign on extension, but its not launching it might issue with anchoring window, I have create custom windo and passing it in presentanchor(for session) function, custom window is launching but ASWebAuthenticationSession browser is not launching Note - flow is like this Apple PSSO register window lauched OIDC login will happen via ASWebAuthenticationSession to get accesstoken which will use in device registration but ASWebAuthenticationSession is not launching, I am using custom scheme as redirect URI iskeywindow for custom window is always false what is right approach to achieve the goal
1
0
196
Apr ’26
iPhone 16 Datasheet
I am trying to find a datasheet containing information such as "Key Exchange / Key Agreement / Key Establishment Protocols Used", "Digital Signature Algorithms Used", "Hash Algorithms Used", etc. Any information would greatly appreciated.
1
0
109
Apr ’26
TEAM ID Prefix Keychain Access
Thanks all for reading my post. A bit of context: We just finished an app transfer to our developer account. We successfully signed and generated the new release. We are already able to roll it out in testflight were we found an issue. We store valuable data in the Keychain like Authentication tokens, once the new app is installed over the old one we are experiencing a loss of all data as the keychain become "untrusted". This is worst case scenario for us because all users will immediately lose the access to the app and hence the whole system. Questions: Is there a way to solve this issue, something like migration of the Keychain data? We came to know the standard migration path: Release a version that copies items from the old access groups to a new group based on com.apple.security.application-groups (App Groups). Wait for most users to update and run the migration. Then perform the App ID prefix change. Is this still the best method? Any improvements or new tools available since the 2022 DTS post? The problem with this is that the app is already on our account and that might need to rollback the transfer. Right? How long should we realistically wait for user migration before making the prefix change? Is there a way to measure migration completion? Thank you in advance!
1
0
183
Mar ’26
password to unlock login keychain in 26.4?
I lived with knowledge that one needs to provide his login password to unlock the login keychain. This does not seem to be entirely true after upgrading Tahoe to 26.4. For example, on 26.3: Go to ~/Library/Keychains Copy login.keychain-db to different name, say test.keychain-db. Double-click on test.keychain-db -> this should open Keychain Access with test in Custom keychains section, it will appear locked. Select test keychain and press Cmd+L to unlock it. When prompted, provide your login password. Result: the keychain is unlocked. When I preform above sequence of steps on 26.4 I am not able to unlock the copied keychain (the original login keychain appears implicitly unlocked).
2
0
332
Mar ’26
Exploring Secure Enclave–backed biometric authorization between macOS and iPhone using public APIs (FaceBridge prototype)
Hi everyone, I’ve been working on an experimental prototype called FaceBridge that explores whether Secure Enclave–backed biometric authorization can be delegated between macOS and iPhone using only public Apple APIs. The goal of the project was to better understand the architectural boundaries of cross-device trust and approval flows that resemble Apple’s built-in Touch ID / Continuity authorization experiences. FaceBridge implements a local authorization pipeline where: macOS generates a signed authorization request the request is delivered to a trusted nearby iPhone over BLE / Network framework the iPhone verifies sender identity Face ID approval is requested using LocalAuthentication the iPhone signs the approval response using Secure Enclave–backed keys macOS validates the response and unlocks a protected action Security properties currently implemented: • Secure Enclave–backed signing identities per device • cryptographic device pairing and trust persistence • replay protection using nonce + timestamp binding • structured authorization request/response envelopes • signed responder identity verification • trusted-device registry model • local encrypted transport over BLE and local network This is intentionally not attempting to intercept or replace system-level Touch ID dialogs (App Store installs, Keychain prompts, loginwindow, etc.), but instead explores what is possible within application-level authorization boundaries using public APIs only. The project is open source: https://github.com/wesleysfavarin/facebridge Technical architecture write-up: https://medium.com/@wesleysfavarin/facebridge I’m particularly interested in feedback around: • recommended Secure Enclave identity lifecycle patterns • best practices for cross-device trust persistence • LocalAuthentication usage in delegated approval scenarios • whether similar authorization models are expected to become more formally supported across Apple platforms in the future Thanks in advance for any guidance or suggestions.
1
0
258
Mar ’26
Control over "\(your_app) wants to open \(another_app)" Dialog
I can't find any information about why this is happening, nor can I reproduce the 'successful' state on this device. My team needs to understand this behavior, so any insight would be greatly appreciated! The expected behavior: If I delete both apps and reinstall them, attempting to open the second app from my app should trigger the system confirmation dialog. The specifics: I'm using the MSAL library. It navigates the user to the Microsoft Authenticator app and then returns to my app. However, even after resetting the phone and reinstalling both apps, the dialog never shows up (it just opens the app directly). Does anyone know the logic behind how iOS handles these prompts or why it might be persistent even after a reset? Thanks in advance!
4
0
559
Mar ’26
TkSmartCard transmitRequest persistently returning Cryptotokenkit error -2 on iOS/iPadOS
We are using the CryptoTokenKit framework, specifically the classes TKSmartCardSlotManager, TKSmartCardSlot, and TKSmartCard, to communicate with smart cards through external USB readers on iOS and iPadOS. In most cases, we are able to detect readers via TKSmartCardSlotManager, and send APDU commands using transmitRequest method, with the following code (where self->_slot and self->_card are previously created TkSmartCardSlot and TkSmartCard, respectively): #import <CryptoTokenKit/CryptoTokenKit.h> - (NSData *)sendCardCommand:(NSData *)command { if (!self->_card || !self->_card.valid || self->_slot.state != TKSmartCardSlotStateValidCard) return nil; NSMutableData *res = [[NSMutableData alloc] init]; NSError *sessionError = nil; [self->_card inSessionWithError:&sessionError executeBlock:^BOOL(NSError **error) { dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); try { [self->_card transmitRequest:command reply:^(NSData * _Nullable response, NSError* _Nullable apduError) { if (apduError != nil) self->_error = apduError; else [res appendData: response]; dispatch_semaphore_signal(semaphore); }]; } catch (NSException *exception) { dispatch_semaphore_signal(semaphore); } dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); if (res.length == 0) return NO; return YES; }]; return res; } However, with certain other USB smart card readers, we occasionally encounter APDU communication failures when calling transmitRequest (for instance, with a HID Global OMNIKEY 5422), which returns the following error: "Domain: CryptoTokenKit Code: -2". Once a failure occurs and transmitRequest starts returning this error, all subsequent calls to transmitRequest fail with the same error. This persists even when: A different smart card is inserted The same card is reinserted A different USB reader (previously working correctly) is connected The TKSmartCard object is recreated via makeSmartCard The slot state changes (observed via KVO) All internal objects (TKSmartCard, TKSmartCardSlot) are reset in the application At this point, the system appears to be stuck in a non-recoverable state which affects all readers and cards, including those that were previously functioning correctly. The only way to recover from this state is terminating and restarting the application which is running the code. After restarting the app, everything works normally again. We have created a bug report: FB22339746. The issue has been reproduced on iOS 26.4 and 18.5. Also on iPadOS 18.1. Anyone has already faced a similar issue? Could it be related to some internal state of TKSmartCardSlotManager?
2
0
294
Mar ’26
Endpoint Security entitlement for open-source behavioral monitoring tool
Hi, I’m building a macOS tool that analyzes process behavior to detect autonomous / AI-like activity locally (process trees, file access patterns, and network usage). The system is fully user-space and runs locally in real time. I’m planning to use the Endpoint Security Framework for process and file event monitoring. This is an open-source project (non-enterprise), developed by a solo developer. My question: What are the realistic chances of getting Endpoint Security entitlements approved for this type of project? Are there specific requirements or common reasons for rejection I should be aware of? Thanks, sivan-rnd
2
0
214
Mar ’26
MFA MacOS At ScreenSaver (Lock Screen).
Hi , I did The MFA(2FA) of Email OTP For MacOS Login Screen using, Authorization Plugin, Using This git hub project. It is working For Login Screen , Im trying to Add The Same plugin for LockScreen but it is not working at lock Screen , Below is the reffrense theard For The issue , https://developer.apple.com/forums/thread/127614, please Share The Code that should Present the NSwindow at Screen Saver (Lock Screen) MacOS .
3
0
1.1k
Mar ’26
[KeyChain Framework] KeyChain Item is accessible post App Transfer without rebuilding the KeyChain
We have utilised the KeyChain Framework for Adding items into KeyChain. We have Generated KeyPair using 'SecKeyGeneratePair' API as below (OSStatus)generateAssymetricKeyPair:(NSUInteger)bitSize{ OSStatus sanityCheck = noErr; SecKeyRef publicKeyRef = NULL; SecKeyRef privateKeyRef = NULL; NSString *appGrpIdentifier = @"group.com.sample.xyz" // Set the private key attributes. NSDictionary *privateKeyAttr = @{(id)kSecAttrIsPermanent: @YES, (id)kSecAttrApplicationTag: [TAG_ASSYMETRIC_PRIVATE_KEY dataUsingEncoding:NSUTF8StringEncoding], (id)kSecAttrCanEncrypt:@NO, (id)kSecAttrCanDecrypt:@YES, (id)kSecAttrAccessGroup: appGrpIdentifier }; // Set the public key attributes. NSDictionary *publicKeyAttr = @{(id)kSecAttrIsPermanent: @YES, (id)kSecAttrApplicationTag: [TAG_ASSYMETRIC_PUBLIC_KEY dataUsingEncoding:NSUTF8StringEncoding], (id)kSecAttrCanEncrypt:@YES, (id)kSecAttrCanDecrypt:@NO, (id)kSecAttrAccessGroup: appGrpIdentifier }; // Set top level attributes for the keypair. NSDictionary *keyPairAttr = @{(id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, (id)kSecAttrKeySizeInBits: @(bitSize), (id)kSecClass: (id)kSecClassKey, (id)kSecPrivateKeyAttrs: privateKeyAttr, (id)kSecPublicKeyAttrs: publicKeyAttr, // MOBSF-WARNING-SUPPRESS: (id)kSecAttrAccessible: (id)kSecAttrAccessibleAfterFirstUnlock, // mobsf-ignore: ios_keychain_weak_accessibility_value // MOBSF-SUPPRESS-END (id)kSecAttrAccessGroup: appGrpIdentifier }; // Generate Assymetric keys sanityCheck = SecKeyGeneratePair((CFDictionaryRef)keyPairAttr, &publicKeyRef, &privateKeyRef); if(sanityCheck == errSecSuccess){ NSLog(@"[DB_ENCRYPTION] <ALA_INFO> [OS-CCF] CALLED Assymetric keys are generated"); } else{ NSLog(@"[DB_ENCRYPTION] <ALA_ERROR> [OS-CCF] CALLED Error while generating asymetric keys : %d", (int)sanityCheck); } if (publicKeyRef) { CFRelease(publicKeyRef); } if (privateKeyRef) { CFRelease(privateKeyRef); } return sanityCheck; } KeyPair is added into the KeyChain (BOOL)saveSymetricKeyToKeychain:(NSData *)symmetricKeyData keyIdentifier:(NSString *)keyIdentifier { NSString *appGrpIdentifier = [KeychainGroupManager getAppGroupIdentifier]; NSDictionary *query = @{ (__bridge id)kSecClass: (__bridge id)kSecClassKey, (__bridge id)kSecAttrApplicationTag: keyIdentifier, (__bridge id)kSecValueData: symmetricKeyData, (__bridge id)kSecAttrKeyClass: (__bridge id)kSecAttrKeyClassSymmetric, // MOBSF-WARNING-SUPPRESS: (__bridge id)kSecAttrAccessible: (__bridge id)kSecAttrAccessibleAfterFirstUnlock, // mobsf-ignore: ios_keychain_weak_accessibility_value // MOBSF-SUPPRESS-END (__bridge id)kSecAttrAccessGroup: appGrpIdentifier }; // Now add the key to the Keychain status = SecItemAdd((__bridge CFDictionaryRef)query, NULL); if (status == errSecSuccess) { NSLog(@"[DB_ENCRYPTION] Key successfully stored in the Keychain"); return YES; } else { NSLog(@"<ALA_ERROR> [DB_ENCRYPTION] Error storing key in the Keychain: %d", (int)status); return NO; } } Post App Transfer, we are able to retrieve the Public & Private Key Reference without rebuilding the keychain Query:- Is this attribute "kSecAttrAccessGroup" helping us to retrieve the KeyChain items without having to rebuild on App Transfer to New Apple Account as described in this set of guidelines. Could you please explain in detail on this. https://developer.apple.com/help/app-store-connect/transfer-an-app/overview-of-app-transfer Keychain sharing continues to work only until the app is updated. Therefore, you must rebuild the keychain when submitting updates. If your keychain group is defined in the Xcode project, replace it with a group created by the recipient, incorporating their Team ID for continued keychain sharing. After the update, users must re-login once as the app cannot retrieve the authentication token from the keychain.
Replies
1
Boosts
0
Views
121
Activity
Apr ’26
App ID Prefix Change and Keychain Access
DTS regularly receives questions about how to preserve keychain items across an App ID change, and so I thought I’d post a comprehensive answer here for the benefit of all. If you have any questions or comments, please start a new thread here on the forums. Put it in the Privacy & Security > General subtopic and tag it with Security. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" App ID Prefix Change and Keychain Access The list of keychain access groups your app can access is determined by three entitlements. For the details, see Sharing Access to Keychain Items Among a Collection of Apps. If your app changes its App ID prefix, this list changes and you’re likely to lose access to existing keychain items. This situation crops up under two circumstances: When you migrate your app from using a unique App ID prefix to using your Team ID as its App ID prefix. When you transfer your app to another team. In both cases you have to plan carefully for this change. If you only learn about the problem after you’ve made the change, consider undoing the change to give you time to come up with a plan before continuing. Note On macOS, the information in this post only applies to the data protection keychain. For more information about the subtleties of the keychain on macOS, see On Mac Keychains. For more about App ID prefix changes, see Technote 2311 Managing Multiple App ID Prefixes and QA1726 Resolving the Potential Loss of Keychain Access warning. Migrate From a Unique App ID Prefix to Your Team ID Historically each app was assigned its own App ID prefix. This is no longer the case. Best practice is for apps to use their Team ID as their App ID prefix. This enables multiple neat features, including keychain item sharing and pasteboard sharing. If you have an app that uses a unique App ID prefix, consider migrating it to use your Team ID. This is a good thing in general, as long as you manage the migration process carefully. Your app’s keychain access group list is built from three entitlements: keychain-access-groups — For more on this, see Keychain Access Groups Entitlement. application-identifier (com.apple.application-identifier on macOS) com.apple.security.application-groups — For more on this, see App Groups Entitlement. Keycahin access groups from the third bullet are call app group identified keychain access groups, or AGI keychain access groups for short. IMPORTANT A macOS app can only use an AGI keychain access group if all of its entitlement claims are validated by a provisioning profile. See App Groups: macOS vs iOS: Working Towards Harmony for more about this concept. Keychain access groups from the first two bullets depend on the App ID prefix. If that changes, you lose access to any keychain items in those groups. WARNING Think carefully before using the keychain to store secrets that are the only way to access irreplaceable user data. While the keychain is very reliable, there are situations where a keychain item can be lost and it’s bad if it takes the user’s data with it. In some cases losing access to keychain items is not a big deal. For example, if your app uses the keychain to manage a single login credential, losing that is likely to be acceptable. The user can recover by logging in again. In other cases losing access to keychain items is unacceptable. For example, your app might manage access to dozens of different servers, each with unique login credentials. Your users will be grumpy if you require them to log in to all those servers again. In such situations you must carefully plan your migration. The key thing to understand is that an app group is tied to your team, not your App ID prefix, and thus your app retains access to AGI keychain access groups across an App ID prefix change. This suggests the following approach: Release a version of your app that moves keychain items from other keychain access groups to an AGI keychain access group. Give your users time to update to this new version, run it, and so move their keychain items. When you’re confident that the bulk of your users have done this, change your App ID prefix. The approach has one obvious caveat: It’s hard to judge how long to wait at step 2. Transfer Your App to Another Team Historically there was no supported way to maintain access to keychain items across an app transfer. That’s no longer the case, but you must still plan the transfer carefully. The overall approach is: Identify an app group ID to transfer. This could be an existing app group ID, but in many cases you’ll want to register a new app group ID solely for this purpose. Use the old team (the transferor) to release a version of your app that moves keychain items from other keychain access groups to the AGI keychain access group for this app group ID. Give your users time to update to this new version, run it, and so move their keychain items. When you’re confident that the bulk of your users have done this, initiate the app transfer. Once that’s complete, transfer the app group ID you selected in step 1. See App Store Connect Help > Transfer an app > Overview of app transfer > Apps using App Groups. Publish an update to your app from the new team (the transferee). When a user installs this version, it will have access to your app group, and hence your keychain items. WARNING Once you transfer the app group, the old team won’t be able to publish a new version of any app that uses this app group. That makes step 1 in the process critical. If you have an existing app group that’s used solely by the app being transferred — for example, an app group that you use to share state between the app and its app extensions — then choosing that app group ID makes sense. On the other hand, choosing the ID of an app group that’s share between this app and some unrelated app, one that’s not being transferred, would be bad, because any updates to that other app will lose access to the app group. There are some other significant caveats: The process doesn’t work for Mac apps because Mac apps that have ever used an app group can’t be transferred. See App Store Connect Help > Transfer an app > App transfer criteria. If and when that changes, you’ll need to choose an iOS-style app group ID for your AGI keychain access group. For more about the difference between iOS- and macOS-style app group IDs, see App Groups: macOS vs iOS: Working Towards Harmony. The current transfer process of app groups exposes a small window where some other team can ‘steal’ your app group ID. We have a bug on file to improve that process (r. 171616887). The process works best when transferring between two teams that are both under the control of the same entity. If that’s not the case, take steps to ensure that the old team transfers the app group in step 5. When you submit the app from the new team (step 6), App Store Connect will warn you about a potential loss of keychain access. That warning is talking about keychain items in normal keychain access groups. Items in an AGI keychain access group will still be accessible as long as you transfer the app group. Alternative Approaches for App Transfer In addition to the technique described in the previous section, there are a some alternative approaches you should at consider: Do nothing Do not transfer your app Get creative Do Nothing In this case the user loses all the secrets that your app stored in the keychain. This may be acceptable for certain apps. For example, if your app uses the keychain to manage a single login credential, losing that is likely to be acceptable. The user can recover by logging in again. Do Not Transfer Another option is to not transfer your app. Instead, ship a new version of the app from the new team and have the old app recommend that the user upgrade. There are a number of advantages to this approach. The first is that there’s absolutely no risk of losing any user data. The two apps are completely independent. The second advantage is that the user can install both apps on their device at the same time. This opens up a variety of potential migration paths. For example, you might ship an update to the old app with an export feature that saves the user’s state, including their secrets, to a suitably encrypted file, and then match that with an import facility on the new app. Finally, this approach offers flexible timing. The user can complete their migration at their leisure. However, there are a bunch of clouds to go with these silver linings: Your users might never migrate to the new app. If this is a paid app, or an app with in-app purchase, the user will have to buy things again. You lose the original app’s history, ratings, reviews, and so on. Get Creative Finally, you could attempt something creative. For example, you might: Publish a new version of the app that supports exporting the user’s state, including the secrets. Tell your users to do this, with a deadline. Transfer the app and then, when the deadline expires, publish the new version with an import feature. Frankly, this isn’t very practical. The problem is with step 2: There’s no good way to get all your users to do the export, and if they don’t do it before the deadline there’s no way to do it after. Test Before You Ship Once you have a new version of your app, with the new App ID prefix, it’s time to test. To run a day-to-day test: On a test device, install the existing version of the app from the App Store. Use the app to generate keychain items as a normal user would. For example, if you store login credentials in the keychain, use the app to save such a credential. In Xcode, run the new version of your app. Check that the keychain items you created in step 2 still work. After you upload this new version to App Store Connect, use TestFlight to run an internal test: On a test device, install the existing version of the app from the App Store. Use the app to generate keychain items as a normal user. For example, if you store login credentials in the keychain, use the app to save such a credential. Use TestFlight to update the app to your new version. Check that the keychain items you created in step 2 still work. Do this before you release the app to your beta testers and then again before releasing it to customers. WARNING These TestFlight test are your last chance to ensure that everything works. If you detect an error at this stage, you still have a chance to fix it. Revision History 2026-04-07 Added the Test Before You Ship section. 2026-03-31 Rewrote the Transfer Your App to Another Team section to describe a new approach for preserving access to keychain items across app transfers. Moved the previous discussion into a new Alternative Approaches for App Transfer section. Clarified that a macOS program can now use an app group as a keychain access group as long as its entitlements are validated. Made numerous editorial changes. 2022-05-17 First posted.
Replies
0
Boosts
0
Views
8.8k
Activity
Apr ’26
DCDevice last_update_time issue
We are currently experiencing an unexpected issue with the DeviceCheck query_two_bits endpoint. According to the official documentation (Accessing and Modifying Per-Device Data), the last_update_time field should represent the month and year when the bits were last modified. The Issue: For several specific device tokens, our server is receiving a last_update_time value that is set in the future. Current Date: April 2026 Returned last_update_time: 2026-12 (December 2026) Here is a response: { "body": "{\"bit0\":false,\"bit1\":true,\"last_update_time\":\"2026-12\"}", "headers": { "Server": ["Apple"], "Date": ["Thu, 02 Apr 2026 06:05:23 GMT"], "Content-Type": ["application/json; charset=UTF-8"], "Transfer-Encoding": ["chunked"], "Connection": ["keep-alive"], "X-Apple-Request-UUID": ["53e16c38-d9f7-4d58-a354-ce07a4eaa35b"], "X-Responding-Instance": ["af-bit-store-56b5b6b478-k8hnh"], "Strict-Transport-Security": ["max-age=31536000; includeSubdomains"], "X-Frame-Options": ["SAMEORIGIN"], "X-Content-Type-Options": ["nosniff"], "X-XSS-Protection": ["1; mode=block"] }, "statusCode": "OK", "statusCodeValue": 200 } Technical Details: Endpoint: https://api.development.devicecheck.apple.com/v1/query_two_bits (also occurring in Production) Response Body Example: JSON { "bit0": true, "bit1": false, "last_update_time": "2026-12" } Observations: This occurs even when our server has not sent an update_two_bits request for that specific device in the current month. Questions: Is there a known issue with the timestamp synchronization or regional database propagation for DeviceCheck? Does the last_update_time field ever represent an expiration date or any value other than the "last modified" month? Best regards,
Replies
1
Boosts
0
Views
146
Activity
Apr ’26
DeviceCheck query_two_bits returns last_update_time in the future — what could cause this?
Hi everyone, I'm integrating Apple's DeviceCheck API into my app and have run into a strange issue that I can't find documented anywhere. The Problem When I call Apple's DeviceCheck query endpoint (POST https://api.devicecheck.apple.com/v1/query_two_bits), the response occasionally returns a last_update_time value that is in the future — ahead of the current server time. Example response: { "bit0": true, "bit1": false, "last_update_time": "2026-05" // future month, not yet reached } What I've Checked My server's system clock is correctly synced via NTP The JWT token I generate uses the current timestamp for the iat field This doesn't happen on every device — only on some specific devices The issue is reproducible on the same device across multiple calls Questions Is last_update_time sourced from the device's local clock at the time update_two_bits was called? Or is it stamped server-side by Apple? Could a device with an incorrectly set system clock (set to the future) cause Apple's servers to record a future last_update_time? Is there a recommended way to validate or sanitize last_update_time on the server side to handle this edge case? Has anyone else encountered this behavior? Any known workarounds? Any insight would be greatly appreciated. Thanks!
Replies
1
Boosts
0
Views
140
Activity
Apr ’26
Clarification on attestKey API in Platform SSO
Hi, We are implementing Platform SSO and using attestKey during registration via ASAuthorizationProviderExtensionLoginManager. Could you clarify whether the attestKey flow involves sending attestation data to an Apple server for verification (similar to App Attest in the DeviceCheck framework), or if the attestation certificate chain is generated and signed entirely on-device without any Apple server interaction? The App Attest flow is clearly documented as using Apple’s attestation service, but the Platform SSO process is less clearly described. Thank you.
Replies
6
Boosts
0
Views
696
Activity
Apr ’26
ASAuthorizationProviderExtensionAuthorizationRequest.complete(httpAuthorizationHeaders:) custom header not reaching endpoint
I’m implementing a macOS Platform SSO extension using ASAuthorizationProviderExtensionAuthorizationRequest. In beginAuthorization, I intercept an OAuth authorize request and call: request.complete(httpAuthorizationHeaders: [ "x-psso-attestation": signedJWT ]) I also tested: request.complete(httpAuthorizationHeaders: [ "Authorization": "Bearer test-value" ]) From extension logs, I can confirm the request is intercepted correctly and the header dictionary passed into complete(httpAuthorizationHeaders:) contains the expected values. However: the header is not visible in browser devtools the header does not appear at the server / reverse proxy So the question is: Does complete(httpAuthorizationHeaders:) support arbitrary custom headers, or only a restricted set of authorization-related headers ? Is there something that I might be missing ? And if custom headers are not supported, is there any supported way for a Platform SSO extension to attach a normal HTTP header to the continued outbound request ?
Replies
1
Boosts
0
Views
343
Activity
Apr ’26
How to store certificate to `com.apple.token` keychain access group.
I’m developing an iOS application and aiming to install a PKCS#12 (.p12) certificate into the com.apple.token keychain access group so that Microsoft Edge for iOS, managed via MDM/Intune, can read and use it for client certificate authentication. I’m attempting to save to the com.apple.token keychain access group, but I’m getting error -34018 (errSecMissingEntitlement) and the item isn’t saved. This occurs on both a physical device and the simulator. I’m using SecItemAdd from the Security framework to store it. Is this the correct approach? https://developer.apple.com/documentation/security/secitemadd(::) I have added com.apple.token to Keychain Sharing. I have also added com.apple.token to the app’s entitlements. Here is the code I’m using to observe this behavior: public static func installToTokenGroup(p12Data: Data, password: String) throws -> SecIdentity { // First, import the P12 to get the identity let options: [String: Any] = [ kSecImportExportPassphrase as String: password ] var items: CFArray? let importStatus = SecPKCS12Import(p12Data as CFData, options as CFDictionary, &items) guard importStatus == errSecSuccess, let array = items as? [[String: Any]], let dict = array.first else { throw NSError(domain: NSOSStatusErrorDomain, code: Int(importStatus), userInfo: [NSLocalizedDescriptionKey: "Failed to import P12: \(importStatus)"]) } let identity = dict[kSecImportItemIdentity as String] as! SecIdentity let addQuery: [String: Any] = [ kSecClass as String: kSecClassIdentity, kSecValueRef as String: identity, kSecAttrLabel as String: kSecAttrAccessGroupToken, kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlock, kSecAttrAccessGroup as String: kSecAttrAccessGroupToken ] let status = SecItemAdd(addQuery as CFDictionary, nil) if status != errSecSuccess && status != errSecDuplicateItem { throw NSError(domain: NSOSStatusErrorDomain, code: Int(status), userInfo: [NSLocalizedDescriptionKey: "Failed to add to token group: \(status)"]) } return identity }
Replies
3
Boosts
0
Views
609
Activity
Apr ’26
Entitlement values for the Enhanced Security and the Additional Runtime Platform Restrictions
I recently turned on the enhanced security options for my macOS app in Xcode 26.0.1 by adding the Enhanced Security capability in the Signing and Capabilities tab. Then, Xcode adds the following key-value sets (with some other key-values) to my app's entitlements file. <key>com.apple.security.hardened-process.enhanced-security-version</key> <integer>1</integer> <key>com.apple.security.hardened-process.platform-restrictions</key> <integer>2</integer> These values appear following the documentation about the enhanced security feature (Enabling enhanced security for your app) and the app works without any issues. However, when I submitted a new version to the Mac App Store, my submission was rejected, and I received the following message from the App Review team via the App Store Connect. Guideline 2.4.5(i) - Performance Your app incorrectly implements sandboxing, or it contains one or more entitlements with invalid values. Please review the included entitlements and sandboxing documentation and resolve this issue before resubmitting a new binary. Entitlement "com.apple.security.hardened-process.enhanced-security-version" value must be boolean and true. Entitlement "com.apple.security.hardened-process.platform-restrictions" value must be boolean and true. When I changed those values directly in the entitlements file based on this message, the app appears to still work. However, these settings are against the description in the documentation I mentioned above and against the settings Xcode inserted after changing the GUI setting view. So, my question is, which settings are actually correct to enable the Enhanced Security and the Additional Runtime Platform Restrictions?
Replies
6
Boosts
0
Views
1.4k
Activity
Apr ’26
Production-Grade Implementation Guidance: DCError Matrices, Retry Strategies, and Simulator Testing for App Attest APIs
Hi there, We're implementing Apple's DeviceCheck App Attest for production iOS authentication. The public documentation defines DCError cases but doesn't specify which errors are expected per API method or recommend retry/remediation strategies. We need Apple's guidance to implement robust, production-aligned error handling before rollout. 1. Error Surface per API Method Question: Can you confirm the complete, officially expected set of DCError values for each method? We understand the following errors are possible across App Attest APIs: invalidKey invalidInput featureUnsupported serverUnavailable unknownSystemFailure Specifically, please confirm which errors can occur for: DCAppAttestService.generateKey() DCAppAttestService.attestKey(_:clientData:) DCAppAttestService.generateAssertion(keyID:clientData:) Are there any additional undocumented or edge-case errors we should handle? 2. Retry Strategy & Remediation Matrix Question: For each API method and error code, please help us with proposal around which errorCode is retriable, whats the remediation pre retry, retry cap and backoff strategy: Kindly also help with errors that are not covered here: Specific sub-questions: invalidKey handling: When this error occurs: Should the app delete the key and call generateKey again? Or should it fail the entire flow? serverUnavailable handling: Should we retry immediately, or wait before retrying? Is exponential backoff recommended? What's the recommended max retry count? Backoff strategy: Which errors (if any) qualify for exponential backoff? Recommended base delay, max delay, and jitter approach? When should we give up and fail the request? unknownSystemFailure: Is this retriable or should we fail? Any known causes or mitigations? 3. Simulator Testing Questions: Simulator API behavior: Can App Attest APIs be called normally on iOS Simulator? If not, is there a way to simulate for testing. Do they complete successfully with simulated attestations, or do they fail? Thanks, Nirekshitha
Replies
0
Boosts
0
Views
329
Activity
Apr ’26
launch ASWebAuthenticationSession from single sign on extenstion
I need to launch ASWebAuthenticationSession from single sign on extension, but its not launching it might issue with anchoring window, I have create custom windo and passing it in presentanchor(for session) function, custom window is launching but ASWebAuthenticationSession browser is not launching Note - flow is like this Apple PSSO register window lauched OIDC login will happen via ASWebAuthenticationSession to get accesstoken which will use in device registration but ASWebAuthenticationSession is not launching, I am using custom scheme as redirect URI iskeywindow for custom window is always false what is right approach to achieve the goal
Replies
1
Boosts
0
Views
196
Activity
Apr ’26
iPhone 16 Datasheet
I am trying to find a datasheet containing information such as "Key Exchange / Key Agreement / Key Establishment Protocols Used", "Digital Signature Algorithms Used", "Hash Algorithms Used", etc. Any information would greatly appreciated.
Replies
1
Boosts
0
Views
109
Activity
Apr ’26
TEAM ID Prefix Keychain Access
Thanks all for reading my post. A bit of context: We just finished an app transfer to our developer account. We successfully signed and generated the new release. We are already able to roll it out in testflight were we found an issue. We store valuable data in the Keychain like Authentication tokens, once the new app is installed over the old one we are experiencing a loss of all data as the keychain become "untrusted". This is worst case scenario for us because all users will immediately lose the access to the app and hence the whole system. Questions: Is there a way to solve this issue, something like migration of the Keychain data? We came to know the standard migration path: Release a version that copies items from the old access groups to a new group based on com.apple.security.application-groups (App Groups). Wait for most users to update and run the migration. Then perform the App ID prefix change. Is this still the best method? Any improvements or new tools available since the 2022 DTS post? The problem with this is that the app is already on our account and that might need to rollback the transfer. Right? How long should we realistically wait for user migration before making the prefix change? Is there a way to measure migration completion? Thank you in advance!
Replies
1
Boosts
0
Views
183
Activity
Mar ’26
password to unlock login keychain in 26.4?
I lived with knowledge that one needs to provide his login password to unlock the login keychain. This does not seem to be entirely true after upgrading Tahoe to 26.4. For example, on 26.3: Go to ~/Library/Keychains Copy login.keychain-db to different name, say test.keychain-db. Double-click on test.keychain-db -> this should open Keychain Access with test in Custom keychains section, it will appear locked. Select test keychain and press Cmd+L to unlock it. When prompted, provide your login password. Result: the keychain is unlocked. When I preform above sequence of steps on 26.4 I am not able to unlock the copied keychain (the original login keychain appears implicitly unlocked).
Replies
2
Boosts
0
Views
332
Activity
Mar ’26
Exploring Secure Enclave–backed biometric authorization between macOS and iPhone using public APIs (FaceBridge prototype)
Hi everyone, I’ve been working on an experimental prototype called FaceBridge that explores whether Secure Enclave–backed biometric authorization can be delegated between macOS and iPhone using only public Apple APIs. The goal of the project was to better understand the architectural boundaries of cross-device trust and approval flows that resemble Apple’s built-in Touch ID / Continuity authorization experiences. FaceBridge implements a local authorization pipeline where: macOS generates a signed authorization request the request is delivered to a trusted nearby iPhone over BLE / Network framework the iPhone verifies sender identity Face ID approval is requested using LocalAuthentication the iPhone signs the approval response using Secure Enclave–backed keys macOS validates the response and unlocks a protected action Security properties currently implemented: • Secure Enclave–backed signing identities per device • cryptographic device pairing and trust persistence • replay protection using nonce + timestamp binding • structured authorization request/response envelopes • signed responder identity verification • trusted-device registry model • local encrypted transport over BLE and local network This is intentionally not attempting to intercept or replace system-level Touch ID dialogs (App Store installs, Keychain prompts, loginwindow, etc.), but instead explores what is possible within application-level authorization boundaries using public APIs only. The project is open source: https://github.com/wesleysfavarin/facebridge Technical architecture write-up: https://medium.com/@wesleysfavarin/facebridge I’m particularly interested in feedback around: • recommended Secure Enclave identity lifecycle patterns • best practices for cross-device trust persistence • LocalAuthentication usage in delegated approval scenarios • whether similar authorization models are expected to become more formally supported across Apple platforms in the future Thanks in advance for any guidance or suggestions.
Replies
1
Boosts
0
Views
258
Activity
Mar ’26
Control over "\(your_app) wants to open \(another_app)" Dialog
I can't find any information about why this is happening, nor can I reproduce the 'successful' state on this device. My team needs to understand this behavior, so any insight would be greatly appreciated! The expected behavior: If I delete both apps and reinstall them, attempting to open the second app from my app should trigger the system confirmation dialog. The specifics: I'm using the MSAL library. It navigates the user to the Microsoft Authenticator app and then returns to my app. However, even after resetting the phone and reinstalling both apps, the dialog never shows up (it just opens the app directly). Does anyone know the logic behind how iOS handles these prompts or why it might be persistent even after a reset? Thanks in advance!
Replies
4
Boosts
0
Views
559
Activity
Mar ’26
TkSmartCard transmitRequest persistently returning Cryptotokenkit error -2 on iOS/iPadOS
We are using the CryptoTokenKit framework, specifically the classes TKSmartCardSlotManager, TKSmartCardSlot, and TKSmartCard, to communicate with smart cards through external USB readers on iOS and iPadOS. In most cases, we are able to detect readers via TKSmartCardSlotManager, and send APDU commands using transmitRequest method, with the following code (where self->_slot and self->_card are previously created TkSmartCardSlot and TkSmartCard, respectively): #import <CryptoTokenKit/CryptoTokenKit.h> - (NSData *)sendCardCommand:(NSData *)command { if (!self->_card || !self->_card.valid || self->_slot.state != TKSmartCardSlotStateValidCard) return nil; NSMutableData *res = [[NSMutableData alloc] init]; NSError *sessionError = nil; [self->_card inSessionWithError:&sessionError executeBlock:^BOOL(NSError **error) { dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); try { [self->_card transmitRequest:command reply:^(NSData * _Nullable response, NSError* _Nullable apduError) { if (apduError != nil) self->_error = apduError; else [res appendData: response]; dispatch_semaphore_signal(semaphore); }]; } catch (NSException *exception) { dispatch_semaphore_signal(semaphore); } dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); if (res.length == 0) return NO; return YES; }]; return res; } However, with certain other USB smart card readers, we occasionally encounter APDU communication failures when calling transmitRequest (for instance, with a HID Global OMNIKEY 5422), which returns the following error: "Domain: CryptoTokenKit Code: -2". Once a failure occurs and transmitRequest starts returning this error, all subsequent calls to transmitRequest fail with the same error. This persists even when: A different smart card is inserted The same card is reinserted A different USB reader (previously working correctly) is connected The TKSmartCard object is recreated via makeSmartCard The slot state changes (observed via KVO) All internal objects (TKSmartCard, TKSmartCardSlot) are reset in the application At this point, the system appears to be stuck in a non-recoverable state which affects all readers and cards, including those that were previously functioning correctly. The only way to recover from this state is terminating and restarting the application which is running the code. After restarting the app, everything works normally again. We have created a bug report: FB22339746. The issue has been reproduced on iOS 26.4 and 18.5. Also on iPadOS 18.1. Anyone has already faced a similar issue? Could it be related to some internal state of TKSmartCardSlotManager?
Replies
2
Boosts
0
Views
294
Activity
Mar ’26
Endpoint Security entitlement for open-source behavioral monitoring tool
Hi, I’m building a macOS tool that analyzes process behavior to detect autonomous / AI-like activity locally (process trees, file access patterns, and network usage). The system is fully user-space and runs locally in real time. I’m planning to use the Endpoint Security Framework for process and file event monitoring. This is an open-source project (non-enterprise), developed by a solo developer. My question: What are the realistic chances of getting Endpoint Security entitlements approved for this type of project? Are there specific requirements or common reasons for rejection I should be aware of? Thanks, sivan-rnd
Replies
2
Boosts
0
Views
214
Activity
Mar ’26
MFA MacOS At ScreenSaver (Lock Screen).
Hi , I did The MFA(2FA) of Email OTP For MacOS Login Screen using, Authorization Plugin, Using This git hub project. It is working For Login Screen , Im trying to Add The Same plugin for LockScreen but it is not working at lock Screen , Below is the reffrense theard For The issue , https://developer.apple.com/forums/thread/127614, please Share The Code that should Present the NSwindow at Screen Saver (Lock Screen) MacOS .
Replies
3
Boosts
0
Views
1.1k
Activity
Mar ’26
Need help learning security and persistence for Swift!!!
Hello, sorry for the awkward text formatting but I kept getting prevented from positing due to "sensitive language"... Help.txt
Replies
2
Boosts
0
Views
622
Activity
Mar ’26