PolicyKit has been around for a long time, and it is a mature system that basically does its job. I recently spent some time to improve the PolicyKit integration in Flatpak and thought it might be useful to write up some of the details.
It is irritating when a dialog pops up unexpectedly and asks questions without providing sufficient details to really know where it is coming from and what the context is. Like
Authentication is required to install software
It would be much better to say what software is being installed, and where it is coming from:
PolicyKit lets you do this by using variables in your message and providing the replacement for them via a PolkitDetails object:
Authentication is required to install $(ref) from $(origin)
polkit_details_insert (details, "origin", origin); polkit_details_insert (details, "ref", ref);
No display – no problem
Its nice to get a PolicyKit dialog when you are using a desktop app that needs to carry out a privileged operation. But PolicyKit is also used by commandline tools, such as flatpak. If you are running a command in a terminal, a dialog might still be ok. But what if you are using the flatpak on the console? A dialog is not available here, so privileged operations will fail.
PolicyKit provides the necessary plumbing to solve this situation, by letting apps register their own ‘agent’, which can handle authorization requests if no other agent is available. (In a graphical session, GNOME Shell provides an agent.)
Glancing over some details, the code to do this looks roughly like this:
listener = polkit_agent_text_listener_new (NULL, &error); polkit_agent_listener_register (listener, flags, subject, NULL, NULL, &error);
Psst, don’t interrupt
As I said earlier, unexpected dialogs are annoying. Ideally, PolicyKit dialogs should only ever appear in response to a direct user action. For example, a dialog is ok if I am clicking the “Install” button in GNOME Software, but not if GNOME Software decides on it own that it is time to install some updates.
PolicyKit has a means to achieve this, by not passing the
flag when checking for authorization. But this check happens in the system service (or mechanism, in PolicyKit lingo), not in your client. In order to take advantage of this flag, the client needs to pass information about user interaction along whenever it calls a privileged method of the mechanism.
In the Flatpak case, I added a ‘no-interaction’ flag to all the flatpak-system-helper methods, and library API that GNOME Software can use to set this flag for background operations.
So there should be less unexpected PolicyKit dialogs in the future.
Update: A useful PolicyKit feature that I forgot to mention is implications. If the the permissions (or actions, in PolicyKit lingo) are ordered in some way (e.g. if you are allowed to install applications, you should also be allowed to update them), you can express these relations with “imply” annotations. This can further reduce the need for duplicate dialogs.`