Building Liberty Services with Lasso
Author: | Frederic Peters |
---|---|
Contact: | fpeters@entrouvert.com |
Date: | 2005-01-22 |
Copyright: | Copyright © 2004, 2005 Entr'ouvert |
- 1. Preface
- 2. The Liberty Architecture
- 3. The Lasso Architecture
- 4. Getting Lasso
- 5. Common Lasso Knowledge
- 6. Single Sign-On and Federation
- 7. Integration with Existing Applications
- 8. Other Profiles
- 9. Lasso in other Languages
This work is licensed under the GNU General Public License. To view a copy of this license, visit http://www.gnu.org/copyleft/gpl.html.
1. Preface
In a digitalised world where both businesses and consumers want security in their transactions the notion of identity has become more and more crucial. Today one's identity on the network is fragmented across various identity providers, employers, business services and other communities. This fragmentation leads to partial and often unsatisfying customers-to-business relationships.
A Federated Network Identity allows new business opportunites and new economies of scale. In a world of federated commerce a user's identity, preferences, buying habits and history, are managed by the user himself and securely exchanged with the organisations of the user's choosing.
1.1. The Liberty Alliance Project
The Liberty Alliance Project was formed in September 2001 to develop open standards for federated network identity management and identity-based services. Its goals are to ensure interoperability, support privacy, and promote adoption of its specifications, guidelines and best practices. The Alliance is made up of more than 150 members, representing a worldwide cross-section of organizations ranging from educational institutions and government organizations, to service providers and financial institutions, to technology vendors and wireless providers.
1.2. The Lasso Project
In July 2003 Entr'ouvert started to develop the "Carte de Vie Quotidienne" project for the commune of Vandoeuvre-les-Nancy. This project quickly drove us to take interest in cross-site authentication problems. We identified Liberty Alliance specifications as the only ones potentially able to satisfy our need for a strong authentication, coupled with private life respect. Lasso is a library written in C which means it can be easily integrated within any kind of web service whenever a strong authentication is required. Lasso has been the first implementation of Liberty Alliance released under the GNU GPL license.
1.3. Acknowledgments
Figures use drawings from GNOME Gorilla theme by Jakub 'jimmac' Steiner.
2. The Liberty Architecture
Building on existing pieces, XML, SAML, SOAP, HTTP, SSL...
Points to specs; quick glossary; user = principal...
Maps use cases to profiles.
This chapter provides a quick overview of the different profiles; they will be detailed and implemented in the next chapters.
2.1. Single Sign-On and Federation
The Single Sign On process allows a user to log in once to an identity provider (IdP), and to be then transparently loged in to the required service providers (SP) belonging to the IP "circle of trust". Subordinating different identities of the same user within a circle of trust to a unique IP is called "Identity Federation". The liberty Alliance specifications allows, thanks to this federation, strong and unique authentication coupled with control by the user of his personal informations. The explicit user agreement is necessary before proceeding to Identity Federation.
The different SPs can't communicate directly together about users informations. They're only able to exchange informations about a user with the IP. This assure :
- private life respect;
- increased security (an unveiled identity for one of the SPs won't endanger the others).
To insure the integrity and the non-revocability of the exchange, a trusted third part releases a security token which identify only the session and not the user.
2.1.1. Artifact Profile

Single Sign-On and Federation interactions, Artifact profile
- the user clicks on a "login" button
- the service provider answers with a redirect to the identity provider
- the browser goes to the identity provider where the user logs in
- the identity provider answers with a redirect, back to the service provider
- the browser goes to the service provider telling it has been authenticated
- the service provider makes a SOAP request to the identity provider asking if it is true that the user has been authenticated
- the identity provider answers that yeah, everything is under control
- the service provider answers to the browser and send a welcome page
2.1.2. Browser POST Profile
Almost the Same thing.
2.2. Single Log-out
A few words about the five different profiles.
2.2.1. Initiated by the Service Provider, using SOAP requests

Single Log-out interactions; initiated at service provider, using SOAP
Should arrange the figure with the SP on the right; I think it would help read the figure.
2.3. Liberty URLs
How does the identity provider knows the "SOAP endpoint" of the service provider ? That is metadata for you.
3. The Lasso Architecture
Doesn't store, doesn't communicate.
Modeled on liberty profiles; one profile = one class
Objet oriented but in C. Talks about how this work (necessary to know for the lasso_profile functions)
Lasso provides the necessary functions to implement Liberty Alliance profiles, as defined in the Liberty ID-FF Bindings and Profiles Specification and explained in the previous chapter. Each profile maps to a Lasso class:
Single Sign-On and Federation | LassoLogin |
Name Registration | LassoRegisterNameIdentifier |
Federation Termination Notification | LassoFederationTermination |
Single Logout | LassoLogout |
Name Identifier Mapping | LassoNameIdentifierMapping |
Identity Provider Introduction | not implemented |
Name Identifier Encryption | not implemented |
There are also a few other classes to know about:
- LassoServer holds the data about a provider, which other providers it knows, what certificates to use, etc.
- LassoIdentity holds the data about a Liberty federated identity
- LassoSession holds the data about an active Liberty session.
- LassoProfile is the base class for profiles.
Talk more about respective usage of Identity and Session.
4. Getting Lasso
Lasso is licensed under the GNU General Public License. That means users are given several inalienable rights: the right to use the library, whatever the purpose is; the right to study how it works, getting access to source code; the right to distribute the library to others and the right to modify the library and publish those modifications.
Talks about library and how Lasso will force the use of the GPL.
4.1. Binary packages
4.1.1. Debian packages
The latest Lasso release should be available straight from any Debian mirror worldwide in the etch or sid distribution. Additionaly packages are provided for the sarge release on a dedicated APT repository. The following line needs to be added to /etc/apt/sources.list:
deb http://www.entrouvert.org ./debian/lasso/
It is then a matter of running:
apt-get install liblasso-dev
4.1.2. RPM packages
RPM Bad. A mess.
4.1.3. Microsoft Windows packages
Ah. Isn't that funky ? (need to ask Romain about cygwin, mingw32 and whatever is needed to get Lasso working on Windows)
4.2. Sources
The source code of the latest release is available at the following URL: http://labs.libre-entreprise.org/project/showfiles.php?group_id=31
Lasso uses the GNU automake and autoconf to handle system dependency checking. It is developed and built locally on GNU/Linux (Debian) both on x86 and PowerPC processors.
4.2.1. Compiling
./configure
The configure shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a Makefile in each directory of the package. It may also create one or more .h files containing system-dependent definitions. Finally, it creates a shell script config.status that can be run in the future to recreate the configuration, and a file config.log containing compiler output (useful mainly for debugging configure).
configure can take a lot of options, a complete list is available with the --help flag: ./configure --help
4.2.1.1. Installation Directories
By default, Lasso will be installed in /usr/local/lib. It is possible to specify an installation prefix other than /usr/local by giving the option --prefix=PATH; for example --prefix=/usr.
4.2.1.2. Optional Features
There are optional features that you may want not to build, things like unit tests, bindings for different languages, etc.
--disable-java | Disable the Java binding |
--disable-python | Disable the Python binding |
--disable-php | Disable the PHP binding |
--disable-csharp | Disable the C# binding |
--disable-tests | Disable the unit tests |
On the other hand there are features you may want to activate.
--enable-debugging | Enable debugging messages |
--enable-profiling | Enable profiling compilation flags |
Once ./configure has been executed it is time to compile the whole thing.
make
It should take a few minutes.
make install
Will then copy the library and header files to their final directories.
4.2.2. Bleeding Edge
CVS (Concurrent Versions System) is the version control system used by Lasso developers to keep track of files, how and by whom they were modified. It is accessible anonymously for people to use the latest developments.
export CVSROOT=:pserver:anonymous@cvs.labs.libre-entreprise.org:/cvsroot/lasso cvs login # press enter cvs -z3 checkout lasso
Note
The CVS version requires more tools to build; notably automake, autoconf and libtool.
5. Common Lasso Knowledge
Starting with basics on using Lasso in a given program.
5.1. Lasso Projects Basics
Lasso functions are defined in several header files typically located in /usr/include/lasso/ or /usr/local/include/lasso/. It is possible to include individual files even if the main lasso.h is sufficient most often.
The first thing to do is then to call lasso_init(). Similarly the last thing will be to call lasso_shutdown(). The smallest and useless Lasso project will therefore be:
#include <lasso/lasso.h> int main(int argc, char *argv[]) { lasso_init(); printf("Hello world.\n"); lasso_shutdown(); return 0; }
Lasso uses a tool called pkg-config to know the necessary flags for compilation and linking.
$ pkg-config lasso --cflags -DXMLSEC_CRYPTO=\"openssl\" -DXMLSEC_LIBXML_260=1 -D__XMLSEC_FUNCTION__=__FUNCTION__ -DXMLSEC_NO_XKMS=1 -DXMLSEC_NO_CRYPTO_DYNAMIC_LOADING=1 -DXMLSEC_CRYPTO_OPENSSL=1 -I/usr/include/lasso -I/usr/include/libxml2 -I/usr/include/xmlsec1 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include $ pkg-config lasso --libs -llasso -lxmlsec1-openssl -lxmlsec1 -lssl -lcrypto -ldl -lgobject-2.0 -lxslt -lxml2 -lpthread -lz -lm -lglib-2.0
Creating an executable from the previous sample will then be a simple matter of calling gcc with the right flags
Creating an executable from the previous sample would then a simple matter of calling gcc with the right flags. But there is currently in bug in XMLSec, the library used by Lasso to provide XML Signature and XML Encryption support. It is possible to workaround the bug:
$ gcc hello.c -o hello $(pkg-config lasso --cflags --libs) <command line>:4:16: missing terminating " character $ gcc hello.c -o hello $(pkg-config xmlsec1 --cflags --libs | tr -d '\\') $ ./hello Hello world.
5.2. Lasso Objects
The Lasso Architecture chapter described the different objects provided by Lasso. The profile objects will be detailed in the following chapters; common objects such as server, identity and session are explained here.
5.2.1. LassoServer
A LassoServer object may be created as follows:
LassoServer *server; server = lasso_server_new("sp-metadata.xml", NULL, "sp-private-key.pem", "sp-crt.pem", lassoSignatureMethodRsaSha1); lasso_server_add_provider(server, "idp-metadata.xml", "idp-public-key.pem", "ca-crt.pem");
- sp-metadata.xml is the Liberty metadata file for the service provider
- idp-metadata.xml is the Liberty metadata file for the identity provider
- sp-private-key.pem is the service provider private key; used to sign documents
- sp-crt.pem is the service provider certificate; sent within signed documents
- idp-public-key.pem is the identity provider public key; used to verify signature in documents sent by the identity provider
- ca-crt.pem is the certificate of the certification authority used by the identity provider.
It is of course possible to have several calls to lasso_server_add_provider if there are more than one identity provider.
5.2.2. LassoProfile
This is the virtual base class for profiles. It notably provides access to the identity and session parts of a profile. See below for examples.
5.2.3. LassoIdentity
/* profile is a pointer to a LassoProfile object */ LassoIdentity *identity; if (lasso_profile_is_identity_dirty(profile)) { identity = lasso_profile_get_identity(profile); if (identity) { dump = lasso_identity_dump(identity); } }
5.2.4. LassoSession
/* profile is a pointer to a LassoProfile object */ LassoSession *session; if (lasso_profile_is_session_dirty(profile)) { session = lasso_profile_get_session(profile); if (session) { dump = lasso_session_dump(session); } }
5.2.5. Serialization
LassoServer, LassoIdentity and LassoSession``objects can be serialized into XML files. Example with a ``LassoServer:
gchar *dump; FILE *fd; dump = lasso_server_dump(server); /* write dump into a file, a database, whatever */ g_free(dump);
Note
lasso_server_dump (and other Lasso dump functions) allocates memory through GLib. g_free is the function to use instead of free to release memory.
It is then really easy to have properly constructed objects returned:
LassoServer *server; gchar *dump; /* restore dump from file, database, whatever */ server = lasso_server_new_from_dump(dump);
Warning
The server dump only contains the filenames; not the actual file contents. Files should not be moved afterwards.
The functions are:
Object | Dump | Restore |
---|---|---|
LassoServer | lasso_server_dump | lasso_server_new_from_dump |
LassoIdentity | lasso_identity_dump | lasso_identity_new_from_dump |
LassoSession | lasso_session_dump | lasso_session_new_from_dump |
6. Single Sign-On and Federation
6.1. Profile Overview
The service provider has four things to do:
- creating an authentication request
- sending it to the identity provider
- receiving an authentication response or an artifact
- (eventually) checking it against the identity provider
The first two steps are handled with an HTTP redirection or an HTML form; typically the user would click on a button, the service provider would then create the authentication request and send an HTTP Redirect to the browser. No URL is defined in the specifications for this first step.
The last two steps are handled in the AssertionConsumerServiceURL; the user will arrive there through an HTTP Redirect or an HTTP POST carrying a piece of information from the identity provider. In case of a redirect, this information, called artifact, won't be large and will be exchanged with the identity provider for a AuthnResponse. An HTTP POST will be able to carry much more information and will therefore be able to provide either the artifact or directly the AuthnResponse.
An appropriate metadata snippet would be:
<?xml version="1.0"?> <EntityDescriptor providerID="service-provider" xmlns="urn:liberty:metadata:2003-08"> <SPDescriptor> <AssertionConsumerServiceURL id="AssertionConsumerServiceURL1" isDefault="true"> https://service-provider.example.com/liberty-alliance/assertionConsumer </AssertionConsumerServiceURL> </SPDescriptor> </EntityDescriptor>
The identity provider has more things to do:
- receiving an authentication request
- authenticating the user if necessary
- sending a response to the service provider
- (eventually) answering a SOAP request with an other response
All but the last one is handled in the SingleSignOnServiceURL; the user has been redirected there from the service provider with an authentication request as URL parameter. This authentication request is used to decide several things (allowed authentication methods for example) and the authentication is done. This step is not part of the Liberty protocols, this can be as simple as straight HTTP authentication with a username and a password or as complex as a Java applet checking a certificate on the client.
Anyway, once the user has been authenticated, an answer must be sent to the service provider. It is actually not a direct communication, the answer bounces on the user agent with an HTTP Redirect or by an HTML form pointing to the service provider.
The answer may be an artifact (available in the query string in case of a redirect or in a LAREQ form field in case of a POST); the user is then simply redirected to this URL. The service provider will then make a SOAP request to the SoapEndpoint asking for the authentication response matching the artifact.
The answer may also be an authentication response; since it will be a large piece of data it must be passed in an HTML page; an HTML form embedding the authentication response. The user will then submit this form to the service provider AssertionConsumerURL.
Metadata would be:
<?xml version="1.0"?> <EntityDescriptor providerID="identity-provider" xmlns="urn:liberty:metadata:2003-08"> <IDPDescriptor> <SoapEndpoint> https://identity-provider.example.com/soapEndpoint </SoapEndpoint> <SingleSignOnServiceURL> https://identity-provider.example.com/singleSignOn </SingleSignOnServiceURL> </IDPDescriptor> </EntityDescriptor>
6.2. Implementing the service provider parts
Warning
The source code presented in the "implementing" section has for sole purpose to explain the different steps necessary to implement the profiles; they notably lack proper error checking. See XXX for details on error checking.
6.2.1. Sending the user to the identity provider
server is a LassoServer object as seen earlier (LassoServer) and idpProviderId is a string with the identity provider Id (the string must match a providerID defined in the metadata file).
LassoLogin *login; /* create login object */ login = lasso_login_new(server);
Select profile to use, HTTP Redirect:
lasso_login_init_authn_request(login, idpProviderId, LASSO_HTTP_METHOD_REDIRECT);
or HTTP POST:
lasso_login_init_authn_request(login, idpProviderId, LASSO_HTTP_METHOD_POST);
Parametrize request:
/* will force authentication on the identity provider */ LASSO_LIB_AUTHN_REQUEST(LASSO_PROFILE(login)->request)->ForceAuthn = TRUE; /* ask for identity federation */ LASSO_LIB_AUTHN_REQUEST(LASSO_PROFILE(login)->request)->NameIDPolicy = strdup(LASSO_LIB_NAME_ID_POLICY_TYPE_FEDERATED); /* the user consents with the idea of identity federation */ LASSO_LIB_AUTHN_REQUEST(LASSO_PROFILE(login)->request)->consent = strdup(LASSO_LIB_CONSENT_OBTAINED);
(see API reference for other possible values)
Create the authentication request:
lasso_login_build_authn_request_msg(login);
An URL is then defined in LASSO_PROFILE(login)->msg_url; the user must be redirected to it; for example, in a CGI:
printf("Location: %s\n", LASSO_PROFILE(login)->msg_url);
6.2.2. Receiving an answer from the identity provider
This part is handled on the AssertionConsumerURL.
6.2.2.1. Receiving an assertion
The user has been directed to this URL. If it was a redirect the query string (the part of the URL after the question mark) will hold the artifact and may be used to initialize the LassoLogin object.
LassoLogin *login; login = lasso_login_new(server); lasso_login_init_request(login, query_string, LASSO_HTTP_METHOD_REDIRECT); lasso_login_build_request_msg(login);
If it was a form post it will have a LAREQ field.
LassoLogin *login; login = lasso_login_new(server); lasso_login_init_request(login, lareq_field, LASSO_HTTP_METHOD_POST); lasso_login_build_request_msg(login);
The service provider must then check this artifact using a SOAP request to the identity provider. The URL is LASSO_PROFILE(login)->msg_url while the request is LASSO_PROFILE(login)->msg_body. The request must succeed with an HTTP 200 status code. The SOAP answer body must then be passed to:
lasso_login_process_response_msg(login, answer);
6.2.2.2. Receiving an authentication response
A form with a LARES field has been posted; this element holds the authentication response.
LassoLogin *login; login = lasso_login_new(server); lasso_login_process_authn_response_msg(lares_field);
6.2.2.3. Federating identities
There is then a nameIdentifier (accessible through LASSO_PROFILE(login)->nameIdentifier) for the user identifying. If this name identifier is already known by the service provider the corresponding identity and session must be restored.
if (session_dump != NULL) { lasso_profile_set_session_from_dump(LASSO_PROFILE(login), session_dump); } if (identity_dump != NULL) { lasso_profile_set_identity_from_dump(LASSO_PROFILE(login), identity_dump); }
Process the authentication request, this will update (or create) the identity and session.
- ::
- lasso_login_accept_sso(login);
Identity and session must then be saved and finally the login object can be destroyed:
lasso_login_destroy(login);
And a success web page may then be displayed.
7. Integration with Existing Applications
That's the part where we talk about identity dumps to insert in existing user tables. And session dumps wherever sessions are stored.
8. Other Profiles
That would be like the single sign-on chapter but harder better faster stronger.
9. Lasso in other Languages
C is cool.
But.
Python. (CGI ?)
PHP. (with code putting the session dump in the PHP $_SESSION["lasso"])
Java. (and JSP ?)
C#. (and ASP.Net ?)
Whatever we have.