I'm working with a security extension on macOs. There are cases where the extension identifies or blocks some user activity. I would like to post a notification to the user via UNUserNotificationCenter.
The extension itself is not running in an app bundle and receives an error that the system cannot resolve the app bundle proxy. To work around this restriction, I have created a separate helper app that can accept arguments and post user notification messages. I can call that app directly and display notification message. If I spawn that app with NSTask from a test command like executable, the app will display notifications. If I perform the exact same spawn from the security extension, the app does not have authorization to display. The error message retrieved when requesting authorization is "Couldn't communicate with a helper application." This error is coming from inside my helper application that was already spawned by the security extension and is in context of requesting authorization to post a user notification to UNUserNotificationCenter. The user has already approved the app to display notifications, the only thing different is spawning the app from the extension. Calling it from the command line or finder works just fine.
https://developer.apple.com/documentation/usernotifications/asking_permission_to_use_notifications
Before I try alternative designs.. Does anyone have insight to what is preventing the connection to user notification center in one deployment and not the other?
I would like to post a notification to the user via
UNUserNotificationCenter.
That’s not going to work. In the terms define by Technote 2083 Daemons and Agents, User Notifications is not a daemon-safe frameork, and your ES client is running as a daemon (either its a launchd daemon or a system extension, and the latter is effectively a daemon).
And when you take a step back it’s obvious that it’s not going to work because macOS supports multiple users. If a daemon posts a notification and there are multiple users logged in, which user is going to see it?
I have created a separate helper app that can accept arguments and post user notification messages.
This won’t help. When you run a program as a child process, using say NSTask, it inherits the parent’s execution context. Again, I recommend that you have a read of TN2083.
The standard way around this problem is to start an agent in each GUI login session, have that agent connect to your daemon, and then have the daemon tell the agent to display a notification on its behalf. When the daemon encounters something that needs notification, it can survey the list of agent connections to decide which agent to instruct.
How you get this agent running depends on how your product is packaged. You mentioned “security extension”. Does that mean your ES client is a system extension? Which means the the final product is a standalone app? Or is this something you install with an installer package?
There is one alternative here, namely to use CFUserNotification. That’s much simpler to adopt but it has many downsides, including:
-
It offers very limited control over how the notification is formatted.
-
It offers no control over how it’s presented. So, in the multi-user case, you can’t target the user whose activity it is you’ve blocked.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"