We are using ASWebAuthenticationSession with apps on IoS to achieve SSO between apps. The IdP for authentication (OIDC) is an on-premise and trusted enterprise IdP based on one of the leading products in the market. Our problem is that the user is prompted for every login (and logouts) with a consent dialogue box:
“AppName” wants to use “internal domain-name” to Sign In
This allows the app and website to share information about you.
Cancel Continue”
I have read in various places that Apple has a concept of “Trusted domains” where you can put an “Apple certified” static web-page on the IdP. This page needs to contain specific metadata that iOS can verify. Once a user logs in successfully a few times, and if the IdP is verified as trusted, subsequent logins would not prompt the consent screen.
Question: I struggle to find Apple documentation on how to go about a process that ends with this “Apple certified web-page” on our IdP”. Anyone who has experience with this process, or who can point me in some direction to find related documentation?
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
General:
Forums subtopic: Privacy & Security > General
Forums tag: App Sandbox
App Sandbox documentation
App Sandbox Design Guide documentation — This is no longer available from Apple. There’s still some info in there that isn’t covered by the current docs but, with the latest updates, it’s pretty minimal (r. 110052019). Still, if you’re curious, you can consult an old copy [1].
App Sandbox Temporary Exception Entitlements archived documentation — To better understand the role of temporary exception entitlements, see this post.
Embedding a command-line tool in a sandboxed app documentation
Discovering and diagnosing App Sandbox violations (replaces the Viewing Sandbox Violation Reports forums post)
Resolving App Sandbox Inheritance Problems forums post
The Case for Sandboxing a Directly Distributed App forums post
Implementing Script Attachment in a Sandboxed App forums post
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] For example, this one archived by the Wayback Machine.
I regularly help developers with keychain problems, both here on DevForums and for my Day Job™ in DTS. Many of these problems are caused by a fundamental misunderstanding of how the keychain works. This post is my attempt to explain that. I wrote it primarily so that Future Quinn™ can direct folks here rather than explain everything from scratch (-:
If you have questions or comments about any of this, put them in a new thread and apply the Security tag so that I see it.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
SecItem: Fundamentals
or How I Learned to Stop Worrying and Love the SecItem API
The SecItem API seems very simple. After all, it only has four function calls, how hard can it be? In reality, things are not that easy. Various factors contribute to making this API much trickier than it might seem at first glance.
This post explains the fundamental underpinnings of the keychain. For information about specific issues, see its companion post, SecItem: Pitfalls and Best Practices.
Keychain Documentation
Your basic starting point should be Keychain Items.
If your code runs on the Mac, also read TN3137 On Mac keychain APIs and implementations.
Read the doc comments in <Security/SecItem.h>. In many cases those doc comments contain critical tidbits.
When you read keychain documentation [1] and doc comments, keep in mind that statements specific to iOS typically apply to iPadOS, tvOS, and watchOS as well (r. 102786959). Also, they typically apply to macOS when you target the data protection keychain. Conversely, statements specific to macOS may not apply when you target the data protection keychain.
[1] Except TN3137, which is very clear about this (-:
Caveat Mac Developer
macOS supports two different keychain implementations: the original file-based keychain and the iOS-style data protection keychain.
IMPORTANT If you’re able to use the data protection keychain, do so. It’ll make your life easier. See the Careful With that Shim, Mac Developer section of SecItem: Pitfalls and Best Practices for more about this.
TN3137 On Mac keychain APIs and implementations explains this distinction. It also says:
The file-based keychain is on the road to deprecation.
This is talking about the implementation, not any specific API. The SecItem API can’t be deprecated because it works with both the data protection keychain and the file-based keychain. However, Apple has deprecated many APIs that are specific to the file-based keychain, for example, SecKeychainCreate.
TN3137 also notes that some programs, like launchd daemons, can’t use the file-based keychain. If you’re working on such a program then you don’t have to worry about the deprecation of these file-based keychain APIs. You’re already stuck with the file-based keychain implementation, so using a deprecated file-based keychain API doesn’t make things worse.
The Four Freedoms^H^H^H^H^H^H^H^H Functions
The SecItem API contains just four functions:
SecItemAdd(_:_:)
SecItemCopyMatching(_:_:)
SecItemUpdate(_:_:)
SecItemDelete(_:)
These directly map to standard SQL database operations:
SecItemAdd(_:_:) maps to INSERT.
SecItemCopyMatching(_:_:) maps to SELECT.
SecItemUpdate(_:_:) maps to UPDATE.
SecItemDelete(_:) maps to DELETE.
You can think of each keychain item class (generic password, certificate, and so on) as a separate SQL table within the database. The rows of that table are the individual keychain items for that class and the columns are the attributes of those items.
Note Except for the digital identity class, kSecClassIdentity, where the values are split across the certificate and key tables. See Digital Identities Aren’t Real in SecItem: Pitfalls and Best Practices.
This is not an accident. The data protection keychain is actually implemented as an SQLite database. If you’re curious about its structure, examine it on the Mac by pointing your favourite SQLite inspection tool — for example, the sqlite3 command-line tool — at the keychain database in ~/Library/Keychains/UUU/keychain-2.db, where UUU is a UUID.
WARNING Do not depend on the location and structure of this file. These have changed in the past and are likely to change again in the future. If you embed knowledge of them into a shipping product, it’s likely that your product will have binary compatibility problems at some point in the future. The only reason I’m mentioning them here is because I find it helpful to poke around in the file to get a better understanding of how the API works.
For information about which attributes are supported by each keychain item class — that is, what columns are in each table — see the Note box at the top of Item Attribute Keys and Values. Alternatively, look at the Attribute Key Constants doc comment in <Security/SecItem.h>.
Uniqueness
A critical part of the keychain model is uniqueness. How does the keychain determine if item A is the same as item B? It turns out that this is class dependent. For each keychain item class there is a set of attributes that form the uniqueness constraint for items of that class. That is, if you try to add item A where all of its attributes are the same as item B, the add fails with errSecDuplicateItem. For more information, see the errSecDuplicateItem page. It has lists of attributes that make up this uniqueness constraint, one for each class.
These uniqueness constraints are a major source of confusion, as discussed in the Queries and the Uniqueness Constraints section of SecItem: Pitfalls and Best Practices.
Parameter Blocks Understanding
The SecItem API is a classic ‘parameter block’ API. All of its inputs are dictionaries, and you have to know which properties to set in each dictionary to achieve your desired result. Likewise for when you read properties in output dictionaries.
There are five different property groups:
The item class property, kSecClass, determines the class of item you’re operating on: kSecClassGenericPassword, kSecClassCertificate, and so on.
The item attribute properties, like kSecAttrAccessGroup, map directly to keychain item attributes.
The search properties, like kSecMatchLimit, control how the system runs a query.
The return type properties, like kSecReturnAttributes, determine what values the query returns.
The value type properties, like kSecValueRef perform multiple duties, as explained below.
There are other properties that perform a variety of specific functions. For example, kSecUseDataProtectionKeychain tells macOS to use the data protection keychain instead of the file-based keychain. These properties are hard to describe in general; for the details, see the documentation for each such property.
Inputs
Each of the four SecItem functions take dictionary input parameters of the same type, CFDictionary, but these dictionaries are not the same. Different dictionaries support different property groups:
The first parameter of SecItemAdd(_:_:) is an add dictionary. It supports all property groups except the search properties.
The first parameter of SecItemCopyMatching(_:_:) is a query and return dictionary. It supports all property groups.
The first parameter of SecItemUpdate(_:_:) is a pure query dictionary. It supports all property groups except the return type properties.
Likewise for the only parameter of SecItemDelete(_:).
The second parameter of SecItemUpdate(_:_:) is an update dictionary. It supports the item attribute and value type property groups.
Outputs
Two of the SecItem functions, SecItemAdd(_:_:) and SecItemCopyMatching(_:_:), return values. These output parameters are of type CFTypeRef because the type of value you get back depends on the return type properties you supply in the input dictionary:
If you supply a single return type property, except kSecReturnAttributes, you get back a value appropriate for that return type.
If you supply multiple return type properties or kSecReturnAttributes, you get back a dictionary. This supports the item attribute and value type property groups. To get a non-attribute value from this dictionary, use the value type property that corresponds to its return type property. For example, if you set kSecReturnPersistentRef in the input dictionary, use kSecValuePersistentRef to get the persistent reference from the output dictionary.
In the single item case, the type of value you get back depends on the return type property and the keychain item class:
For kSecReturnData you get back the keychain item’s data. This makes most sense for password items, where the data holds the password. It also works for certificate items, where you get back the DER-encoded certificate. Using this for key items is kinda sketchy. If you want to export a key, called SecKeyCopyExternalRepresentation. Using this for digital identity items is nonsensical.
For kSecReturnRef you get back an object reference. This only works for keychain item classes that have an object representation, namely certificates, keys, and digital identities. You get back a SecCertificate, a SecKey, or a SecIdentity, respectively.
For kSecReturnPersistentRef you get back a data value that holds the persistent reference.
Value Type Subtleties
There are three properties in the value type property group:
kSecValueData
kSecValueRef
kSecValuePersistentRef
Their semantics vary based on the dictionary type.
For kSecValueData:
In an add dictionary, this is the value of the item to add. For example, when adding a generic password item (kSecClassGenericPassword), the value of this key is a Data value containing the password.
This is not supported in a query dictionary.
In an update dictionary, this is the new value for the item.
For kSecValueRef:
In add and query dictionaries, the system infers the class property and attribute properties from the supplied object. For example, if you supply a certificate object (SecCertificate, created using SecCertificateCreateWithData), the system will infer a kSecClass value of kSecClassCertificate and various attribute values, like kSecAttrSerialNumber, from that certificate object.
This is not supported in an update dictionary.
For kSecValuePersistentRef:
For query dictionaries, this uniquely identifies the item to operate on.
This is not supported in add and update dictionaries.
Revision History
2025-05-28 Expanded the Caveat Mac Developer section to cover some subtleties associated with the deprecation of the file-based keychain.
2023-09-12 Fixed various bugs in the revision history. Added a paragraph explaining how to determine which attributes are supported by each keychain item class.
2023-02-22 Made minor editorial changes.
2023-01-28 First posted.
Hi everyone,
I’m working on adapting our app to iOS 26’s new passkey feature, specifically Automatic Passkey Upgrades.
https://developer.apple.com/videos/play/wwdc2025/279/
Our app already supports passkey registration and authentication, which have been running reliably in production. We’d like to extend passkey coverage to more users.
According to the WWDC session, adding the parameter requestStyle: .conditional to createCredentialRegistrationRequest should allow the system to seamlessly upgrade an account with a passkey. However, in my testing, I consistently receive the following error:
Error | Error Domain=com.apple.AuthenticationServices.AuthorizationError Code=1001 "(null)"
Test environment:
Xcode 26.0 beta 4 (17A5285i)
iPhone 11 running iOS 26.0 (23A5297n)
Questions:
Is the Automatic Passkey Upgrades feature currently available in iOS 26?
I understand that the system may perform internal checks and not all upgrade attempts will succeed. However, during development, is there a way to obtain more diagnostic information? At the moment, it’s unclear whether the failure is due to internal validation or an issue with my code or environment.
Thanks.
Using personal physical iPhone for simulations. Can't get Keychain to read or store AppleID name/email. I want to avoid hard reseting physical phone.
Logs confirm Keychain is working, but userIdentifier and savedEmail are not being stored correctly.
🔄 Initializing UserManager...
✅ Saved testKeychain to Keychain: Test Value
✅ Retrieved testKeychain from Keychain: Test Value
🔍 Keychain Test - Retrieved Value: Test Value
⚠️ Keychain Retrieve Warning: No stored value found for userIdentifier
⚠️ Keychain Retrieve Warning: No stored value found for savedEmail
🔍 Debug - Retrieved from Keychain: userIdentifier=nil, savedEmail=nil
⚠️ No stored userIdentifier in Keychain. User needs to sign in.
📦 Converting User to CKRecord: Unknown, No Email
✅ User saved locally: Unknown, No Email
✅ User saved to CloudKit: Unknown, No Email
Below UserManager.swift if someone can help troubleshoot. Or step by step tutorial to configure a project and build a User Login & User Account creation for Apple Only app.
import Foundation
import CloudKit
import AuthenticationServices
import SwiftData
@MainActor
class UserManager: ObservableObject {
@Published var user: User?
@Published var isLoggedIn = false
@Published var errorMessage: String?
private let database = CKContainer.default().publicCloudDatabase
init() {
print("🔄 Initializing UserManager...")
// 🔍 Keychain Debug Test
let testKey = "testKeychain"
KeychainHelper.shared.save("Test Value", forKey: testKey)
let retrievedValue = KeychainHelper.shared.retrieve(forKey: testKey)
print("🔍 Keychain Test - Retrieved Value: \(retrievedValue ?? "nil")")
fetchUser() // Continue normal initialization
}
// ✅ Sign in & Save User
func handleSignIn(_ authResults: ASAuthorization) {
guard let appleIDCredential = authResults.credential as? ASAuthorizationAppleIDCredential else {
errorMessage = "Error retrieving Apple credentials"
print("❌ ASAuthorization Error: Invalid credentials received")
return
}
let userIdentifier = appleIDCredential.user
let fullName = appleIDCredential.fullName?.givenName ?? retrieveSavedName()
var email = appleIDCredential.email ?? retrieveSavedEmail()
print("🔍 Apple Sign-In Data: userIdentifier=\(userIdentifier), fullName=\(fullName), email=\(email)")
// 🔄 If Apple doesn't return an email, check if it exists in Keychain
if appleIDCredential.email == nil {
print("⚠️ Apple Sign-In didn't return an email. Retrieving saved email from Keychain.")
}
// ✅ Store userIdentifier & email in Keychain
KeychainHelper.shared.save(userIdentifier, forKey: "userIdentifier")
KeychainHelper.shared.save(email, forKey: "savedEmail")
let newUser = User(fullName: fullName, email: email, userIdentifier: userIdentifier)
saveUserToCloudKit(newUser)
}
func saveUserToCloudKit(_ user: User) {
let record = user.toRecord()
Task {
do {
try await database.save(record)
DispatchQueue.main.async {
self.user = user
self.isLoggedIn = true
self.saveUserLocally(user)
print("✅ User saved to CloudKit: \(user.fullName), \(user.email)")
}
} catch {
DispatchQueue.main.async {
self.errorMessage = "Error saving user: \(error.localizedDescription)"
print("❌ CloudKit Save Error: \(error.localizedDescription)")
}
}
}
}
// ✅ Fetch User from CloudKit
func fetchUser() {
let userIdentifier = KeychainHelper.shared.retrieve(forKey: "userIdentifier")
let savedEmail = KeychainHelper.shared.retrieve(forKey: "savedEmail")
print("🔍 Debug - Retrieved from Keychain: userIdentifier=\(userIdentifier ?? "nil"), savedEmail=\(savedEmail ?? "nil")")
guard let userIdentifier = userIdentifier else {
print("⚠️ No stored userIdentifier in Keychain. User needs to sign in.")
return
}
let predicate = NSPredicate(format: "userIdentifier == %@", userIdentifier)
let query = CKQuery(recordType: "User", predicate: predicate)
Task { [weak self] in
guard let self = self else { return }
do {
let results = try await self.database.records(matching: query, resultsLimit: 1).matchResults
if let (_, result) = results.first {
switch result {
case .success(let record):
DispatchQueue.main.async {
let fetchedUser = User(record: record)
self.user = User(
fullName: fetchedUser.fullName,
email: savedEmail ?? fetchedUser.email,
userIdentifier: userIdentifier
)
self.isLoggedIn = true
self.saveUserLocally(self.user!)
print("✅ User loaded from CloudKit: \(fetchedUser.fullName), \(fetchedUser.email)")
}
case .failure(let error):
DispatchQueue.main.async {
print("❌ Error fetching user from CloudKit: \(error.localizedDescription)")
}
}
}
} catch {
DispatchQueue.main.async {
print("❌ CloudKit fetch error: \(error.localizedDescription)")
}
}
}
}
// ✅ Save User Locally
private func saveUserLocally(_ user: User) {
if let encoded = try? JSONEncoder().encode(user) {
UserDefaults.standard.set(encoded, forKey: "savedUser")
UserDefaults.standard.set(user.fullName, forKey: "savedFullName")
UserDefaults.standard.set(user.email, forKey: "savedEmail")
print("✅ User saved locally: \(user.fullName), \(user.email)")
} else {
print("❌ Local Save Error: Failed to encode user data")
}
}
// ✅ Retrieve Previously Saved Name
private func retrieveSavedName() -> String {
return UserDefaults.standard.string(forKey: "savedFullName") ?? "Unknown"
}
// ✅ Retrieve Previously Saved Email
private func retrieveSavedEmail() -> String {
return KeychainHelper.shared.retrieve(forKey: "savedEmail") ?? UserDefaults.standard.string(forKey: "savedEmail") ?? "No Email"
}
// ✅ Sign Out
func signOut() {
isLoggedIn = false
user = nil
UserDefaults.standard.removeObject(forKey: "savedUser")
print("🚪 Signed Out")
}
}
Topic:
Privacy & Security
SubTopic:
General
Tags:
Sign in with Apple
Authentication Services
iCloud Keychain Verification Codes
WebAuthn Level 3 § 6.3.2 Step 2 states the authenticator must :
Check if at least one of the specified combinations of PublicKeyCredentialType and cryptographic parameters in credTypesAndPubKeyAlgs is supported. If not, return an error code equivalent to "NotSupportedError" and terminate the operation.
On my iPhone 15 Pro Max running iOS 18.5, Safari + Passwords does not exhibit this behavior; instead an error is not reported and an ES256 credential is created when an RP passes a non-empty sequence that does not contain {"type":"public-key","alg":-7} (e.g., [{"type":"public-key","alg":-8}]).
When I use Chromium 138.0.7204.92 on my laptop running Arch Linux in conjunction with the Passwords app (connected via the "hybrid" protocol), a credential is not created and instead an error is reported per the spec.
Feedback report id: FB16605524
I'm trying to send emails to private relay service addresses using AWS SES and emails are not received. My emails are sent from dev@mydomain.fr and I've set a custom FROM domain of mail.mydomain.fr. I've added both domains and the dev@mydomain.fr adress to the "Certificates, Identifies & Profiles" section. I've set up DKIM and SPF for both.
Attached a redacted version of email headers.
email_headers_redacted.txt
I modified the system.login.screensaver rule in the authorization database to use "authenticate" instead of "use-login-window-ui" to display a custom authentication plugin view when the screensaver starts or the screen locks.
However, I noticed an issue when the "Require Password after Display is Turned Off" setting is set to 5 minutes in lock screen settings:
If I close my Mac’s lid and reopen it within 5 minutes, my authentication plugin view is displayed as expected.
However, the screen is not in a locked state—the desktop remains accessible, and the black background that typically appears behind the lock screen is missing.
This behavior differs from the default lock screen behavior, where the screen remains fully locked, and the desktop is hidden.
Has anyone encountered this issue before? Is there a way to ensure the screen properly locks when using authenticate in the screensaver rule?
This is on macOS, not iOS. Not sure if that should make a difference?
I have a GUI app and a command line tool (that will run a daemon) that I need to share credentials between. The keys/certs will be stored using the GUI app. But, both tools need to utilize them.
guard let accessControl = SecAccessControlCreateWithFlags(
nil,
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
[.privateKeyUsage],
nil
) else {
throw KeychainCertError.keychainError(errSecAuthFailed, "Failed to create access control for private key")
}
// Define Key Pair Attributes
let privateKeyAttributes: [String: Any] = [
kSecAttrIsPermanent as String: true,
kSecAttrApplicationTag as String: privateLabel.data(using: .utf8)!,
kSecAttrLabel as String: privateLabel,
// kSecAttrAccessControl as String: accessControl,
kSecAttrAccessGroup as String: keychainAccessGroup
]
With the kSecAttrAccessControl commented out, I am able to generate a private key and generate a self signed certificate that is stored on the user login keychain. If I uncomment that line, I get an error to the affect of "Keychain error (-26275): Failed to generate key pair: A required entitlement isn't present"
Also, to share the credentials, don't they need to be NOT on the user keychain for the daemon to access them?
Any ideas what I am doing wrong? I think I'm a bit over my head here with the the security, crypto kit and openssl. 😁
When developing and testing using my phone I got prompted for allowing app tracking. I later uploaded a build to TestFlight, deleted the old testing app and installed the TestFlight build. I am now stuck in an infinite loop of not getting prompted for allowing app tracking for the app. When entering the app settings the toggle for tracking never appears which leaves me not able to enter the app's content. My guess is that the prompt can only be shown once for the app bundle, but there has to be a way for me to get prompted again without changing the app bundle id. Help is appreciated since this app is scheduled to be published in a week.
Hi everyone,
I'm encountering an issue where the background location indicator remains visible on the status bar even though I have set the location permissions to Never for my app in the system settings. Despite taking all the necessary steps to stop location tracking (including stopping updates, geofencing, and other location-related services), the indicator still appears. This seems to be a bug since everything has been turned off on my end.
Here’s what I’ve already tried:
Setting location permissions to Never in the settings.
Stopping startUpdatingLocation(), stopMonitoringSignificantLocationChanges(), and geofencing (using locationManager.stopMonitoringRegions()).
Calling locationManager.showsBackgroundLocationIndicator = false.
Ensuring that the CLLocationManager is fully invalidated.
Despite all of this, the background location indicator still remains in the status bar. I’ve tested it on real devices, as well as in the simulator, with no improvement.
Has anyone experienced something similar, or can suggest why this might be happening? Could this be related to an iOS 18+ issue?
Any insights or guidance would be greatly appreciated.
Hello,
When using ASWebAuthenticationSession with an HTTPS callback URL (Universal Link), I receive the following error:
Authorization error: The operation couldn't be completed.
Application with identifier jp.xxxx.yyyy.dev is not associated with domain xxxx-example.go.link.
Using HTTPS callbacks requires Associated Domains using the webcredentials service type for xxxx-example.go.link.
I checked Apple’s official documentation but couldn’t find any clear statement that webcredentials is required when using HTTPS callbacks in ASWebAuthenticationSession.
What I’d like to confirm:
Is webcredentials officially required when using HTTPS as a callback URL with ASWebAuthenticationSession?
If so, is there any official documentation or technical note that states this requirement?
Environment
iOS 18.6.2
Xcode 16.4
Any clarification or official references would be greatly appreciated.
Thank you.
Topic:
Privacy & Security
SubTopic:
General
Tags:
iOS
Security
Authentication Services
Universal Links
I’d like to submit a feature request regarding the availability of Foundation Models in MessageFilter extensions.
Background
MessageFilter extensions play a critical role in protecting users from spam, phishing, and unwanted messages. With the introduction of Foundation Models and Apple Intelligence, Apple has provided powerful on-device natural language understanding capabilities that are highly aligned with the goals of MessageFilter.
However, Foundation Models are currently unavailable in MessageFilter extensions.
Why Foundation Models Are a Great Fit for MessageFilter
Message filtering is fundamentally a natural language classification problem. Foundation Models would significantly improve:
Detection of phishing and scam messages
Classification of promotional vs transactional content
Understanding intent, tone, and semantic context beyond keyword matching
Adaptation to evolving scam patterns without server-side processing
All of this can be done fully on-device, preserving user privacy and aligning with Apple’s privacy-first design principles.
Current Limitations
Today, MessageFilter extensions are limited to relatively simple heuristics or lightweight models. This often results in:
Higher false positives
Lower recall for sophisticated scam messages
Increased development complexity to compensate for limited NLP capabilities
Request
Could Apple consider one of the following:
Allowing Foundation Models to be used directly within MessageFilter extensions
Providing a constrained or optimized Foundation Model API specifically designed for MessageFilter
Enabling a supported mechanism for MessageFilter extensions to delegate inference to the containing app using Foundation Models
Even limited access (e.g. short text only, strict execution limits) would be extremely valuable.
Closing
Foundation Models have the potential to significantly raise the quality and effectiveness of message filtering on Apple platforms while maintaining strong privacy guarantees. Supporting them in MessageFilter extensions would be a major improvement for both developers and users.
Thank you for your consideration and for continuing to invest in on-device intelligence.
Hi,
I am in need of your help with publishing my game.
I got the following explanation for the negative review of my app/game.
Issue Description
One or more purpose strings in the app do not sufficiently explain the use of protected resources. Purpose strings must clearly and completely describe the app's use of data and, in most cases, provide an example of how the data will be used.
Next Steps
Update the local network information purpose string to explain how the app will use the requested information and provide a specific example of how the data will be used. See the attached screenshot.
Resources
Purpose strings must clearly describe how an app uses the ability, data, or resource. The following are hypothetical examples of unclear purpose strings that would not pass review:
"App would like to access your Contacts"
"App needs microphone access"
See examples of helpful, informative purpose strings.
The problem is that they say my app asks to allow my app to find devices on local networks. And that this needs more explanation in the purpose strings.
Totally valid to ask, but the problem is my app doesn't need local access to devices, and there shouldn't be code that asks this?? FYI the game is build with Unity.
Would love some help on how to turn this off so that my app can get published.
Our application uses device check api to validate the device token in staging server. We are using "https://api.development.devicecheck.apple.com/v1/validate_device_token"for this.But the response is 500 internal server error.
Our production build is working fine.We pointed the build to "https://api.devicecheck.apple.com/v1/validate_device_token" url.We are using the same device check key for both development and production server.
Device check was working fine in development server also.Suddenly it started to failed with out making any changes in our code.
Hello,
I am developing a macOS menu bar window-management utility (similar in functionality to Magnet / Rectangle) that relies on the Accessibility (AXUIElement) API to move and resize windows and on global hotkeys.
I am facing a consistent issue when App Sandbox is enabled.
Summary:
App Sandbox enabled
Hardened Runtime enabled
Apple Events entitlement enabled
NSAccessibilityDescription present in Info.plist
AXIsProcessTrustedWithOptions is called with prompt enabled
Observed behavior:
When App Sandbox is enabled, the Accessibility permission prompt never appears.
The app cannot be manually added in System Settings → Privacy & Security → Accessibility.
AXIsProcessTrusted always returns false.
As a result, window snapping does not work.
When App Sandbox is disabled:
The Accessibility prompt appears correctly.
The app functions as expected.
This behavior occurs both:
In local builds
In TestFlight builds
My questions:
Is this expected behavior for sandboxed macOS apps that rely on Accessibility APIs?
Are window-management utilities expected to ship without App Sandbox enabled?
Is there any supported entitlement or configuration that allows a sandboxed app to request Accessibility permission?
Thank you for any clarification.
Topic:
Privacy & Security
SubTopic:
General
completeRequestWithTextToInsert is used to return text into an arbitrary textfield via the context menu AutoFill/Passwords from a 3rd party password manager (or presumably the Passwords App) in iOS 18.
While testing this feature in the debugger, it would often fail on the first invocation. It also appears to happen intermittently in the released app extension. Subsequent testing using the Passwords App shows it too may fail to return a value.
I have confirmed this behaviour is repeatable with the Passwords App on an iPhone running iOS 18.3.1
Reboot the iPhone.
Show the App Library, and right click Autofill.
Select Passwords
Select Passwords (App)
Select a password.
Nothing will be inserted (intermittently).
Feedback assistant report: FB16788563
Hi, I’ve added attestation to my app, and everything worked as expected during setup. However, after deployment, I noticed some unknownSystemFailure entries in the production logs on New Relic. Could you help me understand what typically causes this error? The documentation suggests issues such as failing to generate a token. What scenarios could lead to that?
I'm using the following code to store a Keychain item:
SecAccessControlCreateWithFlags(
kCFAllocatorDefault,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
.biometryAny,
&error
)
One of my app users reported an issue:
1. The user navigated to his iPhone’s Face ID settings and click `Reset Face ID`.
2. Then, before he set new Face ID, he accidentally tapped the "Back" button and returned to the iPhone Settings page.
3. He later reopened the Face ID setup page and completed the process.
4. Upon returning to my app, the Keychain item secured by Face ID was no longer found.
I understand that .biometryAny may cause Keychain items to become invalidated when biometric data is reset. However, the user’s scenario — where the setup was temporarily interrupted — seems to have caused the item to disappear.
1. Is there a way to detect and handle such interruptions to prevent the Keychain item from being lost?
2. How can I design a better experience to guide the user in recreating the Keychain item when this occurs?
Topic:
Privacy & Security
SubTopic:
General
We recently upgraded OpenSSL from version 1.1.1 to 3.4.0. After this upgrade, we observed that PKCS#12 files generated using OpenSSL 3.4.0 fail to import into the macOS Keychain with the following error:
Failed to import PKCS#12 data: -25264
(MAC verification failed during PKCS12 import (wrong password?))
This issue is reproducible on macOS 14.8.2. The same PKCS#12 files import successfully on other macOS versions, including 15.x and 26.x.
Additionally, PKCS#12 files that fail to import on macOS 14.8 work correctly when copied and imported on other macOS versions without any errors.
PKCS#12 Creation
The PKCS#12 data is created using the following OpenSSL API:
const char* platformPKCS12SecureKey =
_platformSecureKey.has_value() ? _platformSecureKey.value().c_str() : NULL;
PKCS12* p12 = PKCS12_create(
platformPKCS12SecureKey,
NULL,
keys,
_cert,
NULL,
0, 0, 0, 0, 0
);
if (!p12)
{
throw std::runtime_error("Failed to create PKCS#12 container");
}
PKCS#12 Import
The generated PKCS#12 data is imported into the macOS Keychain using the following code:
NSString *certPassKey = [NSString stringWithUTF8String:getCertPassKey()];
NSDictionary *options = @{
(__bridge id)kSecImportExportPassphrase: certPassKey,
(__bridge id)kSecAttrAccessible:
(__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
(__bridge id)kSecAttrIsExtractable: @YES,
(__bridge id)kSecAttrIsPermanent: @YES,
(__bridge id)kSecAttrAccessGroup: APP_GROUP
};
CFArrayRef items = NULL;
OSStatus status = SecPKCS12Import(
(__bridge CFDataRef)pkcs12Data,
(__bridge CFDictionaryRef)options,
&items
);
Topic:
Privacy & Security
SubTopic:
General
Tags:
macOS
Signing Certificates
iCloud Keychain Verification Codes
Passkeys in iCloud Keychain