Cross-Domain Single Sign-On Authentication with JAAS

ingle sign-on (SSO) is a very hot topic. Businesses in every industry are eager to integrate legacy systems into newer applications, and SSO can alleviate the headaches users experience when trying to manage a long list of user names and passwords for various systems. Enter the Java Authentication and Authorization Service (JAAS).

As I wrote in a DevX 10-Minute Solution, “JAAS Security in Action“: JAAS “is a flexible, standardized API that supports runtime pluggability of security modules.” If you are unfamiliar with JAAS, I recommend reading that article and reviewing the downloadable code before continuing, as this article assumes an understanding of JAAS. It takes the next logical step from a security architecture standpoint: integrating your J2EE security model to provide SSO across multiple subsystems by leveraging your existing LDAP directory server, database server, or any other enterprise security system.

Before going any further, let’s clarify how this article uses the term “domain”: It refers to security domains (LDAP, database, etc.) and not Web domains. If you are interested in using JAAS to share authentication information between multiple Web applications, read the article “Implement Single Sign-on with JAAS” written by James Tao in October of 2002. Additionally, if you are interested in Web applications that exist across firewalls and participate in some sort of Web service exchange, read the joint Web Single Sign-On Identify specifications that Microsoft and Sun recently published.

Securing the Enterprise

Single sign-on allows users to enter security credentials once (typically by logging into a workstation or a Web application) and have those credentials propagated to each local and network application the user accesses during his or her session. Local applications exchange authentication information directly, while remote network applications exchange authentication information across the network via encrypted security tokens.

Regardless of whether the deployment scenario is local, across a network, or a combination of the two, the security challenges are the same: sharing credentials between domains, correctly interpreting the credentials once received, and managing different sets of privileges across these domains (e.g., a user could be a manager within one system, a power user in another system, and a normal user in a third).

Finally, the heterogeneous nature of most enterprise systems creates some unique challenges for SSO security architectures. Each application within the enterprise could be comprised of different technologies, operate on different platforms, access disparate data sources, and except slightly different authentication credentials for the same principal (user). In spite of these overwhelming obstacles, JAAS combined with LDAP provides a solid framework for designing and implementing a robust SSO enterprise security framework.

The Architecture

The backbone of a J2EE SSO architecture is the standard J2EE security model, which is well documented in other places (see Related Resources in the left-hand column). In a nutshell, J2EE security consists of principals (users) who are associated with roles (groups) that are given privileges (authorization). These roles with assigned privileges are further organized under the concept of a realm (domain). Each realm maps users and groups to privileges within its own scope. The key to providing SSO is seamlessly connecting these different realms (and corresponding enterprise systems) without requiring the user to enter authentication information each time he or she wishes to access another system.

Consider the following example: A user logs in to an application via HTTP, authenticating herself against the server’s security realm (MemoryRealm, JDBCRealm, JAASRealm, etc). The user then uses the Web application’s search feature, querying the database and returning a resultlist. The database could then require that the middleware platform authenticate against the DB before performing the transaction. Finally, the user wants to update information stored in her directory server (LDAP). This is a privileged action, requiring the user to first authenticate against the LDAP realm before modifying any directory data. All three of these realms likely require slightly different authentication schemes (different user IDs, passwords, additional security tokens, etc.), but the same principal (user) is accessing them each time.

Java can provide an elegant SSO solution for the above scenario (and any number of similar scenarios) using JAAS’s pluggable login module architecture. JAAS login modules facilitate the smooth integration of J2EE’s security framework with various systems and their respective heterogeneous authentication mechanisms (OS, LDAP, database, etc.). These modules can be configured to share authentication data and designed to correctly identify users and roles by mapping principals and roles?even across domains with differing security schemas.

The Components

The application components required for a JAAS SSO solution include the following:

  • Two or more enterprise systems that need a common, integrated security framework
  • Two or more JAAS login module classes to drive the authentication exchange between agent (user or subsystem) and callback handler
  • One or more JAAS callback handler classes to respond to callback events in order to perform the actual authentication procedure(s)
  • A login configuration file to define how JAAS will manage authentication across multiple security realms (configuration could even be stored in an XML file or database)

Assembling these components and connecting all of the pieces correctly can be a bit daunting the first time. Be sure to thoroughly test your JAAS authentication components individually with each system prior to attempting to link them and share authentication information. The process of packaging, deploying, and testing your solution should go something like this:

  1. Write a login module (implement LoginModule, a subtype of LoginContext) and a callback handler (implement CallbackHandler interface) for authenticating against a single enterprise system (LDAP, database, etc.).
  2. Define the configuration for your login module (this could be as simple as an XML file containing a single statement).
  3. Define a UI (Web, console, or rich GUI) to capture authentication data, and then pass it to your login module.
  4. If this is a server-based solution (HTTP, sockets, RMI, etc.), define the J2EE security (constraints and roles) on the server in the usual way (web.xml or application.xml), and then define a realm on the server (server.xml) that references the JAAS login module configuration (accomplished via the appName attribute). Local (non-server) solutions will simply rely upon JAAS and a J2SE policy file to define security constraints and permissions.
  5. Start the server (specifying the login configuration file via a Java command line attribute), launch the client, and provide authentication credentials. Debug and modify as necessary to resolve any errors.
  6. Rinse and repeat. Continue this process as necessary until each enterprise system can successfully be authenticated via a JAAS login module.
  7. Finally, hook all of the individual authentication pieces together. The following section addresses this issue.

The above list simply gives you a brief overview of the process. For more details on how to actually accomplish these steps, please consult the links in the Related Resources space.

Sharing Authentication Across Domains

The JAAS configuration file mentioned earlier defines configuration IDs, which contain one or more LoginModule definitions and corresponding attributes. The key to sharing authentication information across security domains is to have a single JAAS configuration ID that lists multiple login modules, with the second, third, and following modules specifying the useSharedState attribute as true (allowing security credentials to be shared).

The following is a sample configuration involving two systems, LDAP and an Oracle database, included within the same SSO architecture:

BasicAuth {	com.xyz.ldap.LDAPLoginModule required name=LDAPSecurityDomain;};DBAccessAuth {	com.xyz.ldap.LDAPLoginModule required name=LDAPSecurityDomain;com.xyz.db.OracleLoginModulerequired name=OracleSecurityDomainuseSharedState=true;};

Two configurations are defined (BasicAuth and DBAccessAuth) to provide the flexibility of authenticating a user against one or both systems.

To implement this, the first system (LDAP) is treated as the primary system. The corresponding login module should be setup as the security realm for the J2EE container (using the BasicAuth configuration). Once a user has authenticated against the primary system (see Figure 1), she can have her security credentials propagated to the other system(s) in the chain (using the DBAccessAuth) that require authenticated access (see Figure 2).

Click to enlarge
Figure 1: Initial System Authentication/Authorization Process Through JAAS
Click to enlarge
Figure 2: Subsequent System Authentication/Authorization Process Through JAAS

This simple example contains only two subsystems, but a more complex system could include as many JAAS login modules as systems that need to share security credentials. The key difference between how authentication occurs with the two subsystems is that the primary system has JAAS authentication handled automatically (the container manages the process since the login module is configured as a security realm). The secondary subsystem (as well as any subsequent systems) must be called programmatically via the login() method of LoginContext:

LoginContext ctx = new LoginContext( "DBAccessAuth", new SimpleCallbackHandler() );

The above example assumed a fairly ideal situation in which the user’s security credentials were the same for both subsystems. In real life, this is rarely the case. You often find yourself needing to integrate legacy systems with new applications, each requiring different credentials. You can accomplish this by using the original authentication information to unlock a secured datastore that houses secondary authentication information for the specified principal (one or more sets of credentials). Once you’ve obtained this other authentication information, you then can use it to authenticate transparently against any secondary systems. (For more details on this approach, read Vipin Samar and Charlie Lai’s article (PDF): “Making Login Services Independent of Authentication Technologies“.)

Voila! Single sign-on across multiple security domains by mapping primary credentials gathered from the user to secondary credentials stored on the server and used to authenticate transparently against other enterprise systems.

Single SSO in Your Enterprise Framework

SSO is a popular feature of modern enterprise systems. Unfortunately, implementing SSO can be difficult and error-prone. This brief article provides a high-level overview and guide for architects, developers, and/or managers who are interested in implementing a SSO security architecture within their current enterprise frameworks.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Overview

Recent Articles: