Sun Java System Access Manager 7.1 C API Reference

Single Sign-on Calls

The following sections contain information and code samples for some of the single sign-on calls.

Initialization and Cleanup

When implementing single sign-on, am_sso_init() must be called before any other am_sso_* functions to initialize the internal data structures. At the end of all single sign-on routines, am_cleanup() should be called for cleanup. Following is a code sample using these functions.


Note –

For more information on am_cleanup(), see Chapter 9, Additional Data Types and Functions.


#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;
     }

Single Sign-on Token Handles

When a user attempts to access a protected resource, the Session Service creates a new, empty session data structure (also known as an SSOToken) that will store information (such as login time, authentication scheme, authentication level, maximum time out limits and caching time limits) after the user is successfully authenticated. Additionally, the Session Service generates a session identifier (also known as an SSOTokenID) which is a randomly-generated string that identifies the user and corresponding session structure. Technically, the SSOTokenID identifies an instance of an SSOToken.

After a user has been successfully authenticated, the SSOToken is activated and the relevant session information is stored in the structure. Additionally, the state of the SSOTokenID is changed from invalid to valid. When using the single sign-on API for C, a single sign-on token handle contains this valid SSOTokenID and allows for operations based on the SSOToken.

Creating Single Sign-on Token Handles

Once activated, an SSOToken can be obtained and inserted into a single sign-on token handle by passing the SSOTokenID to am_sso_create_sso_token_handle(). This function then checks to see if the identifier is in its local cache and, if not, retrieves the session information associated with the SSOTokenID from Access Manager and caches it. A single sign-on token handle is then assigned to it.

Validating Single Sign-on Token Handles

The caller can check if the session is valid using am_sso_is_valid_token(). If not valid, am_sso_validate_token() will flush the old session information from the local cache (if any) and fetch the latest session information from Access Manager.


Note –

am_sso_refresh_token() duplicates the functionality of am_sso_validate_token(). In addition, it will reset the idle time of the session on the server.


Destroying Session Token Handles

When the caller is finished with a token handle, it must be freed to prevent memory leak by calling am_sso_destroy_sso_token_handle(). The session associated with the token handle can be invalidated or ended with am_sso_invalidate_token().


Tip –

Although this ends the session for the user, the proper way to log out is by using am_auth_logout() as described in am_auth_logout(). Not using am_auth_logout() will result in authentication resources associated with the session remaining on the server unnecessarily until the session has timed out.


Retrieving and Setting Properties

The following code sample shows how you might use the am_sso_get_property() and am_sso_set_property() functions. For additional information, see am_sso_get_property() and am_sso_set_property().

/* 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 are 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 */

Listening and Notification

A session may become invalid because it has been idle over a time limit, it has reached the maximum session time, or it has been terminated by an administrator. An application can be notified of this by implementing a listener function. Additionally, notification must be enabled for the application to receive change notifications when am_sso_init() is initialized. Notification is enabled by setting the com.sun.am.notification.enable property in AMAgent.properties to true, and by providing the com.sun.am.notification.url property a URL which will receive HTTP notification messages from Access Manager. Notification messages are in XML and should be passed as a string (const char *) to am_notify() which will parse the message and invoke the appropriate session or policy listener. Following is a code sample that illustrates this.


Note –

For more information, see Single Sign-on Properties and <am_notify.h>.


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;
     }