Display interactable UI on macOS login screen

We are developing a lightweight VPN client inside a daemon process that will run even when no user session is active on machine. The lightweight VPN runs in machine context and does not require user session. We would like to display some basic diagnosis information about our lightweight client on macOS login window before user is logged into their machine (in case users need that).

So, is it possible to display a UI window on login screen with some basic info that user can interact with. If yes, where can I get started?

Please note, this is not an authorization plugin. We are just wanting to display info about our process that runs a lightweight VPN client on macOS login screen.

Answered by DTS Engineer in 797820022

Oh, wow, lemme dust off TN2228 Running At Login. Its intro describes a number of techniques you can use to run during the login process. The best approach depends on whether you want your UI to be synchronised with the login process or not. It sounds like you don’t, in which case a pre-login agent is the best choice.

And that leads to another very dusty resource, the PreLoginAgents sample code.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Oh, wow, lemme dust off TN2228 Running At Login. Its intro describes a number of techniques you can use to run during the login process. The best approach depends on whether you want your UI to be synchronised with the login process or not. It sounds like you don’t, in which case a pre-login agent is the best choice.

And that leads to another very dusty resource, the PreLoginAgents sample code.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thank you for your response Quinn. Few questions about PreLoginAgents:

  1. What's the best way to enable or disable them? For example if a feature flag is enabled in thin client, we would want to display the PreLoginAgent and not otherwise. One way I could think of is to place and remove the PreLoginAgent from /Library/PrivilegedHelperTools/ directory based on feature flag. Is there any better way? Can we make this decision inside the agent?
  2. Can a PreLoginAgent make an XPC connection to a LaunchDaemon?
  3. Can a PreLoginAgent read files from root directories like /Library/Application Support/?

One important point I just noticed is that PreLoginAgents do not run on machine start/restart when FileVault is enabled on the machine (which is quite common). This breaks the requirement of displaying the UI on login screen in most of cases. People usually either Lock Screen or Restart machine and PreLoginAgent cannot be displayed in either of these cases.

Is there a better way? Should we instead use SFAuthorizationPluginView to display this UI beside the macOS login screen?

What's the best way to enable or disable them?

Pre-login agents are just launchd agents, so you can enable and disable them in all the usual ways you can use for a launchd agent. That usually means:

  • Adding or removing the launchd property list from /Library/LaunchAgents.

  • Messing around with launchctl with the enable and disable subcommands.

The other option, SMAppService, won’t work for you because it only supports agents in ~/Library/LaunchAgents.

Can a PreLoginAgent make an XPC connection to a LaunchDaemon?

Yes. TN2083 Daemons and Agents describes the context in which they run. It’s weird, in that they run as root but are in a GUI [pre-]login session.

Can a PreLoginAgent read files from root directories like /Library/Application Support/?

Yes.

In general, any process can read such files as long as the file permissions are set correctly.

One important point I just noticed is that PreLoginAgents do not run on machine start/restart when FileVault is enabled on the machine

Correct. And there’s no way around that. When you boot a machine with FileVault enabled, it boots to pre-boot environment that will not load any third-party code [1].

This affects authorisation plug-ins as well, and it’s is one of the more common complaints about SFAuthorizationPluginView.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Historically that used to be EFI. These days it’s a cut-down version of macOS. Regardless, there’s no third-party code.

Thank you Quinn for the detailed answer. Few more questions:

  1. On a machine with FileVault enabled, on reboot, what happens to an authorization plugin whose mechanism is added to authorization db before loginwindow:login? Would the plugin still be invoked after pre-boot login? Would login window appear again after the plugin has finished since loginwindow:login is listed after the plugin?
  2. How does pre-boot login work for users who need authentication with AD server? Would they be prompted for AD login again after pre-boot login? (Assuming no third party authorization plugin exists)
Would the plugin still be invoked after pre-boot login?

Yes. After pre-boot, the system boots for real. That ends up starting loginwindow, which does the standard thing, namely try to acquire the system.login.console right. That runs all mechanisms that you configure for that right.

The difference is that the Apple mechanisms detect that the user has entered their credentials into FileVault and uses those to complete the login without displaying any UI. The mechanics of that are not documented.

How does pre-boot login work for users who need authentication with AD server?

I don’t know for sure. Historically EFI wasn’t up to this task. With the pre-boot environment switching to macOS, it would now be feasible to make that work, but I don’t know if it does.

Our general path forward here is Platform SSO. This works in the pre-login environment without running any third-party code. The Platform SSO extension tells the system how it should authenticate with the IdP and then the system does that authentication without needing to run the extension’s code.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Display interactable UI on macOS login screen
 
 
Q