Sun Java System Access Manager 7 2005Q4 Developer's Guide

About the C Library for Single Sign-On

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.

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 AccessManager-base/SUNWam/config/. The following properties must be set:


Note –

If com.sun.am.notificationEnabled is not found in the properties file, the default is false.


com.sun.am.notificationURL=https://myhost.mydomain.com:8000/myURL

More information on properties in the AMAgent.properties file can be found in the J2EE Policy Agent 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 on page 90 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.

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).


Example 9–2 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 the user 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. The following 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. The following 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, maximum session time, and so forth.

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.


Example 9–3 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.


Example 9–4 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;
     }


                  

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, you can use the API in one of two ways: