[Evolution-hackers] Move authentication of backends back to the client (3.13.90)
- From: Milan Crha <mcrha redhat com>
- To: evolution-hackers gnome org
- Subject: [Evolution-hackers] Move authentication of backends back to the client (3.13.90)
- Date: Mon, 02 Feb 2015 17:25:15 +0100
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
[Date Prev][
Date Next] [Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]