Hello, I just committed a change, for 3.13.90 development version, into evolution-data-server [1], evolution [2], evolution-ews [3] and evolution-mapi [4], which moves authentication back to the clients. That is, any credentials (password) prompts are done fully asynchronously on the backend side, and the clients are responsible to provide the credentials. There is one exception, if the credentials are already saved, then they are used first, without any communication between the backend and the clients.
This is done in a very similar way as it used to be couple years ago, except the notifications about credentials requests and authentications responses are handled on top of ESource objects. I chose the ESource object, because it already manages password saving and because some backends, those on the source registry side, cannot be accessed in any different way. There is also a "proxy" in EBackend, which works on top of the ESource methods and signals, making things easier for the backend implementators. The backend "proxy" also makes couple things for free, based on the existence of certain ESource extensions, which are updated accordingly during the authentication process. The extensions are E_SOURCE_EXTENSION_AUTHENTICATION and E_SOURCE_EXTENSION_WEBDAV_BACKEND. The first is updated when the received credentials contain also user name, the second is updated with a trust prompt results, which are also passed into the backend as part of the credentials. That's required, because the change on the ESource can be propagated to backends too late, due to the round-trip from the client to evolution-source-registry, and only then to the factory, while the client talks to the factory directly. The backend open and the authentication process currently looks like: client-side | D-Bus | backend-side ----------------------------------------------------------------------- e_client_open() | ----> | ECal/BookBackend::open() is called: | | a) either set ESource::connection-status to CONNECTED | | b) or try to connect to the server without credentials | | and use e_backend_credentials_required/_sync() or | <---- | e_backend_schedule_credentials_required() to broadcast | | a request for credentials to any client listening | | listener of ESource::credentials-requ | | ired signal can ask for actual | | credentials a user and send them back | | with e_source_invoke_authenticate() | | | ----> | implement EBackendClass::authenticate_sync() to receive | | and use the provided credentials. Based on the result | | of this function is updated ESource::connection-status | | automatically and the output arguments are used to | | iterate with e_backend_credentials_required() again | | The main differences from the pre-this-change behaviour are: a) the backend can open without being connected to the destination (possibly remote) data store b) the ESource::credentials-required signal is delivered to all current listeners of evolution-source-registry, not only to the one which requested the open of the backend c) the backend works with the new ESource::connection-status in its open() implementation only, as long as it uses the provided "proxy" functions on the EBackend master class. As mentioned above, the credentials-required reasons also contain an SSL failures (aka when the destination server certificate checking fails for some reason), which allows to tight the Trust Prompts to the clients as well, thus they are not shown "out of blue" in the system anymore. I re-introduces libedataserverui library, which holds structures to handle credential prompts and show the trust prompts directly in the application's UI. The library is built conditionally, only when the GTK+ is available. The easiest way to implement credential prompt in an application is to create an ECredentialsPrompter and let it live for a whole time of the application. It listens for ESource::credentials-required signal and responds only to REQUIRED and REJECTED reasons. There can be disabled this auto-prompt, either globally or for respective sources. This credential prompter also listens for ESource::connection-status changes and cancels any ongoing prompts when it changes. That's one of the reasons why the ESource::connection-status is used during the authentication phase. That means that this ECredentialsPrompter is written to handle the situation with multiple clients responding to the credential prompt gracefully, by hiding (cancelling) the prompt when it is no longer needed (when another client provided the credentials). A similar functionality is made within the ETrustPrompt. Evolution itself also uses ECredentialsPrompter. It also checks all known sources right after open for their ESource::connection-status state and shows a note in an infobar of the window for those which failed due to SSL certificate, with a button to "View Certificate" and eventually accept or reject the certificate trust. It also handles those sources with AWAITING_CREDENTIALS connection status, in the same way, an infobar message is shown, this time with a "Reconnect" button. Evolution doesn't retry with old credentials on start, it rather asks for the last provided values, which helps to not spam the server with invalid credentials. I keep calling the 'credentials' and not simply 'password' above, because the ECredentialsPrompter is made "plugin-aware". I mean with that, that there can be written more than just a password prompter (the only current implementation which allows to change a user name as well), but also any other credential provider and prompter. That allows to create login methods for GSSAPI/Kerberos, OAuth and so on directly in evolution-data-server and let backends use these methods too (the Camel has this functionality already, but it cannot be easily reused in EBackend-s). I aim on the OAuth, to allow creating for example Google sources which require it even without GNOME Online Accounts - like with the GTasks backend. Another useful case can be the Two-Factor authentication, instead of using application-specific password. The other follow-up work will be to adapt any "clients" and libraries which might be affected by this change. I'd like to help as much as I'll be able, thus if there will be any issues spotted, feel free to ping me or drop me an email and I'll help you to migrate your code. I also removed all the old authentication code and functions, to avoid those system-modal prompts and basically all the old behavior users didn't like, the same as to cleanup API as much as possible. Bye, Milan [1] https://git.gnome.org/browse/evolution-data-server/commit/?id=884fb8d872787d9 [2] https://git.gnome.org/browse/evolution/commit/?id=a6e34f0bb7fd2cf [3] https://git.gnome.org/browse/evolution-ews/commit/?id=115540270568f77 [4] https://git.gnome.org/browse/evolution-mapi/commit/?id=e568bc225455969 _______________________________________________ evolution-hackers mailing list evolution-hackers@gnome.org To change your list options or unsubscribe, visit ... https://mail.gnome.org/mailman/listinfo/evolution-hackers