Sun OpenSSO Enterprise 8.0 C API Reference for Application and Web Policy Agent Developers

The Single Sign-on API for C

The Single Sign-on API for C are provided in the SUNWamcom package which comes with OpenSSO Enterprise or any of its downloadable policy agents. The package includes header files, libraries and samples. The header files are:

Single Sign-on Properties

The properties required for SSO are not read from AMAgent.properties but are picked up from either the OpenSSO server (if the mode is centralized) or from the local configuration file (if the mode is local). P

Certain properties must be read and passed to am_sso_init() in order to initialize the Session Service. Thus, am_sso_init() must be called before any other single sign-on interface. The properties required for single sign-on are retrieved from OpenSSO Enterprise if using centralized agent configuration, and from the configuration file local to the agent if using local agent configuration.


Note –

See Sun OpenSSO Enterprise Policy Agent 3.0 User’s Guide for Web Agents or Sun Java System Access Manager Policy Agent 2.2 User’s Guide for more information.


Before using the API be sure the properties in the following table are set.

Table 4–1 Single Sign-on Properties Defined During Web Policy Agent Installation

Property 

Definition 

com.sun.am.naming.url

Specifies the URL for the Naming Service which, in turn, finds the URL of the Session Service. This property must be set as: 

com.sun.am.naming.url = protocol://OpenSSO Enterprise-host.domain:port/URI/namingservice

com.sun.am.notification.enable

Specifies whether the Notification Service will be used to update the cache. If enabled, a URL where notification messages from OpenSSO Enterprise are sent must be specified. This property is set as: 

com.sun.am.notification.enable = true | false


Note –

If com.sun.am.notification.enable is not found in the properties file, the default value is false.


com.sun.am.notification.url

If com.sun.am.notification.enable is set to true, the value of this property specifies a URL where notification messages from OpenSSO Enterprise are sent. This property is set as:

com.sun.am.notification.url = protocol//host.domain:port/notification_URL

com.sun.am.sso.polling.period

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=#


Note –

By default, this property is not part of the agent configuration properties but can be added when needed.


com.sun.am.sso.max_threads

Specifies the maximum number of threads the single sign-on API for C 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. This property must be set as: 

com.sun.am.sso.maxThreads=#

If not specified the default maximum number of threads is 10. 


Note –

By default, this property is not part of the agent configuration properties but can be added when needed.


For more information, see the Sun OpenSSO Enterprise Policy Agent 3.0 User’s Guide for Web Agents or Sun Java System Access Manager Policy Agent 2.2 User’s Guide.

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>

boolean_t agentInitialized = B_FALSE;
const char* prop_file = "../../config/OpenSSOAgentBootstrap.properties";
const char* config_file = "../../config/OpenSSOConfiguration.properties";

am_web_init (prop_file, config_file);
am_agent_init(&agentinitialized)

     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 OpenSSO Enterprise 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 OpenSSO Enterprise.


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 the agent configuration properties to true, and by providing the com.sun.am.notification.url property a URL which will receive HTTP notification messages from OpenSSO Enterprise. 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;
     }

Non-Web Applications

OpenSSO Enterprise provides the single sign-on API for C to be used primarily with web-based applications. It can though be extended to non-web applications with limitations. You can use the API with non-web applications in either of the following ways: