Distributing Sun Java System Identity Server Applications Using Java Web Start

   
   
Articles Index



Deploying rich client-side solutions in a corporate wide network has always been a daunting task.

Consider the following questions:

  • Have you used Sun Java System Identity Server SDK to integrate management functions into external applications or services?
  • Have you wondered about the efficient mechanism to deploy these rich client-side solutions on end user machines in a diversified corporate network running various platforms and browsers ?


If you have answered yes to the above questions, you should know that the Java Web Start Technology can help address these issues.

In this article you will see the ease with which we can deploy existing client-side applications developed using Sun Java System Identity Server SDK through Java Web Start. You will take a look at the minimal changes needed to build a JNLP-packaged application and learn how to build and deploy your own.

Sun's Java Web Start and the underlying Java Network Launch Protocol(JNLP) are a standard part of the Java 2 platform (J2SE 1.4 and later).

Java Web Start is a helper application which enables you to launch applications simply by clicking on a web page link, and it addresses the common pitfalls in deploying client-side solutions on several platforms within a corporate-wide network running various browser implementations and JRE versions.

Introduction

Java Web Start is an application launcher for Java 2 technology-based applications that are written to be web-deployed, and a helper application which enables you to launch applications simply by clicking on a web page link or by passing the link which is pointing to a JNLP file. If the application is not present on your computer, Java Web Start automatically downloads all necessary files, and then caches the files on your computer so the application is always ready to be relaunched anytime you want -- either from an icon on your desktop or from the browser link. And no matter which method you use to launch the application, the most current version of the application is always presented to you. Java Web Start uses the Java Network Launching Protocol and API (JNLP) technology.

Java applications can access the Sun Java System Identity Server directly, requesting user configuration information using the Sun Java System Identity Server APIs. For example, a mail service might store its users' mailbox size information in Sun Java System Identity Server and the Sun Java System Identity Server SDK can be used to retrieve this information. To process this request, the system running the application must have the Sun Java System Identity Server SDK installed. There must also be at least one instance of the Sun Java System Web Server running the Sun Java System Identity Server.

When a user requests access to a secure application or page using Java Web Start, they must first be authenticated. The request is directed to the Authentication Service which determines the type of authentication process to initiate based on the method associated with the requestor's profile. For instance, if the user's profile is associated with LDAP authentication, the Authentication Service would send an HTML form to their web browser asking for an LDAP user name and password. Having obtained the user's credentials, the Authentication Service calls the respective provider to perform the authentication. (The provider in the LDAP example would be the Directory Server.) Once verified, the service calls the SSO API to generate a Single Sign-On (SSO) token which holds the user's identity and then generates a token ID, a random string associated with the SSO token. This complete token is sent back to the requesting application in the form of a cookie. The authentication component then directs the user to the requested secure application or page.

Java applications use the authentication API to access, and authenticate to, the Authentication Service. In other words, these applications use the Authentication Java API to initiate the authentication process and communicate with the required authentication module. These Authentication Java API are organized in a package called com.sun.identity.authentication and can be executed locally or remotely to communicate locally with the Authentication Service. Communication between the API and the framework occurs by sending XML messages over HTTP(s).

The AuthContext class is defined for each request desiring to authenticate to the Sun Java System Identity Server. Since Sun Java System Identity Server can handle multiple organizations, the AuthContext class must be initialized, at least, with the name of the organization to which the requestor is authenticating. Typical code would instantiate this class to begin the login process. The caller would then use the getRequirements method to ask for the requestor's credentials. The credentials are then submitted to the class using submitRequirements. If more information is required, the above process continues until all the required information has been supplied. The getStatus method is then called to check if the user has been successfully authenticated. If successful, the caller can then get the Subject and SSOToken for the user; if not, the caller obtains a LoginException.

We will use the sample program that comes with Sun Java System Identity Server 6.0SP1 installation. This sample program demonstrates how to integrate the Remote Client API for authenticating users with the Sun Java System Identity Server. It uses LDAP authentication although it can be modified to use other existing or customized authentication modules. The instruction file is the readme.html file found in the <identity_server_root>/SUNWam/samples/authentication/LDAP directory.

Here is the output from running the sample program using command line:

/opt/SUNWam/java/bin/java 
-Djava.util.logging.manager=com.sun.identity.log.LogManager
-Djava.util.logging.config.class=com.sun.identity.log.s1is.LogConfigReader
-Xbootclasspath:/opt/SUNWam/lib/jdk_logging.jar:/opt/SUNWam/java/lib/tools.jar:
/opt/SUNWam/java/jre/lib/rt.jar:/opt/SUNWam/java/jre/lib/sunrsasign.jar:
/opt/SUNWam/java/jre/lib/i18n.jar -classpath .:/opt/SUNWam/lib:
/opt/SUNWam/locale:/opt/SUNWam/lib/jaas.jar:/opt/SUNWam/lib/am_services.jar:
/opt/SUNWam/lib/am_sdk.jar:/opt/SUNWam/lib/jss311.jar:
/opt/SUNWam/lib/servlet.jar:/opt/SUNWam/lib/crimson.jar:
/opt/SUNWam/lib/am_logging.jar LDAPLogin "dc=xyz,dc=sun,dc=com"
orgname is: dc=xyz,dc=sun,dc=com
LDAPLogin: Obtained login context
begin addLoginCallbackMessage()
Got NameCallback
User Name: amadmin
Got PasswordCallback
Password: password
Login success!!

 

Note: The Sun Java System 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



In the next section, we will see how to make this standalone Java application distributable using Java Web Start.

Deploying LDAPLogin Application

Java Web Start leverages existing Internet technology, such as the HTTP protocol and web servers, so existing infrastructure for deploying HTML-based contents can be reused to deploy Java Technology-based applications using Java Web Start.

In order to deploy your application to client machines, you must make sure that all files containing your application are accessible through a web server. This typically amounts to copying one or more JAR files, along with a JNLP file, into the web server's directories. Here are the basic steps:

1. Create the application jar file

Developing applications for deployment with Java Web Start is generally the same as developing stand-alone applications for the Java 2 platform. For instance, the entry point for the application is the standard public static void main(String[] argv).

In this example, we make the following source changes to our code sample

Read the values for LoginName, LoginPassword and orgName from the properties file

        Properties p = new Properties(System.getProperties());

        try {
        FileInputStream propFile = new FileInputStream("login_props.txt");
        p.load(propFile);
        } catch ( java.io.FileNotFoundException fnf ) {
                fnf.printStackTrace();
                System.out.println("File Not Found!!");
                return;
        } catch ( java.io.IOException ioe ) {
                ioe.printStackTrace();
                System.out.println("Cannot load properties file!!");
                return;
        }


        // set the system properties
        System.setProperties(p);
        

        loginName = System.getProperty("LoginName");
        loginPass = System.getProperty("LoginPassword");
        orgName = System.getProperty("orgName");
        
        // copy the password from String to array
        
        int passlen = loginPass.length();
        passArr = new char[passlen + 1];

        int counter = 0;
        for (int index=0; index < passlen; index++) {

                char character = loginPass.charAt(index);
                passArr[ counter++ ] = character;
        }

        passArr[ counter ] = '\n';


        // pass the loginName and passArr to NameCallback, PasswordCallback
        
        // set the username in NameCallback
                    NameCallback nc = (NameCallback) callbacks[i];
                    System.out.println(nc.getPrompt() + ": " + loginName);
                    System.err.flush();
                    nc.setName(loginName);

        // set the user password in PasswordCallback
                    PasswordCallback pc = (PasswordCallback) callbacks[i];
                    System.err.println(pc.getPrompt() + ": " + loginPass);
                    System.err.flush();
                    pc.setPassword(passArr);

You will find the complete source code here.

In order to support web deployment-automatic download and launching of an application-and to ensure that an application can run in a secure sandbox, there are some additional consideration:

The application itself must be delivered as a set of JAR files.

Since our application needs unrestricted access to the system, it needs to be delivered in a set of signed JAR files.

We will download and install J2SE 1.4.2_02. At the time of writing this article, the update release available is J2SE 1.4.2_02.

java -version
java version "1.4.2_02"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_02-b03)
Java HotSpot(TM) Client VM (build 1.4.2_02-b03, mixed mode)

Let us compile the Java application, LDAPLogin.java

javac -classpath .:/opt/SUNWam/lib:/opt/SUNWam/locale:/opt/SUNWam/lib/jaas.jar:
/opt/SUNWam/lib/am_services.jar:/opt/SUNWam/lib/am_sdk.jar:
/opt/SUNWam/lib/jss311.jar:/opt/SUNWam/lib/servlet.jar:
/opt/SUNWam/lib/crimson.jar:/opt/SUNWam/lib/am_logging.jar LDAPLogin.java

jar the resulting class file and properties file to login.jar using the jar command

jar -cvf login.jar ./LDAPLogin.class ./login_props.txt

2. Create a JNLP file for the application

The easiest way to create this file is to modify an existing JNLP file to your requirements. Download the source for the TestJWS.jnlp created for this application.

By including the following settings in the JNLP file, an application can request full access to a client system if all its JAR files are signed :

<security>
   <all-permissions/>
</security>

3. Signing JAR Files

We will sign our jar files created above with a test certificate for use with Java Web Start by using the standard jarsigner tool from the Java 2 SE SDK.

  1. Make sure that you have an SDK 1.4.2 keytool and jarsigner in your path. These tools are located in the SDK bin directory.

  2. Create a new key in a new keystore as follows:

            keytool -genkey -keystore myKeystore -alias myself
    

    You will get prompted for a information about the new key, such as password, name, etc. This will create the myKeystore file on disk.

  3. Then create a self-signed test certificate as follows:

            keytool -selfcert -alias myself -keystore myKeystore
    

    This will prompt for the password. Generating the certificate may take a few minutes.

  4. Check to make sure that everything is OK. To list the contents of the keystore, use this command:

            
            keytool -list -keystore myKeystore
    

    It should list something like:

     
            Keystore type: jks
            Keystore provider: SUN
    
            Your keystore contains 1 entry
    
            myself, Nov 13, 2003, keyEntry,
            Certificate fingerprint (MD5): 
            A2:56:A3:56:A4:A6:7F:08:EE:34:70:02:4D:EB:2E:5A
    

  5. Finally, sign the JAR file with the test certificate as follows:

       
            jarsigner -keystore myKeystore login.jar myself
    

  6. Repeat this step with all of your JAR files needed for running the sample program.

            jarsigner -keystore myKeystore am_logging.jar myself
            jarsigner -keystore myKeystore am_services.jar myself
            jarsigner -keystore myKeystore am_sdk.jar myself     
            jarsigner -keystore myKeystore jaas.jar myself          
            jarsigner -keystore myKeystore servlet.jar myself
            jarsigner -keystore myKeystore crimson.jar myself       
            jarsigner -keystore myKeystore jss311.jar myself        
            jarsigner -keystore myKeystore locale.jar myself
    

    (locale.jar contains the entire directory contents of /opt/SUNWam/locale)

       
            jarsigner -keystore myKeystore properties.jar myself
    

    (properties.jar contains all the properties files in /opt/SUNWam/lib, which are AMConfig.properties, LogConfig.properties and SSOConfig.properties).

 

Note: A self-signed test certificate should only be used for internal testing, since it does not guarantee the identity of the user and therefore cannot be trusted. A trustworthy certificate can be obtained from a certificate authority, such as VeriSign or Thawte, and should be used when the application is put into production.



4. Make the application accessible on the web server

Ensure your application's JAR files and the JNLP file are accessible at the URLs listed in the JNLP file.

  1. If you are using the standard Sun Java System Identity Server 6.0SP1 installation, create a directory called RemoteAuth in the web container, under /opt/SUNWam/public_html.
  2. Copy the jnlp and all the signed jar files to RemoteAuth.
  3. Stop and Start your webserver.


5. Launch your application with Java Web Start

We will launch our application using the Application Manager. The Application Manager keeps track of all applications that have been downloaded and launched using Java Web Start, and allows you to directly launch them.

Application Manager is launched by using the <install-dir>/javaws command on Solaris Operating System and Linux platforms or by clicking the icon on your desktop if you are running the Microsoft Windows operating system.

Java Web Start Console settings:

  1. Run javaws with no arguments

    Enable "Show Java Console" and "Log Output" to a Log File by navigating through File -> Preferences -> Advanced tabs

  2. You can now launch your application by passing the link pointing to the jnlp file like, http://dts-u80-1.xyz.dev.com:58080/RemoteAuth/TestJWS.jnlp

Now, on accepting the test certificate and starting the application, you will see that the sample program runs to completion as shown in the Log File. Here is the log file output:

Java Web Start 1.4.2_02 Console, started Fri Nov 14 16:47:37 PST 2003
Java 2 Runtime Environment: Version 1.4.2_02 by Sun Microsystems Inc.
Logging to file: /jws-hao.txt
LDAPLogin: Obtained login context
begin addLoginCallbackMessage()
Got NameCallback
User Name:: amadmin
Got PasswordCallback
Password:: password
Login success!!

Alternatively, you can install Java Web Start on your browser and create a web page that launches your application from the browser. Refer to the Java Web Start Developer's Guide for details.

Now you have successfully deployed the sample Identity Server LDAP Login application and made it available to all your clients who can access using Java Web Start.

Verifying Log Outputs

The location of all log files below refer to a standard Sun Java System Identity Server 6.0 SP1 installation on Solaris platform.

  1. In /var/opt/SUNWam/logs, you will notice similar log entries in the following files on successfull login,

    amAuthentication.access

    "14-11-2003 17:16:43" "Login Success UserId->uid=amAdmin,ou=People,dc=xyz,dc=dev,dc=COM
    UserDomain->dc=xyz,dc=dev,dc=COM module_instance->LDAP" proxy.xyz.dev.COM/129.149.247.58
    uid=amAdmin,ou=People,dc=xyz,dc=dev,dc=COM INFO dc=xyz,dc=dev,dc=COM 129.149.247.58

    amSSO.access

    "14-11-2003 17:16:43" "SESSION CREATE:uid=amAdmin,ou=People,dc=xyz,dc=dev,dc=COM"
    dts-u80-1.xyz.dev.COM "cn=dsameuser,ou=DSAME Users,dc=xyz,dc=dev,dc=COM" INFO
    dc=xyz,dc=dev,dc=COM dts-u80-1.xyz.dev.COM/129.145.28.83

  2. You can turn on more debug output in Sun Java System Identity Server by setting the debug level directive to message like

    com.iplanet.services.debug.level=message

    in /opt/SUNWam/lib/AMConfig.properties and restarting the server.

    The debug log files are generated in /var/opt/SUNWam/debug

    In the /var/opt/SUNWam/debug/amComm logfile, you will notice the credentials sent back to the Sun Java System Identity Server. The below example illustrates the XML message that contains the authentication credentials.



Received RequestSet XML :
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<RequestSet vers="1.0" svcid="auth" reqid="3">
<Request><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<AuthContext version="1.0"><Request authIdentifier=",sessionid>"><SubmitRequirements>
<Callbacks length="3">
<NameCallback><Prompt>User Name:</Prompt><Value>amadmin</Value></NameCallback>
<PasswordCallback echoPassword="false"><Prompt>Password:</Prompt>
<Value>password</Value></PasswordCallback>
</Callbacks></SubmitRequirements></Request>
</AuthContext>]]>
</Request>
</RequestSet>

The XML Response for the above is illustrated by example below.

Sent ResponseSet XML : <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ResponseSet vers="1.0" svcid="auth" reqid="3">
<Response><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<AuthContext version="1.0"><response >="" authidentifier="<sessionid>">
<LoginStatus status="success" ssoToken="sessionid" 
successURL="http://dts-u80-1.xyz.dev.COM:/amconsole"><subject >..</subject>
</LoginStatus></Response></AuthContext>]]></Response>
</ResponseSet>

 

Note: At the time of writing this article, Sun's Identity Server 6.1 product was not yet released. Hence it is not tested with that release, though the concepts and sample code should work with that release as well.



Conclusion

In this article you have seen the ease with which we can convert existing Identity Server client applications(standalone) to use the Java Web Start technique for distribution to clients. If you have developed a Java application using Remote Client API's for Sun's Identity Server and would like to serve this application to your entire corporate network accessing the central server, this would be an efficient way of distributing your application.

Author

Ck Prasad, a member of technical staff of the Marketing Development Engineering group at Sun, works with independent software vendors to develop and integrate applications with Sun Java Enterprise System products.

See Also

Java Web Start
Identity Server


Reader Feedback
Excellent   Good   Fair   Poor  

If you have other comments or ideas for future technical articles, please type them here:

Comments:
If you would like a reply to your comment, please submit your email address:
Note: We may not respond to all submitted comments.

Have a question about Java programming? Use Java Online Support.