that we should take a look at the unified authentication API used in Subversion.
So I've read the related code yesterday. And I found the work done by the
Subversion folks is really interesting and helpful for our Python keyring library.
This post is going to introduce the security model and API interface used in
Subversion project.
Following paragraphs comes from the comments in Subversion's source code.
Filename: subversion/include/auth.h
We define an authentication "provider" as a module that is able toIn subversion/libsvn_subr/auth.c, we can find following key
return a specific set of credentials. (e.g. username/password,
certificate, etc.) Each provider implements a vtable that
- can fetch initial credentials
- can retry the fetch (or try to fetch something different)
- can store the credentials for future use
For any given type of credentials, there can exist any number of
separate providers -- each provider has a different method of
fetching. (i.e. from a disk store, by prompting the user, etc.)
The application begins by creating an auth baton object, and
"registers" some number of providers with the auth baton, in a
specific order. (For example, it may first register a
username/password provider that looks in disk store, then register
a username/password provider that prompts the user.)
Later on, when any svn library is challenged, it asks the auth
baton for the specific credentials. If the initial credentials
fail to authenticate, the caller keeps requesting new credentials.
Under the hood, libsvn_auth effectively "walks" over each provider
(in order of registry), one at a time, until all the providers have
exhausted all their retry options.
This system allows an application to flexibly define authentication
behaviors (by changing registration order), and very easily write
new authentication providers.
An auth_baton also contains an internal hashtable of run-time
parameters; any provider or library layer can set these run-time
parameters at any time, so that the provider has access to the
data. (For example, certain run-time data may not be available
until an authentication challenge is made.) Each credential type
must document the run-time parameters that are made available to
its providers.
function interface used in Subversion's authentication system.
void svn_auth_open (svn_auth_baton_t **auth_baton, apr_array_header_t *providers, apr_pool_t *pool) void svn_auth_set_parameter (svn_auth_baton_t *auth_baton, const char *name, const void *value) const void * svn_auth_get_parameter (svn_auth_baton_t *auth_baton, const char *name) svn_error_t * svn_auth_first_credentials (void **credentials, svn_auth_iterstate_t **state, const char *cred_kind, const char *realmstring, svn_auth_baton_t *auth_baton, apr_pool_t *pool) svn_error_t * svn_auth_next_credentials (void **credentials, svn_auth_iterstate_t *state, apr_pool_t *pool) svn_error_t * svn_auth_save_credentials (svn_auth_iterstate_t *state, apr_pool_t *pool)When the SVN library asked for the authentication, it first initialize the baton
by calling svn_auth_open(). Then it'll set the needed parameter through
svn_auth_set_parameter(). Finally, it can get the credentials using
svn_auth_first_credentials and svn_auth_next_credentials. Note that the
baton is initialize with a list of providers. When it is asked for credentials,
it'll try to fetch the credentials in that list's order.