Sun Java System Access Manager 6 2005Q1 Developer's Guide |
Chapter 4
Single Sign-On And SessionsThe Session Service is a key component of the Sun Java System Access Manager 6 2005Q1 single sign-on (SSO) solution that enables users to authenticate once yet 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 Session Service, the SSO solution, and the SSO APIs. It contains the following sections:
OverviewA user wanting to access resources protected by Access Manager 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 access privileges or policy. If a user wants to access several resources protected by Access Manager, the Session Service provides proof of authorization so there is no need to re-authenticate; this is single sign-on. As different DNS domains generally have common users who need to gain access to their services in a single session, Access Manager supports a cross-domain single sign-on functionality.
The Session Service provides the functionality to maintain information about an authenticated user’s session across all applications participating in a single sign-on. It is responsible for:
- Generating session identifiers.
- Maintaining a master copy of the session’s state information.
- Implementing the time-dependent behavior of sessions.
- Implementing the session’s life cycle events (For example: logout, session destruction).
- Generating the session’s life cycle event notifications.
- Implementing session failover facilities.
Session Service Concepts
The following concepts are closely tied together when discussing the Session Service and SSO. To understand the differences between them, consider the following definitions and how they will be used in this chapter.
Session
A session is a data structure held in the Access Manager memory that contains session information about an authenticated user.
Session ID
A session identifier (ID) is an opaque, globally unique string that programmatically identifies a specific session instance. With the session ID, a resource is able to retrieve session information.
SSOToken
An SSOToken is a data structure, defined by the SSO API, that represents a snapshot of the session local to the particular application’s memory.
Single Sign-On Process
The next sections describe the process that occurs when a user attempts to gain access to a resource protected by Access Manager.
Contacting A Protected Resource
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 and, inspects it to see if it contains a Session ID. If none exists, the request is redirected to Access Manager where the Session Service creates a Session for the requesting user. Initially, the session is in an invalid state and does not contain user identity information. It does though contain the aforementioned randomly-generated session ID to represent the user’s session. Once the session/session ID is created, the Authentication Service sets a cookie with the session ID only and sends it to the client browser. Simultaneously, a login page is generated by the Authentication Service and returned to the user based upon their configured method of authentication (LDAP, RADIUS, etc.).
Note
For more information on the different methods of authentication, see Authentication Methods in Chapter 5, "Authentication Service," of this manual.
Providing User Credentials
The user, having received the login page (as well as the session ID) fills in the appropriate credentials based on the type of authentication. After entering 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 (using the session ID) and the session state is set to valid. The user can now be redirected to the resource they were attempting to access.
Note
In reality, the user can only be redirected to the resource if their assigned policy permits it. More information on the Policy Service can be found in Chapter 9, "Policy Management," of this manual.
Cookies and SessionsA 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 by which it has been generated. It does not imply that the user is authenticated. Cookies are domain-specific; for example, a cookie generated by DomainA cannot be used in DomainB. Cookies will only be passed to a server in the domain for which the cookie is set. Conversely, servers may only set a cookie in their own domain.
In an Access Manager deployment, the cookie contains the Session ID, an encrypted string generated by the Session Service. With the session ID, a protected resource can get access to the Session where the user’s session information is stored. This information is then used for session validation.
Note
Details on the attributes stored in the session token can also be found in Authentication Methods in Chapter 5, "Authentication Service," of this manual.
Session StructureWhen a user is successfully authenticated they are assigned a valid session. This session contains a number of attributes and properties that define the user’s identity and some time-dependent behaviors (for example, the maximum time before the session expires). The following sections detail these attributes.
Fixed Attributes
The session token contains the following fixed attributes concerning the authenticated user:
- ID—This is the Session ID, a randomly-generated session identifier.
- ClientDomain—This is the DNS domain in which the client is located.
- ClientID—This is the user DN or the application’s principal name.
- Type—This is the user or application type.
- State—This is the state of the session: valid, invalid, destroyed or inactive.
- maxIdleTime—This is the maximum time in minutes without activity before the session will expire and the user must reauthenticate.
- maxSessionTime—This is the maximum time in minutes before the session expires and the user must reauthenticate.
- maxCachingTime—This is the maximum time in minutes before the client contacts Access Manager to refresh cached session information.
- latestAccessTime—This is the last time the user has accessed the resource.
- creationTime—This is the time at which the session token was set to a valid state.
Protected And Custom Properties
The session token also contains an extensible set of properties that are divided into two subsets: protected (or core) properties and custom properties. Protected properties are set by Access Manager. Custom properties are set remotely by any application that knows the Session ID.
Protected Properties
The current protected properties are:
- Organization—This is the DN of the organization to which the user belongs.
- Principal—This is the DN of the user.
- Principals—This is a list of names to which the user has authenticated. (This property may have more then one value defined as a pipe separated list.)
- UserId—This is the user’s DN as returned by the module, or in the case of modules other than LDAP or Membership, the user name. (All Principals must map to the same user. The UserID is the user DN to which they map.)
- UserToken—This is a user name. (All Principals must map to the same user. The UserToken is the user name to which they map.)
- Host—This is the host name or IP address for the client.
- authLevel—This is the highest level to which the user has authenticated.
- AuthType—This is a pipe separated list of authentication modules to which the user has authenticated (For example module1|module2|module3).
- Role—Applicable for role-based authentication only, this is the role to which the user belongs.
- Service—Applicable for service-based authentication only, this is the service to which the user belongs.
- loginURL—This is the client’s login URL.
- Hostname—This is the host name of the client.
- cookieSupport—This attribute contains a value of true if the client browser supports cookies.
- authInstant—This is a string that specifies the time at which the authentication took place.
- SessionTimedOut—This attribute contains a value of true if the session has timed out.
Custom Properties
The custom properties currently used are:
Cross-Domain Support For SSOAccess Manager supports cross-domain SSO. A user authenticated to Access Manager in one DNS domain can access resources in another, integrated DNS domain. This cross-domain functionality is achieved using the Cross-Domain Controller servlet in Access Manager and Policy Agents installed in web containers. The Controller communicates with the policy agent that resides on servers where the protected resources are kept.
Note
The Authentication Service handles SSO requests while the Cross-Domain Controller servlet handles cross-domain SSO requests.
Policy Agents
A policy agent polices the web container on which a protected resource lives by enforcing a user’s assigned policies. They are an integral part of the cross-domain SSO functionality. Two types of policy agents are supported by Access Manager: the web agent and the J2EE/Java agent. The web agent enforces URL-based policy while the J2EE/Java agent enforces J2EE-based security and policy. Both types are available for installation separately from Access Manager and can be downloaded. Additional information can be found in the Sun Java System Access Manager Web Policy Agents Guide and J2EE Policy Agents Guide. General information on the Policy Service can be found in Chapter 9, "Policy Management," of this manual.
Cross-Domain Controller
The Cross-Domain Controller is a servlet responsible for redirecting user requests. The default URL for it is http(s)://identity_server_host.domain_name:port/amserver/cdcservlet. There are three scenarios where the Controller comes into play:
- If a request for a protected resource contains no session ID, the agent redirects the user to the Controller which, in turn, redirects the user to the appropriate Authentication Service module. Assuming the user is authenticated, this scenario would then follow the path outlined in either Step 2 or Step 3.
Note
The authentication process itself is discussed in Chapter 5, "Authentication Service," of this manual.
- If a request for a protected resource already contains a session ID set in a cookie for the same DNS domain in which the resource is deployed, the agent retrieves it and sends an XML/HTTP request to the Naming, Session and Policy Services to retrieve the identity, session and policy information for the requesting user. The user is allowed or denied access to the resource based on this information.
- If a request for a protected resource does not contain a session ID set in a cookie for the same DNS domain in which the resource is deployed (For example: it carries a session ID set in a different DNS domain from the one in which the Access Manager is deployed), the agent redirects the request to the Controller with a Liberty AuthnRequest in the query string. The Controller then finds the session ID, extracts it from the cookie, places it in a Liberty AuthnResponse and sends it back to the agent. The agent finds the session ID, extracts it from the AuthnResponse, sets it in a cookie for the new domain, and sends an XML/HTTP request to the Naming, Session and Policy Services to retrieve the identity, session and policy information for the requesting user. The user is allowed or denied access to the resource based on this information.
A Cross-Domain SSO Scenario
In one scenario, the Access Manager instance for DomainA is its authentication provider. A user authenticates to Access Manager in DomainA and, after authentication, the session is set for DomainA. ServerB, on the other hand, is protected by a policy agent talking to an Access Manager in DomainB.
Note
This is just one scenario; it is not obligatory to have an installed instance of Access Manager in both domains to use the cross-domain feature.
The Access Manager instance in DomainB recognizes the DomainA instance as an authentication provider. If UserA, after authenticating to DomainA, requests a resource on ServerB, the policy agent for DomainB checks for a session ID and will find that there is none (authorizing access to DomainB, that is). The agent then redirects the request to the Cross-Domain Controller running with the Access Manager instance in DomainB. The servlet, following the path outlined in Step 3, finds the session ID from DomainA, extracts it from the cookie, places it in a Liberty AuthnResponse and sends it back to the agent. The agent finds the session ID and sets a cookie for DomainB using the session ID. The agent then sends an XML/HTTP request to the Naming, Session and Policy Services deployed in DomainB. Since the instance of Access Manager in DomianB recognizes the instance of Access Manager in DomainA as an authentication provider, DomainB retrieves identity, session and policy information for the requesting user from DomainA. The user is then allowed or denied access to the resource based on this information.
Enabling Cross-Domain Single Sign-On
As described, in order to exchange session information across two different domains, Policy Agents and the Cross-Domain Controller communicate with each other. By default, Access Manager is installed with the servlet. Policy agents, on the other hand, are installed separately. When installing the agent, the option to configure it for CDSSO must be selected. The cookie domain for the agent must be configured after installation. This is done by editing the AMAgent.properties file. The com.sun.am.policy.agents.cookieDomainList property must be set with the domain in which the agent is installed. If the field is left blank, the cookie domain will be set to the FQDN of the web server on which the agent is installed. Additional information on enabling cross-domain single sign-on can be found in the Web Policy Agents Guide and the J2EE Policy Agents Guide.
SSO APIThe Session Service provides Java and C API to allow external applications to participate in the SSO functionality. All Access Manager services (except for Authentication) require a valid session (programmatically referred to as SSOToken) to process a HTTP request. External applications wishing to use the SSO functionality must also use the SSOToken to authenticate the user’s identity. With the SSO API, an external application can retrieve it and, in turn, the user’s identity, session and policy information. The application then uses this information to determine whether to provide user access to a protected resource.
After successfully authenticating to Access Manager, a user carries their Session ID with them using browser cookies or URL query parameters. Now, each time a user requests access to a protected application, the application needs to verify their identity. Assume a user authenticates to http://www.orgA.com/Store successfully and later tries to access http://www.orgA.com/UpdateInfo, a service that is SSO-enabled. Rather than having the second application authenticate the user again, it can use the API and the user’s session to determine if the user is already authenticated. If the methods determine that the user has already been authenticated (and the session is still valid), access to this page can be achieved. Otherwise, the user would be prompted to authenticate again. The SSO API can also be used to create or destroy a SSOToken, or to listen for SSOToken events. (An event might be a SSOToken timing out because the user has reached the their maximum time limit.) Following are both the Java API Overview and C API Overview.
Java API Overview
In Java, the main classes of the SSO API are SSOTokenManager, SSOToken and SSOTokenListener. The SSOTokenManager class is used to get, destroy, validate, and refresh a session token which is represented by the SSOToken class. The SSOTokenListener class allows the application to be notified when a SSOToken has become invalid, for example when a session has timed out.
SSOTokenManager Class
The SSOTokenManager class contains the methods needed to get, validate, destroy and refresh session tokens. SSOTokenManager is implemented using the singleton design pattern. In order to obtain an instance of SSOTokenManager, the SSOTokenManager.getInstance() method must be called. An instance of SSOTokenManager can then be used to instantiate an SSOToken object using one of the overloaded forms of the createSSOToken() method.
The destroyToken() method would be called to invalidate and delete a token when its session has ended. The isValidToken() and validateToken() methods can be called to verify whether a token is valid, or authenticated. 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. The refreshSession() method resets the idle time of the session. Code Example 4-1 illustrates one way in which the SSOTokenManager class can be used.
SSOTokenID Interface
The SSOTokenID interface is used to identify the SSOToken object.
Caution
The string value of SSOTokenID is globally unique and must only be known to the client browser, Access Manager and the application code. Exposing it to unauthorized users or applications can lead to a security breach by allowing a malicious attacker to impersonate a user.
SSOToken Interface
The SSOToken interface represents a single sign-on token returned from the SSOTokenManager.createSSOToken() method, and contains information such as the authenticated principal name, authentication method, and session information (session idle time, maximum session time, etc.). The SSOToken interface has methods to get predefined session information, such as getAuthType() for the authentication type, as well as a method getProperty() to get any information about the session, predefined or otherwise (for example, information set by the application). The method setProperty() can be used by the application to set application-specific information in the session. The addSSOTokenListener() method can be used to set a listener to be invoked when the session state has become invalid.
Caution
The methods getTimeLeft() and getIdleTime() return values in seconds while the methods getMaxSessionTime() and getMaxIdleTime() return values in minutes.
Code Example 4-2 shows an example of SSOToken code.
Code Example 4-2 Sample Use Of SSOToken
/* get http request output stream for output */
ServletOutputStream out = response.getOutputStream();
/* get the sso token from http request */
SSOTokenManager ssoManager = SSOTokenManager.getInstance();
SSOToken ssoToken = ssoManager.createSSOToken(request);
/* get the sso token ID from the sso token */
SSOTokenID ssoTokenID = ssoToken.getTokenID();
out.println("The SSO Token ID is "+ssoTokenID.toString());
/* use validate method to check if the token is valid */
try {
ssoManager.validateToken(ssoToken);
out.println("The SSO Token validated.");
} catch (SSOException e) {
out.println("The SSO Token failed to validate.");
}
/* use isValid method to check if the token is valid */
if (!ssoManager.isValidToken(token)) {
out.println("The SSO Token is not valid.");
} else {
/* get some values from the SSO Token */
java.security.Principal principal = ssoToken.getPrincipal();
out.println("Principal name is "+principal.getName());
String authType = ssoToken.getAuthType();
out.println("Authentication type is "+authType);
int authLevel = ssoToken.getAuthLevel();
out.println("Authentication level is "+authLevel);
long idleTime = ssoToken.getIdleTime();
out.println("Idle time is "+idleTime);
long maxIdleTime = ssoToken.getMaxIdleTime();
out.println("Max idle time is "+maxIdleTime);
long maxTime = token.getMaxSessionTime();
out.println("Max session time is "+maxTime);
String host = ssoToken.getHostName();
out.println("Host name is "+host);
/* host name is a predefined information of the session,
/* and can also be obtained the following way */
String hostProperty = ssoToken.getProperty("HOST");
out.println("Host property is "+hostProperty);
/* set application specific information in session */
String appPropertyName = "appProperty";
String appPropertyValue = "appValue";
ssoToken.setProperty(appPropertyName, appPropertyValue);
/* now get the app specific information back */
String appValue = ssoToken.getProperty(appPropertyName);
if (appValue.equals(appPropertyValue)) {
out.println("Property "+appPropertyName+", value "+appPropertyValue+" verified to be set.");
} else {
out.println("ALERT: Setting property "+appPropertyName+" failed!");
}
}
A code sample using the getTokenID method is illustrated in Code Example 4-3. With this code, a cookie is created from an SSOToken in order to make SSO work for protected resources not residing on the same server as Access Manager.
Code Example 4-3 Sample Code To Create A Cookie From Session Token
// Get SSOToken string
String strToken = null;
strToken = getSSOToken().getTokenID().toString();
// Set it to response as cookies
String s = strToken;
String ssotokencookiename = "iPlanetDirectoryPro";
String ssotokencookiedomain = ".mydomain.com.tw";
String ssotokencookiepath = "/";
String gt = "/welcomepage.jsp";
Cookie cookie = new Cookie(ssotokencookiename,s);
cookie.setDomain(ssotokencookiedomain);
cookie.setPath(ssotokencookiepath);
response.addCookie(cookie);
response.sendRedirect(gt);
SSOTokenEvent
The SSOTokenEvent interface represents a token event. An event is, for example, when a session has been idle for over a maximum idle time limit, or when a session has reached its maximum allowed time.
SSOTokenListener
The SSOTokenListener interface represents a token notification object. An implementation of the SSOTokenListener interface must be written, then registered with the SSOTokenManager to be invoked when a token event occurs.
The SSOTokenListener interface provides a mechanism to notify applications when a session token has become invalid due to, for instance, the session reaching maximum idle time or the maximum session time. Applications wishing to be notified must write an implementation of the SSOTokenListener interface, then register the implementation through the SSOToken.addSSOTokenListener method. When the SSOToken state has become invalid, the SSOTokenListener implementation’s ssoTokenChanged method will be invoked with a SSOTokenEvent object containing the event type, time, and SSOToken object with the new SSOToken state and other properties of the SSOToken.
Code Example 4-4 Sample Code For SSOToken Event And SSOToken Listener
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: " + id.toString() + "is not valid anymore");
/* redirect user to login */
......
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
public SampleTestRoutine {
...
SSOTokenManager ssoManager = SSOTokenManager.getInstance();
SSOToken ssoToken = SSOManager.createSSOToken(request);
SSOTokenListener sampleListener = new SampleTokenListener();
ssoToken.addSSOTokenListener(sampleListener);
...
}
Sample SSO Java Files
Access Manager provides three groups of sample Java files. With these samples, a developer can create a session token in several ways:
- With the SSO Servlet Sample, a session token can be created for an application that runs on the Access Manager server.
- With the Remote SSO Sample, a session token can be created for an application that runs on a server other than the Access Manager server.
- With the Command Line SSO Sample, a session token can be created by a session ID string and passed through the command line.
The sample files are located in the IdentityServer_base/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 Access Manager application. The files used for this sample are:
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 Access Manager application lives. The files used for this sample are:
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:
The instructions in ssocli.txt can be followed to run this code.
C API Overview
The C API are provided in the SUNWamcom package which comes with Access Manager or any of its downloadable agents. The package includes header files, libraries and samples.
Caution
Previous releases of Access Manager contained C libraries in IdentityServer_base/lib/capi. The capi directory is being deprectated, and is curently available for backward compatability. It will be removed in the next release, and therefore it is highly recommended that existing application paths to this directory are changed and new applications do not access it. Paths include RPATH, LD_LIBRARY_PATH, PATH, compiler options, etc.)
C SSO Include Files
Include files for the C SSO API are am_sso.h and am_notify.h. am_sso.h must be included for any SSO routines. am_notify.h must be included for parsing notification messages from the server and calling SSO listeners.
C SSO Properties
Certain properties must be read in and passed to am_sso_init(), the routine which initializes C API. Because of this, am_sso_init() must be called before any other SSO interface. The default properties file used is AMAgent.properties, located in IdentityServer_base/SUNWam/config/. The following properties must be set:
- The com.sun.am.namingURL property specifies the URL for the Naming Service. This service is used to find the URL of the Session Service for the given SSOToken ID. This property must be set as:
com.sun.am.namingURL = https://myhost.mydomain.com:58080/amserver/namingservice
- The com.sun.am.notificationEnabled and com.sun.am.notificationURL properties specify whether notification is enabled, and if enabled, a URL where the application can listen for messages from Access Manager. These properties must be set as:
com.sun.am.notificationEnabled=true
com.sun.am.notificationURL=https://myhost.mydomain.com:8000/myURL
- The com.sun.am.sso.cacheEntryLifeTime property specifies how long, in minutes, a session token can live in cache before it should be removed. This property must be set as:
com.sun.am.sso.cacheEntryLifeTime=5
If not set, the default is 3 minutes.
- The com.sun.am.sso.checkCacheInterval property specifies how often, in minutes, the cache should be checked for entries that have reached the cache entry life time. This property must be set as:
com.sun.am.sso.checkCacheInterval=5
- The com.sun.am.sso.maxThreads specify the maximum number threads the SSO API should invoke for handling notifications. The API maintains a thread pool and invokes a thread for each notification. If the maximum number of threads has been reached, the notification will wait until a thread is available. If not specified the default maximum number of threads is 10. This property must be set as:
com.sun.am.sso.maxThreads = 5
- The com.sun.am.cookieEnabled property specifies whether the session ID found in the cookie is URL encoded. If true, it will be URL decoded before sent to Access Manager for any session operation. This property must be set as:
com.sun.am.cookieEncoded = true|false
More information on properties in the AMAgent.properties file can be found in the Web Policy Agents Guide and the J2EE Policy Agents Guide.
C SSO interfaces
The C SSO interfaces consist of the following routines. A detailed description of the input and output parameters for each interface is in the header files.
Initialization and Cleanup
To use the C SSO API, the am_sso_init() routine needs to be called before any other routines. This interface initializes the internal SSO module. At the end of all SSO routines, am_cleanup() should be called to cleanup the internal SSO module. Code Example 4-5 is a code sample for these interfaces.
am_sso_init() initializes internal data structures for talking to the Session Service. It takes a properties input parameter that contains name /value pairs from a configuration or properties file, and returns a status on the success or failure of the initialization. The properties used by the C SSO API are covered in C SSO Properties.
am_cleanup() cleans up all internal data structures created by am_sso_init, am_auth_init, or am_policy_init. am_cleanup() needs to be called only once when using any of the Access Manager C API interfaces (authentication, SSO or policy).
Code Example 4-5 Code Sample For am_sso_init and am_cleanup
#include <am_sso.h>
int main() {
am_properties_t *properties;
am_status_t status;
/* create a properties handle */
status = am_properties_create(&properties);
if (status != AM_SUCCESS) {
printf("am_properties_create failed.\n");
exit(1);
}
/* load properties from a properties file */
status = am_properties_load(properties, "./myPropertiesFile");
if (status != AM_SUCCESS) {
printf("am_properties_load failed.\n");
exit(1);
}
/* initialize SSO module */
status = am_sso_init(properties);
if (status != AM_SUCCESS) {
printf("am_sso_init failed.\n");
return 1;
}
/* login through auth module, and do auth functions.
* ...
*/
/* do sso functions
* ...
*/
/* done - cleanup. */
status = am_cleanup();
if (status != AM_SUCCESS) {
printf("am_cleanup failed!\n");
return 1;
}
/* free memory for properties */
status = am_properties_destroy(properties);
if (status != AM_SUCCESS) {
printf("Failed to free properties.\n");
return 1;
}
/* exit program successfully. */
return 0;
}
Get, Validate, Refresh And Destroy SSO Token
A user needs to be authenticated to get the token ID for their login session. A token can be obtained with the token ID and the am_sso_create_sso_token_handle interface. This interface checks to see if the token is in its local cache and, if not, goes to the server to get the session information associated with the token ID and caches it. If the reset flag is set to true, this interface will refresh the idle time of the token on the server. Here is the interface of am_sso_create_sso_token_handle:
Once a token handle is obtained, the caller can check if the session is valid with the am_sso_is_valid_token interface. The am_sso_token_validate interface will flush the token handle in the local cache (if any) and go to the server to fetch the latest session information. The am_sso_refresh_token will also flush the token handle in the local cache (if any) and go to the server to fetch the session information. In addition, it will reset the idle time of the session on the server. Here are the token-related interfaces:
When caller is done with a token handle, it must be freed by calling am_sso_destroy_sso_token_handle to prevent memory leak. Here is that interface:
The session associated with the token can be invalidated or ended with am_sso_invalidate_token. Although this ends the session for the user, the proper way to log out is through am_auth_logout. Using the former interface to end a session will result in authentication resources associated with the session to remain on the server unnecessarily until the session has timed out. Here is the interface for am_sso_invalidate_token:
Get Session Information Interfaces
The following interfaces make it convenient to get server-defined information (or properties) about the session associated with a token. This can include the session idle time, max session time, etc.
- const char * am_sso_get_sso_token_id(const am_sso_token_handle_t sso_token_handle);
- const char * am_sso_get_auth_type(const am_sso_token_handle_t sso_token_handle);
- unsigned long am_sso_get_auth_level(const am_sso_token_handle_t sso_token_handle);
- time_t am_sso_get_idle_time(const am_sso_token_handle_t sso_token_handle);
- time_t am_sso_get_max_idle_time(const am_sso_token_handle_t sso_token_handle);
- time_t am_sso_get_time_left(const am_sso_token_handle_t sso_token_handle);
- time_t am_sso_get_max_session_time(const am_sso_token_handle_t sso_token_handle);
- const char * am_sso_get_principal(const am_sso_token_handle_t sso_token_handle);
- am_string_set_t am_sso_get_principal_set(const am_sso_token_handle_t sso_token_handle);
- const char * am_sso_get_host(const am_sso_token_handle_t sso_token_handle);
Get And Set Property Interfaces
The get and set property interfaces allows an application to get any property (server or application defined) and to set any property in a session. Note that am_sso_set_property will update the sso_token_handle with the latest session properties from Access Manager, including the new property that was set. In addition, if the property that is given in prop_name is a protected property, am_sso_set_property will return success, however the value given will not be set as it is a property protected by Access Manager. These interfaces are:
Code Example 4-6 is a sample of the SSO get, set, create, refresh, validate, invalidate, and destroy interfaces.
Code Example 4-6 Sample Code For Get, Set, Create, Refresh, Validate, Invalidate, and Destroy Interfaces
/* initialize sso as in previous sample */
am_status_t status = NULL;
am_sso_token_handle_t sso_handle = NULL;
char *session_status = NULL;
am_string_set_t principal_set = NULL;
/* create sso token handle */
status = am_sso_create_sso_token_handle(&sso_handle, sso_token_id, false);
if (status != AM_SUCCESS) {
printf("Failed getting sso token handle for sso token id %s.\n", sso_token_id);
return 1;
}
/* check if session is valid */
session_status = am_sso_is_valid_token(sso_handle) ? "Valid" : "Invalid";
printf("Session state is %s\n", session_status);
/* check if session is valid using validate. This also updates the handle with info from the server */
status = am_sso_validate_token(sso_handle);
if (status == AM_SUCCESS) {
printf("Session state is valid.\n");
} else if (status == AM_INVALID_SESSION) {
printf("Session status is invalid.\n");
} else {
printf("Error validating sso token.\n");
return 1;
}
/* get info on the session */
printf("SSO Token ID is %s.\n", am_sso_get_sso_token_id(sso_handle));
printf("Auth type is %s.\n", am_sso_get_auth_type(sso_handle));
printf("Auth level is %d.\n", am_sso_get_auth_level(sso_handle));
printf("Idle time is %d.\n", am_sso_get_idle_time(sso_handle));
printf("Max Idle time is %d.\n", am_sso_get_max_idle_time(sso_handle));
printf("Time left is %d.\n", am_sso_get_time_left(sso_handle));
printf("Max session time is %d.\n", am_sso_get_max_session_time(sso_handle));
printf("Principal is %s.\n", am_sso_get_principal(sso_handle));
printf("Host is %s.\n", am_sso_get_host(sso_handle));
principal_set = am_sso_get_principal_set(sso_handle);
if (principal_set == NULL) {
printf("ERROR: Principal set is NULL!\n");
}else {
printf("Principal set size %d.\n", principal_set->size);
for (i = 0; i < principal_set->size; i++) {
printf("Principal[%d] = %s.\n", i, principal_set->strings[i]);
}
am_string_set_destroy(principal_set);
}
/* get "HOST" property on the session. Same as am_sso_get_host(). */
printf("Host is %s.\n", am_sso_get_property(sso_handle, "HOST"));
/* set a application defined property and get it back */
status = am_sso_set_property(sso_handle, "AppPropName", "AppPropValue");
if (status != AM_SUCCESS) {
printf("Error setting property.\n");
return 1;
}
printf("AppPropName value is %s.\n", am_sso_get_property(sso_handle, "AppPropName");
/* refresh token, idle time should be 0 after refresh */
status = am_sso_refresh_token(sso_handle);
if (status != AM_SUCCESS) {
printf("Error refreshing token !\n");
return 1;
}
printf("After refresh, idle time is %d.\n", am_sso_get_idle_time(sso_handle));
/* end this session abruptly. am_auth_logout() is the right way to end session */
status = am_sso_invalidate_token(sso_handle);
if (status != AM_SUCCESS) {
printf("Error invalidating token.\n");
return 1;
}
/* we're done with sso token handle. free memory for sso handle. */
status = am_sso_destroy_sso_token_handle(sso_handle);
if (status != AM_SUCCESS) {
printf("Failed to free sso token handle.\n");
return 1;
}
/* call am_cleanup, and other cleanup routines as in previous sample */
Listener And Notify Interfaces
Applications can be notified when a session has become invalid, possibly because it has been idle over a time limit, or it has reached the maximum session time. This is done by implementing a listener function of type am_sso_token_listener_func_t, which takes a SSO token handle, event type, event time, application-defined arguments handle, and a boolean argument to indicate whether the listener function should be called in the calling thread or dispatched to a thread from the internal thread pool managed by the C SDK. This listener function must be registered to be invoked when the session has ended and notification must be enabled for an application to receive notifications. Notification is enabled by setting the property com.sun.am.notificationEnabled to true, and by providing a URL where the application is receiving HTTP messages from Access Manager. The URL where the application is receiving messages from the Access Manager is expected to take any message from the server (as an XML string) and pass it to am_notify(). am_notify() will parse the message and invoke session listeners or policy listeners depending on whether the message is a session or policy notification. Code Example 4-7 is a sample implementation of SSOToken listener and how to register it.
Code Example 4-7 Sample Implementation Of SSOToken Listener
void sample_listener_func(
am_sso_token_handle_t sso_token_handle,
const am_sso_token_event_type_t event_type,
const time_t event_time,
void *opaque)
{
if (sso_token_handle != NULL) {
const char *sso_token_id = am_sso_get_sso_token_id(sso_token_handle);
boolean_t is_valid = am_sso_is_valid_token(sso_token_handle);
printf("sso token id is %s.\n",
sso_token_id==NULL?"NULL":sso_token_id);
printf("session state is %s.\n",
is_valid == B_TRUE ? "valid":"invalid");
printf("event type %d.\n", event_type);
printf("event time %d.\n", event_time);
}
else {
printf("Error: sso token handle is null!");
}
if (opaque)
*(int *)opaque = 1;
return;
}
int main(int argc, char *argv[]) {
am_status_t status;
char *sso_token_id = argv[1];
int listener_func_done = 0;
/* initialize sso as in previous samples */
/* get sso token handle */
status = am_sso_create_sso_token_handle(&sso_handle, sso_token_id, false);
/* register listener function. notification must be enabled, if not, status AM_NOTIF_NOT_ENABLED will be returned. */
status = am_sso_add_sso_token_listener(sso_handle, sample_listener_func, &listener_func_done, B_TRUE);
if (status != AM_SUCCESS) {
printf("Failed to register sample listener function.\n");
return 1;
}
C SSO Sample
A sample for the C SSO API is provided in the SUNWamcom package. The README file in the samples directory contains information on each sample including compile instructions and how to run the samples for testing. The sample for C SSO is am_sso_test.c. The usage is am_sso_test -u [user] -p [password] [-f properties file] [-l logfile]. Access Manager must be available with LDAP authentication to test the sample. See the README file and the sample itself for more information.
Java versus C API
The following table provides a side by side comparison of the Java and C SSO API.
Table 4-1 Comparison Between Java And C SSO API
Java Interface
C Interface
SSOTokenManager
SSOTokenManager.getInstance()
am_status_t
am_sso_init(am_properties_t properties)
SSOToken
SSOTokenManager.createSSOToken(String tokenId)
am_status_t
am_sso_create_sso_token_handle( am_sso_token_handle_t *sso_token_handle_ptr, const char *sso_token_id, am_bool_t reset_idle_timer)
boolean
SSOTokenManager.isValidToken(SSOToken token)
boolean_t
am_sso_is_valid_token(const am_sso_token_handle_t sso_token_handle)
void
SSOTokenManager.validateToken(SSOToken token)
am_status_t
am_sso_validate_token(const am_sso_token_handle_t sso_token_handle)
void
SSOTokenManager.destroyToken(SSOToken token)
am_status_t
am_sso_invalidate_token(const am_sso_token_handle_t sso_token_handle)
void
SSOTokenManager.refreshSession(SSOToken token)
am_status_t
am_sso_refresh_session(am_sso_token_handle_t sso_token_handle)
Principal
SSOToken.getPrincipal()
char *
am_sso_get_principal(const am_sso_token_handle_t sso_token_handle)
int
SSOToken.getAuthLevel()
unsigned long
am_sso_get_auth_level(const am_sso_token_handle_t sso_token_handle)
String
SSOToken.getAuthType()
char *
am_sso_get_auth_type(const am_sso_token_handle_t sso_token_handle)
String
SSOToken.getHostName()
char *
am_sso_get_host(const am_sso_token_handle_t sso_token_handle)
long
SSOToken.getIdleTime()
time_t
am_sso_get_max_idle_time(const am_sso_token_handle_t sso_token_handle)
long
SSOToken.getMaxIdleTime()
time_t
am_sso_get_max_idle_time(const am_sso_token_handle_t sso_token_handle)
SSOTokenID
SSOToken.getTokenID()
char *
am_sso_get_sso_token_id(const am_sso_token_handle_t sso_token_handle)
String
SSOToken. getProperty(java.lang.String name)
char *
am_sso_get_property(const am_sso_token_handle_t sso_token_handle, const char *property_name)
void
SSOToken.setProperty( String name, String value)
am_status_t
am_sso_set_property(am_sso_token_handle_t sso_token_handle, const char *name, const char *value)
void
SSOToken.addSSOTokenListener( SSOTokenListener listener)
am_status_t
am_sso_add_sso_token_listener(am_sso_token_handle_t sso_token_handle, const am_sso_token_listener_func_t listener, void *args, boolean_t dispatch_in_sep_thread)
String
SSOToken.getProperty("principals");
am_status_t
am_sso_get_principal_set(am_sso_token_handle_t sso_handle)
N/A
am_status_t
am_sso_destroy_sso_token_handle(am_sso_token_handle_t sso_handle)
N/A
void
am_cleanup()
Non-Web-Based Applications
Access Manager provides the SSO API 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.
- The application has to obtain the Access Manager cookie value and pass it into the SSO client methods to get to the session token. The method used for this process is application-specific.
- Command line applications, such as amadmin, can be used. In this case, session tokens can be created to access the Directory Server directly. There is no session created, making the Access Manager access valid only within that process or VM.
SSO SamplesAccess Manager provides the files necessary to compile and run a sample SSO application. There are three ways in which this can be done:
More specific information on these samples can be found in Sample SSO Java Files.