A PolicyKit refresher

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.

Details, 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);

And it yields a result like this:If PolicyKits built-in text agent does not fit your needs, you can implement a PolkitAgentListener yourself. That is what I ended up doing for Flatpak.

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

POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION

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.`