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

Post

Replies

Boosts

Views

Activity

L4 Per-App VPN is not working with iOS 18 Beta
We are not seeing any traffic from iOS to App-Proxy extension. We have a Safari domains specified in the per App App Proxy VPN configuration which is pushed to our device. When we tap on the safari and start loading one of these domains, safari will not load any websites with these domains. But if we load any other websites with any other domain, the websites are loaded properly. But the same behavior works fine and app receives traffic on iOS 17.5.1 and older iOS versions. The issue is observed only on iOS 18 Beta versions.
0
0
16
46m
SFAuthorizationPluginView Implementation in Swift
Hi, I am currently trying to develop an authorization plugin using SFAuthorizationPluginView. My objective is to display a webView to the user for authentication purposes. I have based my work on the updated NameandPassword example : https://github.com/antoinebell/NameAndPassword. I have seen that the header for the SFAuthorizationPluginView class exists in Swift. However, I have not found any implementation examples of an authorization plugin in Swift. I have attempted to implement this on my own but am encountering difficulties displaying my embedded view within a ViewController. Is it possible to create an authorization plug-in in Swift ?
0
0
93
2d
System Keychain not available from a Daemon
I've been trying to use Keychain from a Daemon for some time now. In the end, I managed to have the System Keychain work for my application and I moved to work on other parts. I finally went back to dealing with Keychain, but the code I wrote before stopped working. Even the application I wrote to test things out stopped working for me, and now it gives the The authorization was denied. error. To give more perspective into what I am doing, I am running a Sandboxed Launch Daemon wrapped in an App-like structure. I register it from my main app via SMAppService API. I also have a System Extension. My test app was structured in the same way and I used the following code to put a new key into the System Keychain and get its reference: var err: Unmanaged<CFError>? let access = SecAccessCreateWithOwnerAndACL(getuid(), getgid(), UInt32(kSecUseOnlyUID | kSecHonorRoot), nil, &err) if let err = err { log.error("Failed to create SecAccess: \(err.takeUnretainedValue().localizedDescription)") } let request = [ kSecClass: kSecClassGenericPassword, kSecAttrService: service, kSecAttrAccount: account, kSecValueData: passwordData, kSecAttrAccess: access as Any, kSecAttrSynchronizable: false, kSecUseDataProtectionKeychain: false, kSecReturnPersistentRef: true, ] as [String: Any] var result: CFTypeRef? let status = SecItemAdd(request as CFDictionary, &result) The goal of this was to share some secrets with a System Extension. The code above worked for me some time ago and I was able to use the System Keychain from my sandboxed daemon. Am I missing something again? Did something change in the meantime? Or did I do something last time that I haven't noticed? Should I cut my losses and avoid Keychain since Apple will not support it anyway?
0
0
102
2d
Local Network Access Permission
We provide software that our customers deploy on their employee work computers to secure sensitive data. We have a daemon which could connect to an on-premise web-server for certain functionality. In Mac OS 15 beta we see that there is a local network access permission dialog that comes up sometimes, and it requires a permission to be provided under the Privacy & Security section of the system preferences. We have seen the local network access permission would pop up only when both Server and Client are residing in the same private network range (eg 172.16.x.x. in our case.) When the same server is accessed from a Sequoia machine over a VPN from external network, the local network access permission does NOT pop up. But note in this case, the Sequoia machine has an IP in the 10.x.y.z range, whereas the server is at 172.16.x.y. We have the following questions: In our setup with Macs connecting to a web-server, what conditions can trigger the local network prompt? In particular, do both the client and server need to be in the same private subnet range for the prompt to be shown? Is it possible that a user at home, working on a Sequoia machine, connecting over VPN to an on-prem server, would trigger this prompt? If so, we would submit this is not expected, as a VPN is not really a local network. Is there an MDM way of automatically providing the permission, so that the prompt is suppressed? In general, is there a programmatic way of providing this permission during installation ? if yes how can we do it. How do we stop users from disabling the permission incase the user has admin rights?
0
1
41
2d
Local Network Access Permision
We are having a daemon which could connect to a on premise server for certain functionality. In Mac OS 15 beta we see that there is a local network access permission dialog when coming up and it requires a permission to be provided under privacy&security section of the system preferences. Now we have also observed following behaviour also in local network access. The local network access permission would pop up only when both Server and Client are residing in the same network say (172.16.x.x.) in our case. The same server when accessed using a machine which is connected to the server using a VPN from external network "local network access permission does not pop up". We have following queries for the above observations. Is there an MDM way of providing the permission ? How do we stop users from disabling the permission incase the user has admin rights? Is there a programatic way of providing this permission during installation ? if yes how can we do it. Another general question would be like does it really need a local network access permission this case ? how to navigate this as all most every other enterprise app might be facing this issue.
0
0
41
2d
Keychain Access kSecAttrAccessibleAfterFirstUnlock
Hey guys, first time posting here. I've been working on a common library that is shared across multiple apps. The purpose of it is to store data in the keychain (with the kSecAttrAccessibleAfterFirstUnlock flag) and that data should be available to be read by any app in the group. Everything works in normal use cases, like, user switches from an app to another, the data is there and read. But there are some edge cases reported by some devices that the data is not there when being read (via push notification) when the device is locked. Note that this not something that happens 100% of the time. Here's my write/read/delete code (it's quite objective-c code) : // // Internal methods // - (NSDictionary *)read:(NSString *)key forGroup:(NSString *)groupId { NSMutableDictionary *query = [self queryData:groupId]; query[(__bridge id)kSecAttrAccount] = key; query[(__bridge id)kSecReturnData] = (__bridge id)kCFBooleanTrue; CFDataRef resultData = NULL; OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef*)&resultData); NSDictionary *value; if (status == noErr) { value = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData*)resultData]; } return value; } - (BOOL)write:(NSDictionary *)value forKey:(NSString *)key forGroup:(NSString *)groupId { NSMutableDictionary *query = [self queryData:groupId]; query[(__bridge id)kSecAttrAccount] = key; query[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne; NSData *data = [NSKeyedArchiver archivedDataWithRootObject: value]; OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL); if (status == noErr){ query[(__bridge id)kSecMatchLimit] = nil; NSDictionary *update = @{ (__bridge id)kSecValueData: data, (__bridge id)kSecAttrAccessible:(__bridge id) kSecAttrAccessibleAfterFirstUnlock }; status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)update); if (status != noErr){ return false; } } else { query[(__bridge id)kSecValueData] = data; query[(__bridge id)kSecMatchLimit] = nil; query[(__bridge id)kSecAttrAccessible] = (__bridge id) kSecAttrAccessibleAfterFirstUnlock; status = SecItemAdd((__bridge CFDictionaryRef)query, NULL); if (status != noErr){ return false; } } return true; } - (BOOL)delete:(NSString *)key forGroup:(NSString *)groupId { NSMutableDictionary *query = [self queryData:groupId]; query[(__bridge id)kSecAttrAccount] = key; query[(__bridge id)kSecReturnData] = (__bridge id)kCFBooleanTrue; OSStatus status = SecItemDelete((__bridge CFDictionaryRef)query); return (status == noErr); } - (BOOL)deleteAll:(NSString *)groupId { NSMutableDictionary *query = [self queryData:groupId]; OSStatus status = SecItemDelete((__bridge CFDictionaryRef)query); return (status == noErr); } - (NSArray *)readAll:(NSString *)groupId { NSMutableDictionary *query = [self queryData:groupId]; query[(__bridge id)kSecReturnData] = (__bridge id)kCFBooleanTrue; query[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitAll; query[(__bridge id)kSecReturnAttributes] = (__bridge id)kCFBooleanTrue; CFArrayRef resultData = NULL; OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef*)&resultData); if (status == noErr) { NSArray *keychainItems = (__bridge NSArray*)resultData; NSMutableArray *items = [NSMutableArray new]; for (NSDictionary *item in keychainItems){ // NSString *key = item[(__bridge NSString *)kSecAttrAccount]; NSDictionary *value = [NSKeyedUnarchiver unarchiveObjectWithData: item[(__bridge NSString *) kSecValueData]]; [items addObject: value]; } return [items copy]; } return @[]; } - (NSMutableDictionary *)queryData:(NSString *)groupId { NSMutableDictionary *query = [NSMutableDictionary new]; query[(__bridge id)kSecClass] = (__bridge id)kSecClassGenericPassword; query[(__bridge id)kSecAttrService] = KEYCHAIN_SERVICE; #if !TARGET_OS_SIMULATOR if (groupId) { query[(__bridge id)kSecAttrAccessGroup] = groupId; // Check if data exists for 'app groups' // - no data found -> we go for 'keychain groups' // - data found -> continue using 'app groups' OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL); if (status != errSecSuccess) { query[(__bridge id)kSecAttrAccessGroup] = [NSString stringWithFormat:@"XXXXXXXX.%@", groupId]; } } #endif return query; } code-block Is there something I'm doing wrong?
1
0
54
3d
I don’t understand any of it
1 ??? (libsystem_kernel.dylib + 5744) [0x1e1b30670] 1 <on behalf of UNKNOWN [6698] (originated by UNKNOWN [6698]), Kernel mode> Binary Images: 0x1049e0000 - 0x1049fbfff com.apple.intelligenceplatform.IntelligencePlatformComputeService 1.0 (123.9.0.1) /System/Library/PrivateFrameworks/IntelligencePlatformCompute.framework/XPCServices/Intelli
1
0
142
4d
Apple Private Relay emails go straight to spam on GMail
When users hide their email via Apple's private relay email server, our emails are sent to spam on GMail. When I look at these emails on GMail, I see the following message: "Why is this message in spam? Lots of messages from privaterelay.appleid.com were identified as spam in the past." Our emails do not go to spam when sent without Apple Private Relay. It sounds like we're being lumped together with bad actors. Is there a way to avoid this?
2
1
134
4d
Can user's Sign In With Apple email change without creating a new account?
I have an app at work that supports Sign In With Apple so that users can create accounts and have their data synced to servers. A couple of years ago one of the users created an account using Sign In With Apple, choosing to use Hide My Email as well (so that their email that the app received looks like *****@privaterelay.appleid.com). The legacy in-house backend of the app unfortunately uses email addresses as user identifiers with the unlucky assumption that emails remain the same. The app doesn't offer users the ability to change email addresses. The user in question recently reported that since very recently they are no longer able to use the app. It turns out that their Sign In With Apple email address for my app had changed at some point. They shared an iPhone screenshot of their Sign In With Apple settings for the app. The screenshot says that they created an account for this app two years ago, but the email address in the "This app received" field is different to one that they initially signed up with, and it's also a Hide My Email address. It's important to note that this app was also transferred between developer accounts about a year ago, and since then this user, including thousands of other users didn't have issues using Sign In With Apple. So my main question is: in what scenario it's possible for the email associated with a Sign In With Apple account for an app to change without creating a new account?
0
0
93
4d
Getting "User interaction is not allowed." error while fetching data from the keychain
Hi, We are getting error while fetching data from the keychain. Error code : "-25308" Error message : "User interaction is not allowed." This is happening in our Production app and many users are facing this issue. This issue is coming randomly for random users. Its working fine but suddenly we are getting this error randomly. We have tried to add delay when keychain is giving error randomly to minimise the issue but it is not fixing our issue and What could be the reason of this issue Can we have dedicated support for this? Thank You.
1
0
70
4d
MacOS: Custom Login Interface
Hello Quinn “The Eskimo!”, I am trying to customize the mac os login screen. The initial thing I want to do is to add a link or a button on login screen, tapping which should open a web page. As suggested by you on different forums, I opened a DTS ticket and received the starter project for the same. Now the problem is, the starter project is crashing with following log, arguments: mechanism -1 will get arguments mechanism 2 will get arguments mechanism -1 did get arguments none mechanism -1 will get LAContext mechanism 2 will get LA context QAuthHostSimulator/QAuthHostEngineCallbackHelper.swift:144: Fatal error Could you please help me resolve this issue. Thanks.
1
0
106
5d
ASWebAuthenticationSession and additionalHeaderFields
I'm trying to set a Cookie on ASWebAuthenticationSession on iOS 17.4+ using the new available method additionalHeaderFields. I can use this method to set any header field but "Cookie". As soon as I try to set this header, I receive the following error: Cannot start ASWebAuthenticationSession: Error Domain=com.apple.AuthenticationServices.WebAuthenticationSession Code=1 "One or more provided headers are invalid." UserInfo={NSLocalizedFailureReason=One or more provided headers are invalid.} The same content, but with different name ("Foo") is inserted as a header in the request. So, are there any limitation about setting cookies on ASWebAuthenticationSession? I've found any information abut this
0
0
107
6d
-34018 A required entitlement isn't present. from command line swift program and more
I'm having several issues with managing certificates in the default keychain using swift on macOS. I have a self containd command line test program with hardcoded pem format cert and private key. I can convert both pem formats to der via openssl. Issue 1, For Certificate: I can create a certificate and add it to the keychain. I am not able to find or delete the certificate after I add it. Issue 2, For the key: I can create the key but when I try to add it to the keychain I get "A required entitlement isn't present." In our actual app, I can add certs but can't find them (success but cert returned does not match). I can add keys and find them. All using similar code to my test app, so I decided to write the test and got stuck. I don't see any special entitlements for keychain access in our app. Looking for answers on issue 1 and issue 2. I have a self contained public github project here as it won't let me attach a zip: https://github.com/alfieeisenberg/cgcertmgr It won't let me attach a zip of the project or my source. In both cases below I tried with just labels, just tags, and both with same results. Here is how I'm trying to add keys: func addPrivateKeyToKeychain(privateKey: SecKey, label: String) -&gt; Bool { let addQuery: [NSString: Any] = [ kSecClass: kSecClassKey, kSecAttrKeyClass: kSecAttrKeyClassPrivate, kSecAttrLabel: label, kSecAttrApplicationTag: label, kSecValueRef: privateKey ] let status = SecItemAdd(addQuery as CFDictionary, nil) if status != errSecSuccess { if status == errSecDuplicateItem { print("\(#function): \(#line), Key already exists: errSecDuplicateItem") } print("\(#function): \(#line), status: \(status) \(SecCopyErrorMessageString(status, nil) as String? ?? "Unknown error")") } return status == errSecSuccess } Here is adding certs: func addCertificateToKeychain(certificate: SecCertificate, label: String) -&gt; Bool { let addQuery: [NSString: Any] = [ kSecClass: kSecClassCertificate, kSecAttrLabel: label, kSecAttrApplicationTag: label, kSecValueRef: certificate ] let status = SecItemAdd(addQuery as CFDictionary, nil) if status != errSecSuccess { print("\(#function): \(#line), status: \(status) \(SecCopyErrorMessageString(status, nil) as String? ?? "Unknown error")") } return status == errSecSuccess } And finding a cert: func findCertificateInKeychain(label: String) -&gt; SecCertificate? { let query: [NSString: Any] = [ kSecClass: kSecClassCertificate, kSecAttrLabel: label, kSecAttrApplicationTag: label, kSecReturnRef: kCFBooleanTrue!, kSecMatchLimit: kSecMatchLimitOne ] var item: CFTypeRef? let status = SecItemCopyMatching(query as CFDictionary, &amp;item) print("\(#function): \(#line), status: \(status)") if status != errSecSuccess { print("\(#function): \(#line), status: \(status) \(SecCopyErrorMessageString(status, nil) as String? ?? "Unknown error")") } guard status == errSecSuccess, let certificate = item else { print("\(#function): \(#line), Certificate not found") return nil } return (certificate as! SecCertificate) } Output: ===Trying Certs=== tryCerts(pemCertificate:): 338, Certificate added: true findCertificateInKeychain(label:): 272, status: -25300 findCertificateInKeychain(label:): 274, status: -25300 The specified item could not be found in the keychain. findCertificateInKeychain(label:): 277, Certificate not found tryCerts(pemCertificate:): 340, Certificate found: nil deleteCertificateFromKeychain(label:): 314, status: -25300 The specified item could not be found in the keychain. tryCerts(pemCertificate:): 342, Certificate deleted: false ===Trying Keys=== addPrivateKeyToKeychain(privateKey:label:): 256, status: -34018 A required entitlement isn't present. Program ended with exit code: 0
7
0
226
1w
Launch constraints to prevent an agent from being launched manually by a user?
One of our apps contains an agent that is launched at login using a plist in /Library/LaunchAgents. Now the question came up if I can make sure this agent is only launched by the system and cannot be launched by a user or another application. I wonder if this can be done using launch constraints. I played a bit with responsible application constraints but I couldn't make it work. Either the agent didn't launch at all or it could also be launched by just double-clicking on it in Finder. I wonder whether this is even possible. Thanks.
6
0
264
1w
How do I display the "You can choose to quit "AppName" now, or do it on your own later." dialog?
Install and launch a macOS app. At that time, if the app requires permission to record the screen, the following dialog will be displayed from the OS. Grant access to this application in Privacy &amp; Security settings, located in System Settings.   Follow the instructions in this dialog and select "Allow" in the system settings screen. Normally, after "Allow", the following dialog should be displayed from the OS. "AppName" mac may not be able to record the contents of your screen until it is quit. You can choose to quit "AppName" now, or do it on your own later.   But, it does not appear. Why? Is there some setting that needs to be done on the app side?
1
0
116
1w