Java Development News:

SSO and Identity Management

By Justen Stepka

01 Dec 2005 | TheServerSide.com

The Problem

As web-applications have grown over the years to support various business processes, these applications have expanded the number of users, groups and roles that need to be managed by administrators.

With most of these applications, administration functions are controlled by a small sub-set of internal users that have permissions to access additional functionality where they become the gatekeeper for the security information and application deployment attributes.

The burden taken on with the administration grows as the number these systems are deployed. This is where single sign-on (SSO) and identity management can reduce the overall administration work when managing user information such as their password, attributes, group, and roles memberships in a centralized user repository.

Single Sign-On (SSO)

SSO varies in definition depending on who you talk too. The first is the most basic where the second is a further extension of the first and often referred to as the holy grail of SSO:

  1. A central repository where username and password information is kept and then used by all subscribing applications for authentication and authorization.
  2. When a user authenticates, they are then assigned a token. This token can then be used by other subscribing applications to assure the user is who they claim to be. With this token, the user can then bypass the authentication process and immediate being to use the application.

The benefits to using SSO are great in number, here a few features:

  • Termination of an account is instant across all applications.
  • Simplified authentication approach, all applications use the same method of authentication removing the burden of continually solving the same problem with each application.
  • Identity information does not have to be replicated between applications. This is useful for information such as addresses or user preferences.
  • Reduced number of authentication credentials for a user. Removing the need to remember multiple credentials resulting in replicated passwords.

Example Deployment Environment

If you are like most organizations (even open-sources projects for that matter), you have multiple systems online now. For the purpose of this article, we will assume ACME Corporation has the following requirements:

  • Active Directory Server storing all employee information.
  • Custom database storing customer information.
  • Inventory management application, for employees.
  • Public website where customers can order ACME widgets.
  • Intranet application where company information is posted, for employees.
  • Issue tracking software such as JIRA where customers log Widget defects.
  • Forum system software such as Jive where customers receive support for their Widgets.

This deployment might be something like the following:

Error! No topic specified.

Without SSO and shared identity information, as a customer you would need to register three separate accounts: one for the public website, another for the issue tracking system and a third to access the online forum system. Having to keep, maintain and use three separate accounts for these systems is rather annoying and cumbersome.

The goal is to unify the authentication for customers, so that each separate application does not maintain its’ own set of users, groups and permissions. By connecting the public website, issue tracking and online forum software together with a single customer database, when the customer registers with the public website (or any system that supports registration) the customer is then able to use the same username and password with all three sites.

Forward thinking applications these days are starting to expand their authentication to support external users through implementing an interface or directly connecting to LDAP. JIRA and Jive have been selected specifically for the support they offer when connecting to external authentication systems.

To those who are developing such applications that provide external authentication, if you are choosing to provide an LDAP only connection, this may limit your customers. For smaller corporations, or those who are running their systems at remote datacenters, LDAP may be too costly or overkill when a simple database will do. Providing the interface option then becomes a more flexible and elegant solution.

Designing for SSO

When developing your application to support the external use of authentication or authorization, there are a few natural breaks in functionality:

  • Authentication – The process of verifying the credentials provided by the requesting user.
  • Authorization – Determining whether a requesting user has access to a specific resource through group or role mapping.
  • Profile – The personal details and preferences that are associated to the user.
  • Management – Creating, modifying and deleting of security rules and relationships.

It is important to break out these operations into separate interfaces.

Though this may seem overly complex at first, often a deployment may not be able to support the external storage of all functionality. Breaking the interface implementations at these natural points makes it simpler too keep one of the interface implementations local to the developed application.

For example, you may keep authentication and authorization information in your custom database or LDAP server, but do not have the ability to write information to the server. Because the application can not write information to the server, it would then need to keep profile information local to the application stored internally.

Interface Examples

The interfaces provided for this example are as simple as possible, having a minimal set of Exceptions that could be expanded on to provide the client applications with better checked error handling.

Additional Exceptions might be:

  • InvalidPasswordException – the supplied password fails to meet requirements.
  • InvalidGroupException – the supplied group already exists or does not exist.
  • InvalidRoleException – the supplied role already exist or does not exist.

It is important to remember that as you add complexity to an already complex problem, the difficulty with implementing such a solution seems to go up ten-fold.

An existing interface system that already exists is OSUser ( http://www.opensymphony.com/osuser/ ), which is developed and maintained by the Open Symphony group.

Authentication

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

/**

* Authentication interface to be implemented by appliations wanting to provide custom

* authentication connectors.

*/

public interface Authentication {

/**

* The KEY to use when storing the authenticated user token.

*/

public final static String HTTP_SESSION_TOKEN_KEY = "httpSessionTokenKey";

 

/**

* Generic possitive/negative authentication.

*

* @param username The username.

* @param password The password.

* @throws AuthenticationException Invalid authentication, unable to authenticate the request.

*/

public void authenticate(String username, char[] password) throws AuthenticationException;

 

/**

* Generic possitive/negativae authentication. With this method, the request and reponse object

* are used to set any specific request information during the authentication, such as the SSO

* token key. The token key could be added to the session or to the user cookie for other

* applications to access when validating a user.

*

* @param username The username.

* @param password The password.

* @param request The http request object.

* @param response The http response object.

* @throws AuthenticationException Invalid authentication, unable to authenticate the request.

*/

public void authenticate(String username, char[] password, HttpServletRequest request,

HttpServletResponse response) throws AuthenticationException;

 

/**

* Validates an existing authentication for SSO. The implementation should check the session or

* the user cookies for an existing token and then verify that token.

*

* @param request The http request object.

* @param response The http response object.

* @throws AuthenticationException Invalid authentication, unable to validate the token.

*/

public void isValidSSO(HttpServletRequest request, HttpServletResponse response)

throws AuthenticationException;

}

Authorization

import java.util.List;

 

/**

* Authorization interface to be implemented by appliations wanting to provide custom

* authorization connectors.

*/

public interface Authorization {

 

/**

* Checks if the user is a member of the supplied group.

* @param username The username.

* @param group The group name.

* @return <code>true</code> if and only if the user a valid group member, otherwise

* <code>false</code>.

*/

public boolean isGroupMember(String username, String group);

 

/**

* Checks if the user is a member of the supplied role.

* @param username The username.

* @param role The role name.

* @return <code>true</code> if and only if the user a valid role member, otherwise

* <code>false</code>.

*/

public boolean isRoleMember(String username, String role);

 

/**

* Returns a list of groups the user is a member of.

* @param username The username.

* @return List of {@link String groups} the supplied user is a member of.

*/

public List listGroups(String username);

 

/**

* Returns a list of roles the user is a member of.

* @param username The username.

* @return List of {@link String roles} the supplied user is a member of.

*/

public List listRoles(String username);

Profile

public interface Profile {

/**

* Adds an attribute to the user.

*

* @param username The username.

* @param key The key.

* @param value The value.

* @throws InvalidUserException Invalid username.

*/

public void addAttribute(String username, String key, String value) throws InvalidUserException;

 

/**

* Removes an attribute from the user.

*

* @param username The username.

* @param key The attribute key.

* @param value The attribute value.

* @throws InvalidUserException Invalid username.

*/

public void removeAttribute(String username, String key, String value) throws InvalidUserException;

 

 

/**

* Obtains an attribute for a user.

*

* @param username The username.

* @param key The key.

* @return The value.

* @throws InvalidUserException Invalid username.

*/

public String getAttribute(String username, String key) throws InvalidUserException;

}

Management

/**

* Management interface to be implemented by appliations wanting to provide identity management

* capabilities.

*/

public interface Management {

/**

* Adds a user to the identify management server.

*

* @param username The username.

* @param password The password.

* @throws InvalidUserException Unable to add the user.

*/

public void addUser(String username, char[] password) throws InvalidUserException;

 

/**

* Removes a user from the identity management server.

*

* @param username The username.

* @throws InvalidUserException Unable to remove the user.

*/

public void removeUser(String username) throws InvalidUserException;

 

/**

* Changes the password for the user.

*

* @param username The username.

* @param password The password.

* @throws InvalidUserException Unable to change the password for the user.

*/

public void changePassword(String username, char[] password) throws InvalidUserException;

 

/**

* Adds a user to a group.

*

* @param username The username.

* @param group The group.

* @throws InvalidUserException Unable to add the user to the group.

*/

public void addToGroup(String username, String group) throws InvalidUserException;

 

/**

* Adds a user to a role.

*

* @param username The username.

* @param role The group.

* @throws InvalidUserException Unable to add the user to the role.

*/

public void addToRole(String username, String role) throws InvalidUserException;

 

/**

* Removes a user from a group.

*

* @param username The username.

* @param group The group.

* @throws InvalidUserException Unable to remove the user from the group.

*/

public void removeFromGroup(String username, String group) throws InvalidUserException;

 

/**

* Removes a user from a role.

*

* @param username The username.

* @param group The group.

* @throws InvalidUserException Unable to remove the user from the group.

*/

public void removeFromRole(String username, String group) throws InvalidUserException;

}

The simplest approach is to load the implementations off of a deployment configuration file following the DAO Factory model. The DAO Factory model is a core J2EE pattern, more about this pattern can be found at http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html .

Using this interface approach will allow you to quickly integrate dynamic security rules as your organization and application grows.

The Solutions

JAAS (Java Authentication and Authorization Services)

Open-Source Solutions

  • JOSSO, or Java Open Single Sign-On, is an open source J2EE-based SSO infrastructure aimed to provide a solution for centralized platform neutral user authentication. JOSSO works much like JAAS bug provides a communication layer that can query a centralized server which then plugs into an LDAP server using the supplied LDIF. Customized authentication interfaces may be coded.
  • CAS, or central authentication service is an authentication service developed by Yale University that uses an HTTP to a centralized proxy server for authentication. Once a successful authentication occurs, the user is then assigned a ticket that can be validated by the client web-application. The centralized server can be configured using an interface system to support a pluggable authentication into existing user stores.
  • The Java Authentication and Authorization Service (JAAS) is a set of APIs that enable services to authenticate and enforce access controls upon users. It implements a Java technology version of the standard Pluggable Authentication Module (PAM) framework, and supports user-based authorization JAAS works by programming to an authentication or authorization interface system that is standardized by the Java security API. So long as pluggable interfaces are kept complete, this approach can be used to plug into just about any username and password authentication system.

Commercial Solutions

  • IDX is an application security framework that handles authentication and authorization for your web-applications. With IDX you can quickly integrate web-applications into a single security architecture that supports single sign-on and centralized identity management. The application is divided into two parts: the administration console is a clean and powerful web-interface to manage directories, users and their security rights. The integration API provides a platform neutral way to integrate web-applications into a single security architecture. With the integration API, applications can quickly access user information or perform security checks.
  • Siteminder is an application server that provides SSO, a centralized security policy server, enterprise manageability, federated identity support that is open and easily extensible.

About the Author

Justen is an expert in the processes and development of enterprise level software solutions. He brings together a wide range of skills to assist clients who are developing technology solutions. Justen works for Authentisoft, where they develop the IDX - Identity Exchange SSO and identity management framework (http://www.authentisoft.com).

Additionally, Justen will be speaking at the up coming 2006 TheServerSide Java Symposium (http://javasymposium.techtarget.com) as part of the industry security panel.