Sun ONE logo     Previous     Contents     Index     Next     
Sun ONE Identity Server Programmer's Guide



Chapter 4   Single Sign-On


The Sun™ One Identity Server provides a single sign-on (SSO) solution that enables a user to authenticate once to access multiple resources. In other words, successive attempts by a user to access protected resources will not require them to provide authentication credentials for each attempt. This chapter explains the solution, how it works and the SSO APIs. It contains the following sections:



Overview

Identity Server uses access control instructions (ACIs) to define administrative privileges that will protect an organization's proprietary data and web resources from unauthorized persons. A user wanting to access these protected resources must first pass validating credentials through the Authentication Service. A successful authentication gives the user authorization to access the protected resources, based on their assigned policies, roles or other such instructions. If a user wants to access several resources protected by Identity Server, the Session (or SSO) Service provides proof of authorization so there is no need to re-authenticate. As different domains generally have common users who need to generate access to their services in a single user session, Identity Server has also added a cross-domain functionality to the Session Service.


Contacting A Policy Agent

When a user attempts to access a protected resource via a web browser, a policy agent installed on the server that hosts the resource intercepts the request. The policy agent then inspects the request to see if a user session identifier, or token, exists. If none exists, the request is passed to the Identity Server where it first contacts the Session Service to create a session token and then the Authentication Service which pushes a login page to verify the user.



Note

Policy agents police the web server or application server on which the protected resource lives and enforce user policy. They are available for installation separately from the Identity Server. Additional information can be found in the Sun ONE Identity Server Policy Agent Guide.




Creating A Session Token

Before a user's credentials can be authenticated, a session token is generated by the Session Service. Each token contains a randomly-generated Identity Server session identifier which ultimately represents the authenticated user. Once created, the Authentication Service inserts the token into a cookie and assigns it to the client browser. At the same time the token is assigned, a login page is returned to the user based upon their organization's method of authentication (LDAP, RADIUS, Unix, etc.).



Note

The session token, at this point, is in an invalid state and will remain in one until the user has completed authentication.




Providing User Credentials

The user, having received the correct login page as well as a session token, fills in the appropriate authorization information based on the login page returned. After the user enters their credentials, the data is sent to the authentication provider (LDAP server, RADIUS server, etc.) for verification. Once the provider has successfully verified the credentials, the user is authenticated. The user's specific session information is retrieved from the token and the session state is set to valid. The user can now be redirected to the resource they were attempting to access.



Cookies and Session Tokens



A cookie is an information packet generated by a web server and passed to a web browser. It maintains information about the user's habits with regards to the web server it is generated by. It does not imply that the user is authenticated. Cookies are domain-specific; for example, a cookie generated by domainone.com cannot be used in domaintwo.com. In an Identity Server implementation, the cookie is generated by the Session Service and set by the Authentication Service. In addition, Identity Server cookies are session cookies that are stored in memory only.

A session token is generated by the Session Service and inserted into a cookie. It is generated using a secure random number generator and contains Identity Server-specific session information. Before a protected resource is accessed, the user is validated by the Authentication Service and a SSO token is created.



Cross-Domain Support For SSO



Identity Server supports cross-domain SSO. A user authenticated to Identity Server in one domain can access resources protected by a web agent in another domain. For example, in one scenario, the Identity Server instance for DomainA is the authentication provider. A user authenticates to Identity Server in DomainA and, after authentication, the token is set for DomainA. ServerB is protected by a web agent talking to an Identity Server in DomainB.



Note

It is not obligatory to have an installed instance of Identity Server in both domains to use the cross-domain feature.



The Identity Server in DomainB recognizes the DomainA server as its authentication provider. If UserA accesses a resource on ServerB after authenticating to DomainA, the policy agent at DomainB checks for a SSO token and finds that there is no token authorizing access to DomainB. In a cross-domain SSO scenario, the agent will redirect the user to the URL of the cross-domain component running with the Identity Server instance in DomainB. This component redirects the request to the cross-domain component in DomainA since the Identity Server in DomainA is the authentication provider. This request contains the SSO token set by Identity Server in DomainA in the cookie header. The cross-domain component at DomainA will send a response back to the component in DomainB with access authorization if their configured policy permits it. The DomainB component validates the SSO token from DomainA and creates an SSO token for the user in DomainB. This process sets a cookie for the user in DomainB.

If a user accesses a resource directly at DomainB without authenticating at DomainA, the user is redirected to authentication at DomainA. If the authentication is successful, the SSO token is sent to DomainB from DomainA. The ServerB validates the SSO token with DomainA, creates it for DomainB and redirects the user to the original requested resource.



Note

Identity Server uses a combination of URL parameters and cookies to implement cross-domain SSO. If a cookie is set in DomainA, the cookie value is carried over to DomainB using parameters, and a new cookie will be set with the same cookie name and value, but a different cookie domain.




Enabling Cross-Domain Single Sign-On

To enable cross-domain SSO, the administrator needs to install two different components: the Cross Domain Controller and the CDSSO Component. The Cross Domain Controller component comes bundled, and is installed, with Identity Server. The CDSSO Component needs to be installed separately onto all participating DNS domain servers.



Note

The administrator can choose not to enable the cross-domain feature; in this case, the CDSSO component would function within a single domain.




Cross Domain Controller

The Cross Domain Controller (CDC) is associated with the Identity Server that is protecting a specific domain. It redirects a request to either the Authentication Service or to the SSO Component. When a HTTP request comes into the CDC and no SSO token information is found, the request is redirected to the Authentication Service. If a SSO token is found for another domain, the request is redirected to the SSO Component with the appropriate session information appended to the query string.


CDSSO Component

The CDSSO Component is deployed in each Identity Server-protected domain. When a user attempts to access a resource, the request is intercepted by the policy agent as discussed in "Contacting A Policy Agent". If no SSO token is found, the request is redirected to the CDSSO Component in the domain where the resource exists. The CDSSO Component searches the query string again for the SSO token. As no token is found, the request is redirected to the Cross Domain Controller associated with the Identity Server that protects the resource. From this point, the authentication process will be followed.



Note

If a SSO token is found by the policy agent when the request is made, the CDSSO Component would not receive the request as the agent would validate the token as described in Chapter 3 "Authentication Service."




Configuring For Cross-Domain SSO

The SSO components need to be enabled in order to allow the cross-domain SSO function to work. Assuming a single Identity Server instance:

  1. Install Identity Server in a primary DNS domain.

    This will install the complete Identity Server application as well as the CDC component. The default CDC service URL, after installation, is http(s)://Identity_Server_host:port/amserver/cdcservlet.

  2. Run the installer again on a machine in all participating DNS domains and choose the Cross-Domain Support option.

    All machines in participating DNS domains need to have an instance of the CDSSO component installed. After running this option, a CDSSO directory is created in <identity_server_root>/SUNWam/web-apps. The default CDSSO Component service URL is http(s)://<CDSSO_domain_host>:<port>/ uri/cdsso.



    Note

    Install the CDSSO Component on any web server with host services (in all participating DNS domains) that need to be protected.



  3. Edit the com.iplanet.services.cdsso.cookiedomain property in the cdsso.properties file found in the <identity_server_root>/SUNWam/ web-apps/cdsso/WEB-INF/classes directory.

    The com.iplanet.services.cdsso.cookiedomain property must be set to the domain name which hosts the CDSSO component installed in Step 2. Code Example 4-1 is copied from the file itself.



    Code Example 4-1    Portion of CDSSO.properties file  
    * The following keys will be used for Cross Domain SSO support.
    * The user if needs cross domain sso support should change
    *"com.iplanet.services.cdsso.CDCURL" property to point to the
    * cdcservlet running with the Identity Server instance
    * "com.iplanet.services.cdsso.cookiedomain" property should
    * specify a comma separated list of domains for which the cdsso
    * servlet will set a SSOToken.
    * Ex:com.iplanet.services.cdsso.cookiedomain=.sales.com, .eng.com,.marketing.com
    */

    com.iplanet.services.cdsso.CDCURL=http://example.domain_name.com :8080/amserver/cdcservlet
    com.iplanet.services.cdsso.cookiedomain=.sales.com
    /*
    ...

  4. The following three properties, specific to the policy agent, need to be edited in each policy agent's AMAgent.properties file if the agent was not originally installed with CDSSO enabled.

    • Change the value of com.iplanet.am.policy.agents.ccdsso-enabled to enable cross-domain SSO. Code Example 4-2 illustrates this property.



      Code Example 4-2    Portion of AMAgent.properties file 
      #Is CDSSO enabled
      com.sun.am.policy.agents.ccdsso-enabled=true
      ...

    • Modify the SSO redirect URL. Code Example 4-3 illustrates this property.



      Code Example 4-3    Second portion of AMAgent.properties file 
      *login in a CDSSO Scenario.
      com.sun.am.policy.agents.cdsso-component.url=http://<cdsso_host> :<cdsso_port>/<uri>/cdsso
      ...

    • Add the SSO service URL to the not enforced list. Code Example 4-3 illustrates this property.



...
/*If cross domain sso support is enabled notenforcelist should be *edited to add cdsso servlet URL in it
com.sun.am.policy.agents.notenforcedList=*/amcdsso/*
...

Third portion of AMAgent.properties file"> Code Example 4-4   

...
/*If cross domain sso support is enabled notenforcelist should be *edited to add cdsso servlet URL in it
com.sun.am.policy.agents.notenforcedList=*/amcdsso/*
...

Third portion of AMAgent.properties file
This instance of Identity Server and all its participating DNS domains are now cross-domain SSO enabled.



Note

The cross-domain SSO solution assumes a single Identity Server instance; therefore all user and policy information needs to be centralized in that instance. Multiple Identity Server instances are allowed only if they are all in the same domain.





SSO API



The SSO solution provides Java API to allow external applications to participate in the SSO functionality. All Identity Server services (except for Authentication) need a valid SSO token to process a HTTP request. External applications wishing to use the SSO functionality must use the SSO token to validate the user's identity. With the SSO API, an external application can get the token and, in turn, the identity of a user and related authentication information. Once a user is authenticated, this information is used to determine whether or not to provide access to the requested resource based on the validated user's policy. The SSO API can also be used to create or destroy a SSO token, to check the token's validity or to listen for token events. (An event might be a token timing out because the user has reached the token's maximum time limit.)


Non-Web-Based Applications

Identity Server provides the SSO component primarily for web-based applications, although it can be extended to any non-web-based applications with limitations. With non-web-based applications, their are two possible ways to use the API.

  1. The application has to obtain the Identity Server cookie value and pass it into the SSO client methods to get to the SSO token. The method used for this process is application-specific.

  2. Command line applications, such as amadmin, can be used. In this case, SSO tokens can be created to access the Directory Server directly. There is no session created, making the Identity Server access valid only within that process or VM.


API Overview

The primary purpose of the SSO API is to allow any service or application to make use of the SSO functionality. They are provided for the implementation of a SSO solution in external applications. Using these APIs, the identity of the user and related authentication information can be called. The application then uses this information to determine whether to provide user access to a protected resource. The SSO client applications get the information from the SSO token. For example, assume a user authenticates to http://www.DomainA.com/Store successfully and later tries to access http://www.DomainB.com/UpdateInfo. Rather than having the application authenticate the user again, it can use the API to determine if the user is already authenticated. If the methods indicate that the user is valid and has already been authenticated, access to this page can be given without the user authenticating again. Otherwise, the user is prompted to authenticate again.

Each time a user attempts to access a protected application, the application needs to verify their validity. Generally, the SSO component generates a SSO token for a user once the user is authenticated. After generation, the token is carried with the user as the user moves around the web. When the user attempts to access an application or service that is SSO-enabled, this token is used for user validation. Specifically, an instance of the SSOTokenManager class is created to allow access to the createSSOToken, destroyToken and isValidToken methods. An instance of the SSOToken class is then called; it contains the session information. Between the two, an application can determine if the user is authenticated. Another way to use the API is to invoke the SSOTokenListener interface which notifies the application when a token has become invalid in order for the application to terminate its access.



Note The Identity Server Javadocs can be accessed from any browser by copying the complete <identity_server_root>/SUNWam/docs/ directory into the <identity_server_root>/SUNWam/public_html directory and pointing the browser to http://<server_name.domain_name>:<port>/docs/index.html.




SSOTokenManager Class

The SSOTokenManager class must be implemented to create one instance per token. It contains the three methods needed to create, get, validate and destroy SSO tokens. The createSSOToken() method is called to create a session token. It contains methods for doing this using the command line or through the internet. The destroyToken() method is called to delete a token when its session has ended. The isValidToken() and validateToken() methods can be called to verify the authenticity of a token. isValidToken() returns true or false depending on whether the token is valid or invalid, respectively. validateToken() throws an exception only when the token is invalid; nothing happens if the token is valid.



Note

SSOTokenManager is a final class and a singleton. SSOToken and SSOTokenID are Java interfaces. Additionally, SSOTokenListener and SSOTokenEvent are provided to support notification when SSO tokens are invalidated.




Sample SSOTokenManager Code
The SSOTokenManager class can be used in the following way to determine if a user is authenticated:



Code Example 4-5    Sample SSOTokenManager Code
/* create the sso token from http request */
SSOTokenManager manager = SSOTokenManager.getInstance();

/* The request here is the HttpServletRequest. */
SSOToken token = manager.createSSOToken(request);

/* use isValid to method to check if the token is valid or not
* this method returns true for valid token, false otherwise*/
if (token.isValid()) {

/* user is valid, this information may be enough for some
* applications to grant access to the requested resource.
* A valid user represents a user who is already authenticated,
* by some means. If access can be given based on this
* further check on user information is not necessary.
*/

/* let us get some user information */
String host = token.getHostName();
java.security.Principal principal = token.getPrincipal();
String authType = token.getAuthType();
int level = token.getAuthLevel();

..........

} else {
/* token is not valid, redirect the user login page */
}
...


SSO Implementations
The SSOTokenManager maintains a configuration database of valid implementations for SSOProvider, SSOToken and SSOTokenID. A request to SSOTokenManager gets delegated to the SSOProvider. Hence, the SSOProvider performs the bulk of the function of SSOTokenManager. The SSOToken is the SSO token that contains the crucial information about the token, and SSOTokenID is a string representation of SSO token. Although SSOTokenManager could support multiple and disparate providers, the only valid SSO provider is SSOProvider.


Additional Classes

The following classes can be used to implement customized SSO functionality in an application that does not use the default SSOProvider provided.


SSOToken
The SSOToken class represents a "single sign-on" token and contains information like the user validation, the authentication method, the host name of the client browser that sent the request, and session information (maximum session time, maximum session idle time, session idle time, etc.). Code Example 4-5 also makes use of the SSOToken interface.


SSOTokenEvent
The SSOTokenEvent class represents a token event. An event is, for instance, when a token becomes invalid due to idle time-out or hitting a time limit maximum. A token is granted when a change in the state of the token, like those mentioned, occurs. An application must come to know of events in order to terminate access to the application for a user whose token has become invalid. The SSOTokenListener class would need to be implemented by applications to receive SSO token events.

Sample SSOTokenEvent Code. The SSOTokenEvent class can be used in the following way to get SSO Token events:



Code Example 4-6    Sample SSOTokenEvent Code 
public class AppTokenListener implements SSOTokenListener {
public void ssoTokenChanged(SSOTokenEvent event) {
try {
SSOToken token = event.getToken();
int type = event.getType();
long time = event.getTime();
SSOTokenID id = token.getTokenID();
System.out.println("Token id: " + id.toString() + "is not valid anymore");
/* redirect user to login */
......
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
...
SSOTokenListener myListener = new AppTokenListener();
token.addSSOTokenListener(myListener);



SSOTokenID
The SSOTokenID class is used to identify the SSOToken object. Additionally, the SSOTokenID string contains a random number, the SSO server host, and server port. The random string in the SSOTokenID is unique on a given server. In the case of services written using a servlet container, the SSOTokenID can be communicated from one servlet to another either:

  • as a cookie in a HTTP header; or

  • as an implementation of the SSOTokenListener interface by the applications to receive the SSO token events.


SSOTokenListener
The SSOTokenListener interface provides a mechanism for applications that need notification when an SSO token expires. (It could expire if it reached its maximum session time, or idle time, or an administrator might have terminated the session.) Applications wishing to be notified must invoke the addSSOTokenListener method using the SSOToken interface; this method implements the SSOTokenListener interface. A callback object will be invoked when the SSO token expires. Using the SSOTokenEvent (provided through the callback), applications can determine the time, and the cause of the SSO token expiration.



Note

Once an application registers for SSO token events using addSSOTokenListener, any SSO token event will invoke the ssoTokenChanged method. The application can take suitable action in this method.




Sample API Code

Following are examples of code that illustrate various operations that can be performed by the SSO API.


User Authentication Sample Code

This code can be used to determine if a user is authenticated. (Additionally, the API can be used to perform a query on a token for information such as host name, IP address, or idle time).



Code Example 4-7    Code Sample To Determine If User Is Authenticated 
try {
ServletOutputStream out = response.getOutputStream();

/* create the sso token from http request */
SSOTokenManager manager = SSOTokenManager.getInstance();
SSOToken token = manager.createSSOToken(request);

/* use isValid method to check if the token is valid
* this method returns true for valid token, false non
*/
if (manager.isValidToken(token)) {
/* let us get all the values from the token */

String host = token.getHostName();
java.security.Principal principal = token.getPrincipal();
String authType = token.getAuthType();
int level = token.getAuthLevel();
InetAddress ipAddress = token.getIPAddress();
long maxTime = token.getMaxSessionTime();
long idleTime = token.getIdleTime();
long maxIdleTime = token.getMaxIdleTime();
out.println("SSOToken host name: " + host);
out.println("SSOToken Principal name: " + principal.getName());
out.println("Authentication type used: " + authType);
out.println("IPAddress of the host: " +
ipAddress.getHostAddress());
}
/* try to validate the token again, with another method
* if token is invalid, this method throws exception
*/
manager.validateToken(token);

/* get the SSOTokenID associated with the token */
SSOTokenID tokenId = token.getTokenID();

String id = tokenId.toString();

/* print the string representation of the token */

out.println("The token id is " + id);

/* set properties in the token. We can get the values
* of set properties later
*/
token.setProperty("Company", "Sun Microsystems");
token.setProperty("Country", "USA");
String name = token.getProperty("Company");
String country = token.getProperty("Country");

out.println("Property: Company is - " + name);
out.println("Property: Country is - " + country);

out.println("SSO Token Validation test Succeeded");
/* add a listener to the SSOToken. Whenever a token
* event arrives, ssoTokenChanged method of the
* listener will get called.
*/
SSOTokenListener myListener = new SampleTokenListener();

token.addSSOTokenListener(myListener);
out.flush();
} catch (Exception e) {
System.out.println("Exception Message: " + e.getMessage());
e.printStackTrace();
}
}
}

In some cases, it might be more efficient and convenient to use SSOTokenManager.validateToken(token) than SSOTokenManager.isValidToken(token). SSOTokenManager.validToken(token) throws an exception when the token is invalid, thus terminating the method execution right away.


Get Token Sample Code

This sample code can be used to get the SSO token if the SSOtokenID string is passed to the application.



Code Example 4-8    Code Sample To Get Token from Token ID 
/* create the sso token from SSO Token Id string */
SSOTokenManager manager=SSOTokenManager.getInstance();
SSOToken token = manager.createSSOToken(tokenString);
* let us get the SSOTokenID associated with the token */
SSOTokenID id = token.getTokenID();

String tokenId = id.toString();

/* print the string representation of the token */

System.out.println("The token ID is " + tokenId);

/* set properties in the token. We can get the values
* of set properties later */

token.setProperty("Company", "Sun Microsystems");
token.setProperty("Country", "USA");
String name = token.getProperty("Company");
String country = token.getProperty("Country");

System.out.println("Property: Company is - " + name);
System.out.println("Property: Country is - " + country);

System.out.println("SSO Token Validation test Succeeded");
/* add a listener to the SSOToken. Whenever a token
* event arrives, ssoTokenChanged method of the
* listener will get called.
*/
SSOTokenListener myListener = new SampleTokenListener();

token.addSSOTokenListener(myListener);
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
SSOTokenManager manager=SSOTokenManager.getInstance();
SSOToken token = manager.createSSOToken(tokenString);
}
}



Listen For Event Code Sample

Applications can listen for SSO token events. It is possible that while a user is using an application, an SSO token may become invalid because, for example:

  • the user's access times out because of the maximum time limit; or,

  • the user fails to log out of an application and the idle time-out expires.

The application must be informed of these events to follow-up on the invalid token by terminating the user's access. The following two sample codes can be used to get token events.



Code Example 4-9    Code Sample To Register For SSOToken Events
token.addSSOTokenListener(myListener);


where SampleTokenListener is a class defined as:



Code Example 4-10    Code Sample Defining SampleTokenListener Class 
public class SampleTokenListener implements SSOTokenListener {

public void ssoTokenChanged(SSOTokenEvent event) {
try {
SSOToken token = event.getToken();
int type = event.getType();
long time = event.getTime();

SSOTokenID id = token.getTokenID();

System.out.println("Token id is: " + id.toString());

if (SSOTokenManager.getInstance().isValidToken(token)) {
System.out.println("Token is Valid");
} else {
System.out.println("Token is Invalid");
}

switch(type) {
case SSOTokenEvent.SSO_TOKEN_IDLE_TIMEOUT:
System.out.println("Token Idle Timeout event");
break;
case SSOTokenEvent.SSO_TOKEN_MAX_TIMEOUT:
System.out.println("Token Max Timeout event");
break;
case SSOTokenEvent.SSO_TOKEN_DESTROY:
System.out.println("Token Destroyed event");
break;
default:
System.out.println("Unknown Token event");
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}

After the application registers for SSO token events using addSSOTokenListener, any SSO token events will invoke the ssoTokenChanged() method. The application can take a suitable action in this method.



Sample SSO Java Files



Identity Server provides three groups of sample Java files. With these samples, a developer can create an SSO token in several ways:

  1. An SSO token can be created for an application that runs on the Identity Server server.

  2. An SSO token can be created for an application that runs on a server other than the Identity Server server.

  3. An SSO token can be created by a session ID string can be passed through the command line.

The files are in the <identity_server_root>/SUNWam/samples/sso directory.


SSO Servlet Sample

This sample can be used to create a token for an application that resides on the same server as the Identity Server application. The files used for this sample are:

  • Readme.html

  • SampleTokenListener.java

  • SSOTokenSampleServlet.java

The instructions in Readme.html can be followed to run this code.


Remote SSO Sample

This sample can be used to create a token for an application that resides on a different server from the one on which the Identity Server application lives. The files used for this sample are:

  • remote.html

  • SSOTokenFromRemoteServlet.java

  • SSOTokenSampleServlet.java

The instructions in remote.html can be followed to run this code.


Command Line SSO Sample

This sample illustrates how to validate a user from the command line using a session ID string. The files used for this sample are:

  • ssocli.txt

  • CommandLineSSO.java

  • SSOTokenSample.java

The instructions in ssocli.txt can be followed to run this code.


Previous     Contents     Index     Next     
Copyright 2002   Sun Microsystems, Inc. All rights reserved.

Last Updated December 02, 2002