ID-FF 1.1 Java Toolkit
Bryan Field-Elliot, Chief Architect
Document Last Updated: November 9, 2004
This document is updated frequently. We suggest you read the latest online version, here.
The purpose of the ID-FF 1.1 Java Toolkit is to allow developers to quickly build Federated Identity Management services into new and existing web site projects. Federated Identity Management allows end-users to link their accounts on one system, to their accounts on other systems, allowing for seamless Single Sign-On and other features (such as Global Logout). This is done using the Liberty Alliance ID-FF protocols, version 1.1.
The toolkit was architected by experienced Java web application developers, with other Java web application developers in mind. The primary aim of the toolkit is to shield the developer from the time-consuming, lower-level details of implementing the Liberty Protocol. These details include: XML parsing, XML data binding, SOAP, Digital Signatures, SAML, and finally, the Liberty Protocol itself. Instead, developers can focus on the high-level Servlet/JSP APIs we provide, ignoring (for the most part) the lower subsystems previously mentioned.
For an overview of the Liberty Protocol, we refer you to the Liberty Architecture Overview, an excellent and mostly short (44-page) description of the problems the Liberty Protocol aims to solve. It should be considered required reading in order to implement using the ID-FF 1.1 Java Toolkit. This document will continue to assume you have already read the Liberty Architecture Overview document and understand its concepts and definitions, such as Service Provider, Identity Provider, Federation, Termination, etc. There are several more detailed documents describing the Liberty Protocol, but as previously mentioned, it is the aim of this toolkit to shield you from these details.
The root folder of the Toolkit distribution contains the Ant build script (build.xml), which you should not need to customize. In addition, there is an external properties file for Ant (called build.properties), which we DO e+xpect you to customize, before building.
The "conf" folder contains all configuration files, static data files (such as your Liberty Providers directory), and XML Schemas (which are deployed with the web application to speed parsing). These files are copied into their correct destinations by build.xml.
The "docs" folder contains this document and other supporting documentation, such as the complete Liberty Protocol specification. In addition, the auto-generated Javadocs for this system are located in the "api" subfolder. Lastly, all licenses of external libraries and dependencies used by the toolkit, are contained within the "licenses" subfolder.
The "src" folder contains the Java source files.
The "webapp" folder contains a layout of the sample web application as it is intended to be deployed. Build.xml will assemble its pieces and archive it into a .war file.
"sourceid-sso.jar", located in the root folder, is an archive of the sourceid-sso compiled classes, meant to be deployed in your own web application's "WEB-INF/lib" folder, along with assorted configuration files.
"sourceid-sso.war", also located in the root folder, is a complete sample application, almost ready to be deployed. We say "almost" because the Providers directory (sourceid-sso-providers.xml) needs to be populated with actual Service or Identity providers, so that your deployment has another site to "talk to".
If you are deploying into any of the following environments, please follow these prerequisite environment setup instructions before proceeding to deploy the toolkit.
Make sure to check the XML-Security Installation Guide. Also look at the following bug-report if you are intending to use a JDK version higher than 1.4.2_04. The Sun JDK ships with versions of Apache Xalan , an XSLT processor. The XML security library has tight dependancies on the version of Xalan included. A working version of xalan.jar is distributed with the toolkit, in the webapp/WEB-INF/lib subdirectory. The file "xalan.jar" MUST be copied into Java's "endorsed libraries" directory. In your JAVA_HOME directory, find the "/jre/lib" subdirectory (but NOT "/lib"). Inside this lib directory, create a subdirectory called "endorsed" if it doesn't already exist. Then, copy the toolkit-distributed version of xalan.jar into this directory.
Apache Jakarta Tomcat, version 4.1.x, ships with an older version of the Apache Xerces XML parser. This must be updated with version 2.2.1 or higher; version 2.2.1 is distributed with the toolkit, and must be MOVED OUT OF the toolkit's WEB-INF/lib directory, and MOVED IN TO Tomcat's "common/lib" directory. The new files can be found in the toolkit's "webapp/WEB-INF/lib" subdirectory, and are called xercesImpl.jar and xmlParserAPIs.jar.
Caucho Resin is a high-performance Servlet container. In it's configuration file (conf/resin.conf), the following JAXP System Properties must be set for proper functioning of the toolkit. These options should go near the top of the file, just inside the <caucho.com> element:
<caucho.com> <system-property javax.xml.transform.TransformerFactory="org.apache.xalan.processor.TransformerFactoryImpl"/> <system-property javax.xml.parsers.DocumentBuilderFactory="org.apache.xerces.jaxp.DocumentBuilderFactoryImpl"/> <system-property javax.xml.parsers.SAXParserFactory="org.apache.xerces.jaxp.SAXParserFactoryImpl"/> |
JBoss 3.0.4 ships with two outdated libraries: the Crimson XML parser, and an older version of Castor. The toolkit ships with (and requires) Apache Xerces XML Parser (which supercedes Crimson), and a later version of Castor. To deploy the toolkit on Jboss 3.0.4 with Jetty:
In the "lib" subdirectory of your JBoss home directory, remove the file "crimson.jar". We recommend not deleting this file, but rather, moving it to a different directory (which will not be in JBoss's classpath).
Copy the files "xercesImpl.jar" and "xmlParserAPIs.jar" from the toolkit's webapp/WEB-INF/lib directory, into JBoss's main "lib" directory (same location as step 1 above).
In the "server/default/lib" subdirectory of your JBoss home directory, remove the files "castor.jar" and "xalan.jar", placing them into the same "out of the way" directory used in step 1.
Into the "server/default/lib" directory (used in step 3), copy the file "xalan.jar" from the toolkit's webapp/WEB-INF/lib directory. Do NOT also copy the file "castor-0.9.4.2-xml.jar" from the toolkit's webapp/WEB-INF/lib directory here.
With these library changes made, the toolkit will deploy properly in JBoss 3.0.4 + Jetty.
Orion ships with older XML Parsers (e.g. Crimson), which need to be upgraded to newer versions (e.g. Xerces, distributed with the toolkit) before deployment. Orion's classpaths are hard-coded into the MANIFEST.MF file of orion.jar, which make upgrading the XML Parser awkward and inelegant. However, the following process has been demonstrated to work:
From the Orion home directory, remove the files "crimson.jar", "jaxp.jar", "xalan.jar", and "xerces.jar" into a separate, out-of-the-way directory, where they will not be loaded by Orion's classpath.
Copy the file "xml-apis.jar" from the toolkit's webapp/WEB-INF/lib directory, into Orion's home directory. Once there, rename the file to "jaxp.jar".
Copy the file "xercesImpl.jar" from the toolkit's webapp/WEB-INF/lib directory, into Orion's home directory. Once there, rename the file to "xerces.jar".
Copy the file "xalan.jar" from the toolkit's webapp/WEB-INF/lib directory, into Orion's home directory.
The ID-FF 1.1 Java Toolkit is a Liberty Protocol implementation toolkit for Federated Identity Management. The nature of Federated Identity Management is such that it requires "Federation Partners" in order to work; consequently, a quick demo of the toolkit requires not one, but two separate deployments. One deployment acts as a "Service Provider", while the other acts as an "Identity Provider". The following step-by-step instructions should guide you in establishing these two "demo deployments". A familiarity with your Java Servlet container is assumed.
1. Create empty working directories for each of the two deployments, named "sso-sample-idp" and "sso-sample-sp".
2. Un-jar the toolkit web archive (sourceid-sso.war) into each of these two working directories. The master web archive contains sample applications and configuration for both an IDP and a SP, although only one set of code will be active per deployment.
3. Customize the sample Service Provider deployment by editing the file "sso-sample-sp/WEB-INF/sourceid-sso-providers.xml", and locate the block entitled "Sample Identity Provider Descriptor". This block describes the Identity Provider (IDP) that this Service Provider (SP) will be federating with. Within this block, locate the section containing all of the IDP endpoint URL's. Edit each endpoint URL to match the URL prefix of your actual deployment. The following XML fragment illustrates in red the URL prefixes which need customizing:
<lib:IDPDescriptor xmlns:lib="http://projectliberty.org/schemas/core/2002/12" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <!-- ...portions omitted... --> <!-- The endpoints in the following URL's are correct for services offered by the ID-FF 1.1 Java Toolkit. If federating this installation with another instance of the toolkit, then all you need to do is customize the URL's to match your deployment (e.g. replace "http://localhost:9080/sso-sample-idp" with your server name and servlet context). --> <lib:SoapEndpoint>http://localhost:9080/sso-sample-idp/sso/soap/endpoint</lib:SoapEndpoint> <lib:SingleLogoutServiceURL>http://localhost:9080/sso-sample-idp/sso/logout</lib:SingleLogoutServiceURL> <lib:SingleLogoutServiceReturnURL>http://localhost:9080/sso-sample-idp/sso/logout</lib:SingleLogoutServiceReturnURL> <lib:FederationTerminationServiceURL>http://localhost:9080/sso-sample-idp/sso/fedterm</lib:FederationTerminationServiceURL> <lib:FederationTerminationServiceReturnURL>http://localhost:9080/sso-sample-idp/sso/fedterm</lib:FederationTerminationServiceReturnURL> <lib:SingleSignOnServiceURL>http://localhost:9080/sso-sample-idp/sso/authn</lib:SingleSignOnServiceURL> |
4. Customize the sample Identity Provider deployment by editing the file "sso-sample-idp/WEB-INF/sourceid-sso-providers.xml", and locate the block entitled "Sample Service Provider Descriptor". This block looks similar to the sample Identity Provider Descriptor edited in step 3. Again, find the endpoint URLs section, and customize these URLs to match the URL prefix of your actual deployment. The following XML fragment illustrates in red the URL prefixes which need customizing:
<lib:SPDescriptor xmlns:lib="http://projectliberty.org/schemas/core/2002/12" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <!-- ...portions omitted... --> <!-- The endpoints in the following URL's are correct for services offered by the ID-FF 1.1 Java Toolkit. If federating this installation with another instance of the toolkit, then all you need to do is customize the URL's to match your deployment (e.g. replace "http://localhost:9080/sso-sample-sp" with your server name and servlet context). --> <lib:AssertionConsumerServiceURL>http://localhost:9080/sso-sample-sp/sso/authnRequest</lib:AssertionConsumerServiceURL> <lib:SoapEndpoint>http://localhost:9080/sso-sample-sp/sso/soap/endpoint</lib:SoapEndpoint> <lib:SingleLogoutServiceURL>http://localhost:9080/sso-sample-sp/sso/logout</lib:SingleLogoutServiceURL> <lib:SingleLogoutServiceReturnURL>http://localhost:9080/sso-sample-sp/sso/logout</lib:SingleLogoutServiceReturnURL> <lib:FederationTerminationServiceURL>http://localhost:9080/sso-sample-sp/sso/fedterm</lib:FederationTerminationServiceURL> <lib:FederationTerminationServiceReturnURL>http://localhost:9080/sso-sample-sp/sso/fedterm</lib:FederationTerminationServiceReturnURL> |
5. The master web archive (sourceid-sso.war) comes configured to be Service Provider, with a sample ProviderID befitting a Service Provider. The last thing we need to customize is the Identity Provider deployment's configuration file to change its role to that of IDP. Edit the file sso-sample-idp/WEB-INF/sourceid-sso.xml and change the first two options to match the following:
<provider-id>SourceID-Sample-IDP</provider-id> <provider-role>idp</provider-role> |
6. Deploy these two directories into your Servlet Container, and start it up.
7. With your browser, visit the Service Provider home page (/sso-sample-sp/ in your deployment). Log on to a local account. Since the (demo) in-memory account handler is configured by default, any username and password will do (but remember the username you chose; you'll need it later).
8. After logging in to the sample Service Provider, click on the "Click to Federate" link. You'll be redirected to the sample Identity Provider, where you can log on again, this time using a different username and password (again, any combination will work, but remember the username you chose).
9. After logging in to the sample Identity Provider, you'll be redirected back to the sample Service Provider, and the two accounts will have been federated.
10. Close your browser, and launch it again (to clear any session cookies).
11. Again, visit the sample Service Provider login page. However, don't log in using the username and password created in step 7. Instead, click on the link near the bottom, "SourceID-Sample-IDP".
12. You will be redirected to the sample Identity Provider page. Log in using the username and password created in step 8.
13. After successful authentication, you'll be redirected back to the Service Provider home page, having now been logged in to both the Identity Provider and the Service Provider using a single authentication step (at the IDP).
14. At this point, you can test other capabilities of the Liberty Protocol, including Global Logout, and Federation Termination, by clicking on the appropriate links on the home pages of either the sample Service Provider or the sample Identity Provider.
This toolkit depends on several other Java tools and libraries. All of these libraries have amenable licenses (mostly based upon the BSD license), included in the docs/licenses subdirectory. The .jar files of all of these libraries upon which the toolkit depends, are already included in the web application's WEB-INF/lib subdirectory. These dependencies are:
Apache Jakarta Commons Logging, version 1.0.2
Apache Jakarta Log4J, version 1.2.7
Apache XML Xerces2-J, version 2.2.1
Apache XML Xalan-J, version 2.4.1
Apache XML Security for Java, version 1.0.5D2
Exolab Castor, version 0.9.4.2
Apache XML Axis, version 1.0
In addition, the Apache Ant build system is required in order to rebuild the toolkit from source; Ant is not required for deployment, and is not included in the distribution.
Unlike other toolkits, the ID-FF 1.1 Java Toolkit is not a simple library of functions. Rather, it is a complete Servlet framework, meant to be "forward-facing" and directly answering invocations from clients (be they browser-based or SOAP-based). The toolkit will handle all incoming traffic from your Servlet container which is Liberty Protocol specific. This toolkit will parse these requests, validate them for correctness, verify their digital signatures (if any), and lastly, delegate business logic and persistence logic to your developer-provided plug-in points. After these messages are handled by the toolkit (with possible delegation of business logic to your code), it will construct appropriate Liberty Protocol message responses, sign them, and send them back out over the wire.
In addition to responding to Liberty messages from the outside world, the toolkit provides an invocation framework for your web application (which co-exists in the same Servlet context as the toolkit) to initiate Liberty message events. This toolkit will handle your message request, interact with remote Identity or Service providers as appropriate (as well as redirect the end-user's browser as appropriate), and finally, return control back to your web application (with resultant messages) when the request completes.
It is important to delineate exactly what the ID-FF 1.1 Java Toolkit is NOT:
The toolkit is NOT a persistence framework for storing and retrieving your existing account information, or for the new Liberty Protocol-specific account federation attributes. Instead, this toolkit depends upon a developer-provided "AccountHandler" adaptor to communicate with your permanent data store.
The toolkit does NOT perform authentication of your users. Instead, at appropriate times (as designated by the Liberty Protocol), the toolkit will delegate control to your JSP pages or Servlets where your normal authentication takes place. Once you have authenticated your users, control is passed back to the toolkit (along with each user's Unique Identifier), where further message handling occurs.
To deploy the toolkit, the developer must perform three primary tasks:
Configure the toolkit by editing sourceid-sso.xml, and by listing the other services you wish to Federate with in sourceid-sso-providers.xml.
Write an implementation of the interface org.sourceid.sso.handlers.AccountHandler, which acts as an adaptor between the toolkit and your persistent storage. Using this adaptor approach, your storage medium for accounts and federation attributes can be an SQL database, an LDAP directory, or anything else which can be accessed from Java.
Write JSP pages or Servlets which render nice User Interfaces for Liberty Protocol actions. This toolkit is packaged with sample JSP pages for performing all of the basic Liberty functions; these pages can be adapted easily, or relevent code sections cut-and-pasted into your existing JSP pages.
Again, it is the aim of this toolkit to make it as easy as possible to perform these tasks, with a minimum amount of dipping into lower-level subsystems (such as SOAP, XML, Liberty Protocol itself, etc.).
Logging in the ID-FF 1.1 Java Toolkit is extensive and easily customizable. We use the Apache Jakarta Commons-Logging factory, which acts as a wrapper around the "real" logging system of choice. By editing conf/commons-logging.properties, Commons-Logging can be wrapped around JDK 1.4's built-in logging, or around Apache Log4J. These logging systems, in turn, allow fine-grained control over which categories of event to log, which severities, and where to append log entries (files, databases, or even triggered email messages).
The four severities of logging (common to most logging systems), and their normative meaning to the toolkit, are as follows:
Debug. Of interest to developers only, or turned on for the benefit of debugging. Very verbose.
Info. This severity is not used by the toolkit.
Warn. The toolkit uses this logging severity to indicate a severe problem, occuring on the remote end of a conversation. It will make best efforts to recover from the problem, and it should not be considered a "show-stopper". Examples include the reception of a Liberty message from another provider, without a verifiable digital signature.
Error. Severe errors on the local installation of the toolkit will be logged with this severity. They typically require immediate attention in order to continue functioning properly. Examples include configuration options which are invalid, or an inability to load dependent libraries.
As a user, if you believe events are occuring and being logged in ways which do not fit the spirit and intent of the preceding severity descriptions, please describe the scenario in question on the sourceid-users mailing list for possible future revision.
Exception handling is relatively simple in this release of the toolkit. There are very few exceptions which we catch and try to recover from; in most cases, exceptions will "bubble upwards" in the call stack to the invoking toolkit Servlet. From there, we will package the exception into a Request attribute, and forward control onto the JSP page or Servlet you specify as the "default exception handler" in conf/sourceid-sso.xml. Exceptions are not caught, wrapped, and rethrown, as is common in some other multi-tiered systems. Instead, they are thrown as-is to your provided exception handler. This means that exceptions thrown can be of any type which extends "Exception".
As previously mentioned, the toolkit is intended to be co-deployed with your existing web applications; they will share the same Servlet context, and thus, some options will be configured together in web.xml.
The sample web.xml which is bundled with the toolkit distribution is relatively straightforward; it declares several Servlets (no Filters), and maps them all to URL namespaces beginning with "/sso/". These mappings can be customized away from "/sso/" (e.g. the path prefix is not a hard requirement), but we recommend leaving the /sso/ namespace alone for deployments until you are very familiar with its workings.
The following sections describe each option in sourceid-sso.xml. This file should be located in your web application's "WEB-INF" subdirectory.
This option declares the filename of your providers descriptor file. This file contains all of the attributes which define a provider (either a Servier Provider or an Identity Provider), as defined in the Liberty Protocol. Each deployment of a Liberty Protocol system (not necessarily based upon the toolkit) is expected to create an XML descriptor of the site, including it's unique Provider ID, it's URL endpoints for various Liberty messages, and the various profile styles it supports. This XML descriptor, in turn, is to be cut-and-pasted into other systems' provider directories, including sourceid-sso-providers.xml. In this way, the parameters by which account federation can occur with other systems, are defined.
The <default> element within <exception-handlers> should contain the URI of the JSP page or Servlet which you wish for the toolkit to forward Exceptions to. The default setting is an example exception handling JSP page, included with this distribution.
This block includes parameters needed by the toolkit in order to access your site's Public/Private keypair. The current release of the toolkit requires a standard Java keystore file, which can be generated using javatool. The toolkit is distributed with a sample key (located in conf/sourceid.keystore), along with a readme file (conf/readme.keystore) which describes the commands used to generate it. We recommend generating a new public/private keypair as part of every site installation.
This element contains the path to your keystore file. The default is to pull it from inside the WEB-INF subdirectory of your web application, but any path accessible by your Servlet container will work.
The global password of your keystore file.
The key name (or alias) within the keystore file to use.
The password associated with the specific key, often different from the global password for the whole file.
This important element is the unique ProviderID for your Liberty Protocol-enabled site. It is the "primary key" if you will, which other Liberty sites will use to recognize messages from your site. Using the public DNS name of your primary web site is a common practice.
Valid values for this element are "idp" or "sp", for Identity Provider or Service Provider. These roles are described in detail in the Liberty Architecture Overview.
If you are deploying the toolkit with the role of Identity Provider, then here you must provide the URL of your user authentication JSP page or Servlet. When the toolkit receives an authentication request from a remote Service Provider, it will delegate the request to the URI you specify here. After this page completes user authentication, it should forward control back to the toolkit's Authenticator servlet. Here the toolkit can establish an account federation (if the user requested it), and generate and return an assertion.
If you are deploying the with the role of Identity Provider, then here you may specify the "time to live" for all authentication assertions generated. It is expected that this value should not exceed the session inactivity timeout of your web application context.
If you are deploying the toolkit with the role of Identity Provider, then here you may specify the URL of the JSP page or Servlet which renders the "Single Logout Images" pages. Briefly, when an Identity Provider performs Global Logout, the user is redirected to a web page which contains a list of images, one for each Service Provider that they have authenticated with. The images's "src" attributes all point to the Service Providers' global logout service endpoints. After each Service Provider logs the user out, an HTTP redirect is issued (on the image) back to the Identity Provider. Finally, the Identity Provider will issue another redirect to an actual image (usually of an "OK" symbol or checkmark). This may all sound very complicated, but the toolkit is distributed with a sample IDP Logout Render Page (with accompanying "Checkmark" graphic) which is short and easily customizable.
Used in conjunction with the previous option, this option specifies the URL of the final "Done" graphic image to be shown a the end of the Logout process.
If you are deploying the toolkit with the role of Identity Provider, then here you may specify the URL of the JSP page or Servlet which renders a "Form Post" in Liberty Protocol terms. This page is used by the "brws-post" profile for Authentication. The JSP page provided in the sample application (and preconfigured in sourceid-sso.xml) works well, but this mechanism is provided to customize it (or simply change it's location in your web application) if needed.
When the toolkit processes logout requests (whether as an IDP or as an SP, and whether the request arrives via SOAP back-channel or HTTP front-channel), it will take care of "logging out" the user as far as it's internals are concerned. If your application tracks a user's "logged-in" state by way of a session-context attribute, then enter the attribute key here, and the toolkit will also remove your attribute from the user's session context upon logout.
When the toolkit generates authentication assertions, this tolerance value will be included in the SAML assertion generated. Enter the number of SECONDS of tolerance for "Not Before" here. The Liberty Protocol recommends a default value of 1 minute; the toolkit defaults to 1 minute (60 seconds) if this option is not present.
When the toolkit generates authentication assertions, this tolerance value will be included in the SAML assertion generated. Enter the number of SECONDS of tolerance for "Not On or After" here. The Liberty Protocol recommends a default value of 5 minutes; the toolkit defaults to 5 minutes (300 seconds) if this option is not present.
This option specifies the Java classname of your implementation of the AccountHandler interface. An implementation of this interface is needed in order for the toolkit to store and retrieve federation information. This distribution comes with a sample, in-memory-only AccountHandler. It's purpose is to facilitate testing, get the system up and running (in a demo capacity) with very little outside dependencies (e.g. you don't need to set up a database to see the toolkit work), and lastly, as an illustration of how to implement a "real" AccountHandler.
The toolkit also ships with a sample JDBC Account Handler, called AccountHandlerJDBC. It is configured by way of a simple configuration file, called sourceid-sso-jdbc.xml, which must be present in the WEB-INF directory of your Servlet Context. This adaptor accepts several SQL queries as parameters in the configuration XML file for storing and retrieving federation attributes from standard SQL tables. See the configuration file sourceid-sso-jdbc.xml for additional comments and examples regarding how to set up the JDBC account handler; lastly, be sure to modify sourceid-sso.xml, to specify the JDBC Account Handler (the default configuration is to use the in-memory Account Handler).
Finally, the toolkit also ships with a sample LDAP Account Handler (by way of JNDI), called AccountHandlerJNDI. It is configured by way of a simple configuration file, called sourceid-sso-jndi.xml, which must be present in the WEB-INF directory of your Servlet Context. By configuring sourceid-sso-jndi.xml, you can describe your Directory schema, including where to find the UserID attribute and where to find the Federation attributes. See the configuration file sourceid-sso-jndi.xml for additional comments and examples regarding how to set up the JNDI account handler; lastly, be sure to modify sourceid-sso.xml, to specify the JNDI Account Handler (the default configuration is to use the in-memory Account Handler).
This option specifies the Java classname of your implementation of the ArtifactHandler interface. The ArtifactHandler is used to temporarily store, retrieve, and expire (if unclaimed for a period of time) authentication assertions. The default configuration is to use the In-Memory Artifact Handler, suitable (and recommended) for single-server deployments. The interface exists as a pluggable compoent, however, for adaptation to larger systems (such as server clusters), where there is no guarantee that an artifact will be retrieved from the same server at which it was generated.
If you plan to support LECP (Liberty-Enabled Client or Proxy) and run the toolkit as an IDP, then you need to write an adaptor class for the toolkit to acquire the currently authenticated user "out of band". If you don't know what this is for, you almost certainly don't need it. The sample class below is for testing and illustration purposes only, do NOT deploy it in a production capacity (e.g. leave this commented out!). See the section on "Implementing an Out-of-Band Authentication Handler" for more information.
The Liberty Protocol defines a discovery mechanism called the Identity Provider Introduction protocol, used to determine an anonymous user's "preferred IDP". To use the Identity Provider Introduction via Common Domain Cookie (Liberty Bindings and Profiles, section 3.6), then uncomment these options (commented out by default) and configure your Common Domain (which you share with your other Identity Providers and Service Providers), as well as the host name (including port number if not standard) of this web application within that Common Domain. Leaving these options commented out will disable the Identity Provider Introduction protocol. Note that the triggering of the Identity Provider Introduction servlets (either as an IDP when it's time to write the cookie, or as an SP when it's time to read the cookie), are not automatic; you must explicitly trigger them from your JSP pages or Servlets at a time which is appropriate for your application. The sample JSP pages (for IDP and for SP) illustrate good use of these servlets and how to set or retrieve the user's preferred IDP.
If the toolkit is deployed as an Identity Provider (IDP), and you would like a chance to modify outbound SAML assertions before they are returned to the Service Providers (SP's) (so that, for example, you can insert custom attributes which are specific to your circle-of-trust), then you may implement an AssertionProviderHandler, and give it's class name below. The default value (commented out) is a sample AssertionProviderHandler, in the "test" package, which inserts the current userid as an extra attribute. You may customize or extend this sample, or build your own interface implementation from scatch.
The AccountHandler interface is a high-level interface between the toolkit and a persistent account storage. Custom persistence mechanisms need to implement the AccountHAndler interface, and be registered by classname in sourceid-sso.xml.
The central focus of the AccountHandler interface is the "userID", a generic Java Object meant to represent a single unique user in your persistent storage system. The toolkit doesn't care what class of object you use to refer to your users; all that is required is correct implementation of the Object.equals() and Object.hashCode() methods. The toolkit is told whom you're talking about by passing one of these objects, and later the toolkit might pass an object back to you to "talk about" the same user. Integer objects can be used if they are sequence-style primary keys in a relational database. String objects can also be used, if for example you wish to use a simple "username" as the user-identifying primary key class. In the LDAP world, a String containing a UID attribute is an appropriate choice of object class for AccountHandler's userID.
Lastly, your persistent storage medium might need to be extended in order to store Liberty-specific account federation attributes. For each account in your persistent storage, you will need to be able to store zero or more federation records, indicating that the account has been federated with an account on a remote Service or Identity Provider.
Each such "federation record" references a single account, and contains three additional attributes:
The ProviderID (a String) of the remote provider this account is federated with,
The Locally-Provided Name Identifier (a String), which the remote Provider will use to identify this user when sending us messages, and
The Remote-Provided Name Identifier (a String), which we will use when communicating with the remote Provider about this user.
As an example, assume we are using a relational database to storage account information. Assume also that we already have a database table in place, defined as follows:
CREATE TABLE accounts (username TEXT PRIMARY KEY, password TEXT)
In this scenario, we'll be required to add another table to store federation attributes, as follows:
CREATE TABLE account_federations (username TEXT, provider_id TEXT, local_name TEXT, remote_name TEXT)
where account_federations.username is a foreign key which references accounts.username. In addition, the combination of username and providerID can be designed as a (compound) primary key on the account_federations table.
The methods and parameters of the AccountHandler interface are explained below:
Upon Servlet initialization, a single instance of your AccountHandler implementation will be created, and it's init() method called. This instance will have the same lifecycle, and is expected to follow the same standard threading conventions as, a normal servlet. That is to say, only one instance will ever be created (per Servlet application context), and this one instance will serve multiple threads simultaneously.
Also following the lifecycle of the Servlet context, the destroy() method will be called upon shutdown or uninstallation of the Servlet Context.
When a user elects to federate an account at a Service Provider with an account at an Identity Provider, this method will be called to ask your persistent storage to store the federation. The toolkit will pass your userID object identifying the user (which your code will have already passed to the toolkit during a prior exchange), the ProviderID we wish to federate with, and the pair of names (localName and remoteName) to store.
Note that each NameIdentifier is a complex type composed of three sub-attributes: Name, Format, and Qualifier. However, since the toolkit will never ask for users using only a subset of these components, it is "safe" to munge these components together into a single String, before persistent storage, if you choose. This will be required, for example, to fit a NameIdentifier into a single field in a relational database. We recommend appending the three sub-attributes together into a single String, separated by colons (":"), as follows: "Name:Qualifier:Format". This munging recommendation is a convenience only, so that Liberty NameIdentifiers can occupy a single field, rather than three. If you wish to store the components separately, or if it is easy to do so (as is the case with Directory servers), then this is fine too.
If the federation already exists (e.g. there already is an entry for the given userID and providerID), then the toolkit expects you to overwrite the data with the new namePair supplied.
When a user elects to break a federation between two accounts (Defederate), this method will be called. Here, you should remove the userID-providerID federation attribute, if any. (For example, delete the row in the table, if using a relational database).
This method will be called by the toolkit to query on a ProviderID and NameIdentifier, and return a userID objec (or null if no such federation exists). The "isLocalProvidedNameIdentifier" boolean parameter indicates whether you should be looking for a match on the "localProvided", or on the "remoteProvided", NameIdentifier attribute.
This method will be called by the toolkit to retrieve the NameIdentiferPair (local- and remote-provided), given a specific UserID and ProviderID. "null" should be returned if no match is found.
The ArtifactHandler is meant to be a high-performance, self-expiring cache of Assertion Artifacts. The default implementation (in-memory) is sufficient for deployment in a typical single-server deployment scenario. Future versions of this document will discuss the interface in more detail; for now, please refer to the ArtifactHandler interface definition, and ArtifactHandlerInMemoryImpl implementation class, for further information. The interface is slightly simpler than the AccountHandler interface, and can be adapted in many ways to distributed server scenarios such as a J2EE bus.
This section pertains to implementations specifically interested in the LECP protocols (Liberty-Enabled Client or Proxy). LECP's are typically WAP gateways, browser proxies, or browser plugins, which intermediate the authentication process by automatically choosing an IDP on behalf of the user, retrieving the authentication, and posting it back to the SP.
The Service Provider (SP) side of the LECP protocol is fully specified in the Liberty Protocol and is completely "generic". Thus, no special implementation needs to occur in order to build a Service Provider with the toolkit which can "consume" LECP clients.
However, the Identity Provider (IDP) side of the LECP protocol is not fully specificied. It requires that an Identity Provider authenticate the user "out of band" from the Liberty protocol itself, and have those credentials ready ahead of time.
In order to support this, the toolkit supplies an interface called "OOBAuthnHandler". This simple interface has only one primary function: getAuthn(). It is your responsibility to build an class which implements this interface, and configure this class name in sourceid-sso.xml. At the appropriate time, the toolkit will call out to your class, passing it the HttpRequest originally received from the Servlet Container. In return, the toolkit expects for you to pass back the "UserID" of the user (as it is used elsewhere in this framework).
In typical deployments, the OOBAuthnHandler will retrieve the UserID from environment properties included in the HttpRequest. These might be HTTP headers (which might be set by an intermediating proxy), or perhaps from the client's IP address (also retrievable from the HttpRequest object).
The toolkit provides a sample OOBAuthnHandler, called OOBAuthnHandlerTest. This extremely simple handler looks for the HTTP header "SourceID-Test-UserID". If present, it uses the contents of this HTTP header as the actual UserID of the current user. Obviously this is completely insecure for deployment straight onto the Internet. But if there is an intermediating proxy (as is typically the case with LECP), then this header can be safely polled, as the proxy can prohibit the real client from spoofing it's value.
The OOBAuthnHandlerTest class can be used as a template for building your own handler.
The ID-FF 1.1 Java Toolkit will invoke your JSP pages or Servlets by way of Servlet Chaining (also known as RequestDispatcher.forward()). Your JSP pages or Servlets will also use this mechanism to return control back to the toolkit. Certainly, Servlet Chaining is not as straightforward a mechanism as simple class method calls. The toolkit makes this process as simple as it can be made to be, by using well-defined Request attribute names and values as "input" parameters for every such invocation. Request attributes are a good mechanism to "pass parameters" between Servlets in this way, because they are private to the invocate, and they automatically expire at the end of the HTTP request's processing.
Following is an example of a typical invocation. In this case, an IDP authentication page has just authenticated the user. It's now time to pass control back to the toolkit, so tht an assertion can be generated, an account federation created, and control passed back to the calling Service Provider:
<%-- idp/logon.jsp --%>
<%
// User just submitted their Username and password,
// we checked it against the database, it's good,
// and we've saved the UserID to our application's
// own session variable for later reference. Now we
// tell the toolkit about the authentication. We
// won't see the user again for a while, they'll be
// headed back to the Service Provider now.
request.setAttribute("UserID", userID);
request.setAttribute("AuthnMethod",
"urn:oasis:names:tc:SAML:1.0:am:password");
RequestDispatcher dispatch =
application.getNamedDispatcher("SourceID-SSO-Authenticator");
dispatch.forward(request, response);
%>
Because Request Attributes (not to be confused with Request Parameters) are short-lived, they really aren't useful for anything besides Servlet Chaining (the passing of control from one Servlet or JSP page to another). Consequently there is little risk of name clash between attributes set at different places in the codebase. For this reason, the toolkit uses Request attribute names which are short and easy to type, such as "UserID", "Return.Success", etc. These standardized attribute names (detailed in a later section) server as input parameters for invocations in to, or out of, the toolkit Servlets.
Session and ServletContext (application) Attributes, because they are long-lived, are more complicated to properly namespace. This must be done in order to ensure that there are no name clashes between the attributes the toolkit needs to keep, and those which your existing application codebase needs to keep. For this reason, all toolkit Session and ServletContext attributes will be prefixed with "org.sourceid.sso.". Ordinarily you will not need to bother with the contents of these attributes; when they do need attention, the toolkit will copy the references into more simply-named Request attributes before passing control to your code.
Following is a table describing all of the invocation points between the toolkit and your code. It should be well understood by now that these invocation points are only a piece of the overall Liberty Protocol message interactions, which are typically three-way interactions between a Service Provider, an Identity Provider, and the end-user's browser. The toolkit takes care of the bulk of message processing and coordination amongst these three parties; as a developer using the toolkit, all you need to deal with are these (relatively simplified) invocation points.
In the following sections, "Requests" are invocations made by the application into the toolkit, while "Delegations" are invocations made by the toolkit into web application code. In both cases, the mechanism is Servlet Chaining (e.g. RequestDispatcher.forward() ), and the "input" parameters are in the form of Request Attributes.
Lastly, the toolkit distribution comes with a complete (but simple) web application illustrating the use of all of these invocation points. There are a small set of JSP pages for the "Identity Provider" role, and another set of JSP pages for the "Service Provider" role. These JSP pages, in the name of simplicity, do not have have any external dependencies on Tag Libraries, including the JSTL. Consequently they have more than average amount of "plain Java code" in them. They are meant to illustrate the toolkit API, without necessarily being examples of good JSP coding technique.
|
Description: |
At a Service Provider's normal Login page, now that it's Liberty-enabled, it can offer to log the user on using local credentials (e.g. username and password), or it can offer to log the user on by way of a known Identity Provider. If the user chooses an Identity Provider, then the application should use this request to retrieve the IDP authentication. |
|
Example: |
See sp/logon.jsp |
|
Input Request Attributes: |
|
|
(Optional) ProviderID |
The unique ProviderID of the Identity Provider the user wishes to authenticate with. If this parameter is omitted, then the toolkit will assume you wish to initiate a LECP (Liberty-Enabled Client/Proxy) authentication with the client (in which case, a list of acceptable IDP's is sent to the client). If you are not using LECP, then you must supply a ProviderID in this parameter. If you do not know what LECP is, then you most likely don't need it. |
|
(Boolean) IsPassive |
False if the IDP can intercept the user session for a period of time. True to prevent this. See Liberty Protocols & Schema for further explanation. |
|
(Boolean) ForceAuthn |
True to force the IDP to re-authenticate the user, even if a session was already established. |
|
(Boolean) Federate |
True if the IDP should establish a federation if one doesn't already exist. If false, and if no federation already exists, then the authentication will fail. |
|
(String) Return.Success |
The URL of the JSP page or Servlet to return to, after this request completes successfully. |
|
(String) Return.Failure |
The URL of the JSP page or Servlet to return to, should this request fail. |
|
(org.sourceid.sso.xml.lib.AuthnContextType) AuthnContext |
(optional) A desired Authentication Context which the IDP must fulfill. See Liberty Protocols & Schema for further explanation. |
|
(String) AuthnContextComparison |
(optional) The value "minimum", "exact", or "better", with respect to the Authentication Context. See Liberty Protocols & Schema for further explanation. |
|
Output Request Attributes (present on Return.Success or Return.Failure): |
|
|
(Object) UserID |
The UserID of the authenticated user, or null if no authentication occurred |
|
(String) Failure.Reason |
If the request failed (and the user was forwarded to the Return.Failure page), then this attribute will contain a short code explaining the reason for failure. |
|
Description: |
The Logout request allows the user to log out of the Identity Provider where they first authenticated, and every Service Provider they have since authenticated to, all in one step. What's more, this action can be taken from the site of any one of the Service Providers, or the Identity Provider. In all cases, the toolkit request is the same. |
|
Example: |
See idp/logout.jsp or sp/logout.jsp |
|
Input Request Attributes: |
|
|
(String) ProviderID |
If the request originates from a Service Provider, then the ProviderID of the Identity Provider the user desires to Single Logout from, is required. This is because, at a Service Provider, the user may collect session authentications from more than one Identity Provider. On the other hand, if the request originates from an Identity Provider, then this input request attribute is not required, as the only option is to Single Logout from the present Identity Provider. |
|
(String) Return.Success |
The URL of the JSP page or Servlet to return to, after this request completes successfully. |
|
(String) Return.Failure |
The URL of the JSP page or Servlet to return to, should this request fail. |
|
Output Request Attributes (present on Return.Success or Return.Failure): |
|
|
AuthnMethod |
This can be a String object, indicating a simple authentication method (see example, or SAML for a list of valid strings), or, it can be an instance of org.sourceid.sso.xml.lib.AuthnContext, indicating the Liberty Protocol authentication context used. |
|
Description: |
The Terminate Federation request allows the user to terminate an account federation between the current site, and another site of opposite primary role (e.g. Terminate Federation between this Service Provider and another Identity Provider, or between this Identity Provider and another Service Provider). This action has the implicit effect invaliding the authenticated session between the SP and the IDP. |
|
Example: |
See idp/terminateFederation.jsp or sp/terminateFederation.jsp |
|
Input Request Attributes: |
|
|
(String) ProviderID |
The ProviderID of the remote site (whether Identity Provider or Service Provider), with which the current user wishes to Terminate Federation (break the account linkage). |
|
(Object) UserID |
The UserID of the current user who desires to terminate a federation. This is required because the Terminate Federation request does not require a prior authentication to occur. |
|
(String) Return.Success |
The URL of the JSP page or Servlet to return to, after this request completes successfully. |
|
(String) Return.Failure |
The URL of the JSP page or Servlet to return to, should this request fail. |
|
Output Request Attributes (present on Return.Success or Return.Failure): |
|
|
AuthnMethod |
This can be a String object, indicating a simple authentication method (see example, or SAML for a list of valid strings), or, it can be an instance of org.sourceid.sso.xml.lib.AuthnContext, indicating the Liberty Protocol authentication context used. |
|
Description: |
When a user requests to authenticate via an Identity Provider, the toolkit delegates the authentication logic to the application. The JSP page or Servlet invoked here is specified in sourceid-sso.xml, option <idp-authentication-uri>. On this page, the application should collect user credentials, authenticate the user, and return control back to the toolkit with the results. |
|
Example: |
See idp/logon.jsp |
|
Input Request Attributes: |
|
|
(org.sourceid.sso.xml.lib.AuthnRequestType) AuthnRequest |
The original authentication request, originating from the Service Provider. |
|
(org.sourceid.sso.xml.lib.AuthnContext) AuthnContext |
The desired authentication context, as expressed by the Service Provider. |
|
(String) AuthnContextComparison |
The authentication context comparison level, "minimum", "exact", or "better", desired by the Service Provider. |
|
(Boolean) Federate |
True if the IDP should establish a federation if one doesn't already exist. If false, and if no federation already exists, then the authentication will fail. |
|
(String) Return.Success |
The URL of the JSP page or Servlet to return to, after this request completes successfully. |
|
(String) Return.Failure |
The URL of the JSP page or Servlet to return to, should this request fail. |
|
(org.sourceid.sso.xml.lib.AuthnContextType) AuthnContext |
(optional) A desired Authentication Context which the IDP must fulfill. See Liberty Protocols & Schema for further explanation. |
|
(String) AuthnContextComparison |
(optional) The value "minimum", "exact", or "better", with respect to the Authentication Context. See Liberty Protocols & Schema for further explanation. |
|
When done, forward control back to this Servlet, with the additional Request attributes below: |
SourceID-SSO-Authenticator |
|
(Object) UserID |
The UserID of the authenticated user, or null if no authentication occurred |
|
AuthnMethod |
This can be a String object, indicating a simple authentication method (see example, or SAML for a list of valid strings), or, it can be an instance of org.sourceid.sso.xml.lib.AuthnContext, indicating the Liberty Protocol authentication context used. |
The ID-FF 1.1 Java Toolkit has been developed and tested on:
RedHat Linux 8.0 on Intel
Sun JDK 1.3.1_06 for Linux
Sun JDK 1.4.1_01 for Linux (see Deployment Environment Notes)
Apache Tomcat, version 4.1.18 (see Deployment Environment Notes)
PostgreSQL, version 7.2.3, for the JDBC Account Handler
OpenLDAP, version 2.0.25, for the LDAP (JNDI) Account Handler
Resin (Caucho), version 2.1.6 (see Deployment Environment Notes)
JBoss, version 3.0.4, with Jetty Servlet container as the default (see Deployment Environment Notes)
Orion, version 1.5.2b (see Deployment Environment Notes)
We would appreciate feedback on the SSO-Users mailing list with respect to other environments tested; this feedback will be inserted into future revisions of this document, with attribution to the testers who provided the feedback.
<lib:AuthnResponse> requires ProviderID in Liberty 1.1, but the toolkit has made the element optional for 1.0 compatibility.
Some internal session attributes are not aggressively cleaned up after use; more work is needed to clean up session variables after they're no longer needed.
There is some code duplication across the system, as there are several ways of doing (mostly) the same thing in Liberty. Examples include front-channel (browser) vs. back-channel (SOAP) messages for the same underlying command. In some cases, code is duplicated with only minor changes across two parts of the system. Over time, we hope to consolidate more of this logic by refactoring. In the interim, it is not a performance problem.
SourceID.org Home Page
Liberty Alliance Project Home Page