The Clarens web service layer performs user authentication using X509
certificates issued by a certificate authority. It does so within the
confines if the http Basic authentication protocol. This means that
authentication information is passed along in the http
header information using the AUTHORIZATION field. E.g.:
AUTHORIZATION Basic a80a844c376705cd8ecb8debdae0
The string following the Basic keyword is a Base64 encoding of some information that the user wishes to pass to the server, usually the string user:password. In Clarens usernames and password are not used, but since the Basic authentication scheme is known by most http client programs and libraries, it eases the implementation of new clients to Clarens services. In server versions 0.6.3 or greater the cookies named clarens_username and clarens_password may alternatively be used from within clients that are unable to set the authentication headers.
Note that the following assumes some knowledge of encryption using public/private keys. Also note that the authentication can be done without using an encrypted link (i.e. using http instead of https), but https is recommended if security of transferred data is required. For the primary HEP application where Clarens is used http is normally used since the data is not ordinarily confidential, and the encryption/decryption slows down data transfer significantly.
In order to do proper authentication of the client by the server, and vice versa, a challenge-response (or two-step) authentication must be used. The Clarens scheme is based on GSI, with the exception that does it was designed to fit into the http protocol without changes to servers or libraries.
The information interchange is described below, with some implementation examples interspersed written in Python. There is also a C++ implementation available which uses OpenSSL directly, see the Clarens layer for the Root package, which is part of the Clarens package.
| PYTHON | |
|
That is, ustring is the SHA1 digest of ustring_raw.
| PYTHON | |
|
AUTHORIZATION: Basic <string>
where <string> is the Base64 encoding of ustring:text_ucert.
| PYTHON | |
|
Note that the above also removes any linefeed character from the resultant string to make sure the http server does not get confused, since a CRLF sequence is used to indicate the end of a header line in the http protocol.
A typical system.auth call would look like this::
| HTTP | |
|
Most http libraries in one form or another allows you to set the username and password of the http request, and you would not need to do the header construction manually.
| PYTHON | |
|
That is, a transport with the username and password of (ustring,text_ucert)
is constructed and the xmlrpc client object is initialized using that
transport.
| XML-RPC | |
|
These three strings are as follows: STRING1: The PEM-encoded server certificate. (PEM-encoding is basically Base64) STRING2: A server 'nonce' value that was encrypted using the client's public key, and then Base64 encoded. STRING3: The client's 'nonce' value encrypted using the server's private key, and then Base64 encoded.
| PYTHON | |
|
| PYTHON | |
|
Verify that the key is authentic and still valid:
| PYTHON | |
|
| PYTHON | |
|
Then check if server_ustring is equal to ustring
| PYTHON | |
|
| PYTHON | |
|
Note that when the http header is constructed the user and password (or in
our case the ustring and mcrypt_server_nonce values are again combined
into a string (separated by a colon) and Base64 encoded when sent to the
server as part of each RPC call.
system.logout method of the
server, which produces an XML request that looks like this:
| HTTP | |
|
The server responds with and integer of value 0 when the call succeeds:
| HTTP | |
|
To allow for authentication under these circumstances, the system.auth2
server-side function was created. The function is called without an argument,
and returns the server certificate, client certificate and new password to be used
as strings. In addition, the user and password combination in the Authentication headers
or cookies should be set to a session key as in the non-SSL case and the string BROWSER respectively.
The username and new password should be used in subsequest RPC calls, in either the Authentication headers or cookies in the same way as in the non-SSL case. E.g.:
| PYTHON | |
|
Proxy authentication requires that the Gridsite Apache module be installed
and configured on the server. On an OpenPKG-based installation the command
clump install gridsite
will install and configure this package automatically.
For this reason, future Clarens services would also be usable from a stateful protocol, e.g. FTP.
Since the http protocol is designed to handle multiple requests from the same client using one or more socket connections, the server and user session ids remain valif between requests, and the server should store those session ids. This makes it possible to have a single sign-on for a client to use different applications, or different instances of the same application to connect to the server and make requests, as long as every application knows the two session ids. Obviously the server should keep track of who makes these reqeusts, and this is done by ensuring that a pair of session ids are unique to a unique IP address.
It is also possible to connect to multiple servers from a single client application, the only requirement is that a session id pair must be negiotiated with every server. Note that most private encryption keys are themselves encrypted, so that a password is usually required to enable the client to perform that negotiation process.
Note that Globus works around this inconvenience by creating a temporary
unencrypted public/private keypair through the globus-proxy-init command,
which in turn presents its own set of problems. It is also once again
recommended that SSL encryption (https) be used if data confidentiality is
important.