Practical TAM Authorization API

Creating a JSP to display the TAM Credential

Learn simple use of the Tivoli Access Manager Java Authorization API to create a JSP which will display the TAM credential on a web application server running behind Tivoli Access Manager WebSEAL or the Tivoli Access Manager web plug-ins. This capability will essentially mirror the output of the "epac" CGI application that ships with the Tivoli Access Manager web runtime environment (except it will execute much faster!). A downloadable version of the final product is provided.

Shane B. Weeden, Senior Software Engineer, IBM

Shane WeedenShane Weeden is a senior software engineer with the IBM Federated Identity Manager development team. He has worked in IT security for 13 years, and has spent the last seven years working with Tivoli Security products. Shane has been with the Federated Identity Manager development team since its conception, and now divides his time between customer-focused engagements and core product development activities. He holds a Bachelor of Information Technology from the University of Queensland in Australia.



26 April 2007

Before you start

Learn what to expect from this tutorial, and how to get the most out of it.

About this tutorial

This tutorial takes you through a very basic IBM® Tivoli® Access Manager (TAM) Java™ authorization API example, written as a Java Server Page (JSP). This example will run on an application server (for example, WebSphere® Application Server), typically running behind a TAM WebSEAL server, or Web server with the TAM Web Server Plug-in installed. In this configuration, the WebSEAL or Web Server Plug-in will pass to our JSP the iv-creds HTTP header containing a TAM credential. This is a long ASN-1 encoded string representing a user's credentials in TAM.

Our example will user the TAM Java authorization API to unpack this credential and display it in an appealing HTML table, in much the same way as is done in the C programming language by the example epac demonstration program, which ships with the TAM PDWebRTE.

Objectives

In this tutorial, you’ll learn about the TAM Java authorization API, how to configure an application to use it, and some of the API's basic classes and methods. We won't be actually performing any authorization decisions in this tutorial - we will simply be using the API to read and display the attributes of a TAM credential.

Prerequisites

This tutorial is written for programmers working with Tivoli Access Manager whose skills and experience are at a beginning to intermediate level. You should have a basic knowledge of Java and Java Server Pages, and a working knowledge of Tivoli Access Manager.

System requirements

To develop and run the example in this tutorial, you need Tivoli Access Manager WebSEAL (or Web Plug-in) installed, along with the Authorization Server (pdacld). You also need an application server supported by the TAM Java Runtime (such as WebSphere Application Server). Typically the TAM Web Portal Manager administration console (PDWPM) that ships with TAM runs on WebSphere Application Server, and this is an ideal execution environment for the example we will develop.


Establishing an execution environment

Initially you need to establish a location to develop, test, and run your JSP. For those Development-minded folks, using an integrated development environment (IDE) like Eclipse is ideal, and if you are comfortable with this go ahead and create your own Web application with a JSP in it. You will need to configure the TAM JRTE against the JRE of your application server.

For those who have the TAM Web Portal Manager installed and running behind WebSEAL, and just want somewhere to run the JSP, you can just put the JSP (a simple text file) into the existing installed application. For example, on my Linux® system with a WebSphere Application Server profile called idp where PDWPM is installed, this directory is where I can put my example JSP

/opt/IBM/WebSphere/AppServer/profiles/idp/installedApps/idpNode01Cell/TAMWPM.ear/pdadmin.war

Besides having somewhere to run the JSP, you will also need to pass the TAM credentials to it in an HTTP header. This can be done with WebSEAL using a junction, or with the TAM Web Plug-in installed on an HTTP server fronting your JSP execution engine. This tutorial will use WebSEAL, junctioned to the WebSphere Server which hosts the PDWPM application. When creating the junction, you must configure it to include the iv-creds header. Example 1 demonstrates a pdadmin command for creating a junction passing the correct HTTP headers for our tutorial:

Example 1. Creating a WebSEAL junction which passes the iv-user and iv-creds headers
pdadmin sec_master> server task idp-webseald-idp.ibm.com create -t tcp -h 
localhost -p 9080
 -c all /appjct
Created junction at /appjct
pdadmin sec_master>

Having established your execution environment that can receive the iv-user and iv-creds headers, create a simple file called epac.jsp with the content shown in Listing 1:

Listing 1. Our first JSP
<html>
  <p>Hello <%=request.getHeader("iv-user")%>.</p>
  <p>Your raw credential is: <%=request.getHeader("iv-creds")%></p>
</html>

Now access your JSP using the browser, being sure to connect to the TAM WebSEAL or Web Plug-in. This will ensure the TAM credential (iv-creds) and TAM user (iv-user) HTTP headers are passed to the JSP. In my examples I will be using WebSEAL and the JSP will run on the WebSphere Application Server in the PDWPM directory shown above, so my URL will look like:

https://hostname/appjct/pdadmin/epac.jsp

Provided you have logged in with a valid TAM user ID, your screen should look something like:

Figure 1. The output of our first JSP
epac_1

Now that we have the basic JSP execution environment established, we can begin to expand on the functionality and robustness of the code, and introduce the TAM Java Authorization API.


Handling exceptions

In anticipation of any exceptions thrown in code we might call, we will now add a global try/catch block around our JSP code to catch and display in red text any exception text. Modify the epac.jsp to look like:

Listing 2. Adding exception handling
<html>

  <head>
    <%@page language="java"
      contentType="text/html; charset=ISO-8859-1"
      pageEncoding="ISO-8859-1"
      import = "java.io.PrintWriter"
      import = "java.io.StringWriter"
    %>
    <meta http-equiv="PRAGMA" content="NO-CACHE">
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <title>epac.jsp</title>
  </head>
  <body>
<%
    Exception error = null;
    String name = "";
    String cred = "";
    try {
      //
      // perform all our heavyweight processing that might throw an exception here
      //
      name = request.getHeader("iv-user");
      cred = request.getHeader("iv-creds");
    } catch (Exception e) {
      error = e;
    }

    //
    // Our "work" is over now - decide what we are going to display to the user
    //

    if (error != null ) {
      //
      // there was an error above - print the formatted error information
      //
      StringWriter sw = new StringWriter();
      PrintWriter pw = new PrintWriter(sw);
      error.printStackTrace(pw);
%>
      There was an error processing the credential: <%=error.getMessage()%>
      <br />
      <font color="RED">
      <pre>
      <%=sw.toString()%>
      </pre>
      </font>

<%
    } else {
      //
      // no error - print our credential data
      //
%>
      <p>Hello <%=name%>.</p>
      <p>Your raw credential is: <%=cred%></p>
<%
    }
%>
  </body>
</html>

We have introduced several new sections into the JSP – here are the significant items:

  • Added a @page section which includes our Java imports.
  • Added a meta tag to indicate that browsers should not cache this page.
  • Split the body into two main sections. The first section is where we are going to do all our volatile work (i.e. stuff that might throw an exception). The second section is where we are going to display the results of our work. This will either be formatted output from our processing above, or a formatted error.

We haven't actually changed the display of our working JSP at this stage, but we now have laid the groundwork to deal with any errors we might encounter. The rest of our work comprises two aspects:

  • Using the Java Authorization API to parse the credential into a Java data structure. This will be done within the try/catch block.
  • Displaying the credential data in an HTML table. This will be done in the lower part of the body if there is no error encountered.

Since this tutorial focuses on the Java Authorization API, we'll spend the majority of our time parsing the TAM credential into an internal data structure. The code to display the credential data in an HTML table will be provided without detailed explanation at the end.


Initializing the Java authorization API and creating a PDPrincipal

We are going to add sections to the JSP to initialize the TAM Java Authorization API, and use our TAM credential to create a PDPrincipal.

Make the changes indicated below to the JSP (between the sections marked BEGIN_ADD_CODE and END_ADD_CODE):

Listing 3. Initialization of the Java authorization API and creating a PDPrincipal
    ...
    
      // BEGIN_ADD_CODE
      
      import = "java.net.URL"
      import = "com.tivoli.pd.jazn.PDAuthorizationContext"
      import = "com.tivoli.pd.jazn.PDPrincipal"
      
      // END_ADD_CODE
      
    ...
    try {
      //
      // perform all our heavyweight processing that might throw an exception here
      //
      name = request.getHeader("iv-user");
      cred = request.getHeader("iv-creds");

      // BEGIN_ADD_CODE
      
      /*
      * First the configuration setting - you will need to update the tamcfgurl to point
      * to a tam java configuration file. This is typically created with the java command
      * com.tivoli.pd.pdjcfg.SvrSslCfg. If you have pdwpm (TAM console) installed on this
      * WebSphere, it has one you can just use. Otherwise use SrvSslCfg to create you own
      * config file (see TAM documentation for usage).
      */
      String tamcfgurl = "file:///opt/PolicyDirector/java/export/pdwpm/pdwpm.properties";

      //
      // build the authorization context needed for PD java API's
      //
      PDAuthorizationContext pdac = new PDAuthorizationContext(
        request.getLocale(),
        new URL(tamcfgurl));

      //
      // now build our PDPrincipal from the iv-creds header data
      //
      PDPrincipal princ = new PDPrincipal(pdac, cred.getBytes());
      
      // END_ADD_CODE

    } catch (Exception e) {
      error = e;
    }
    .

if all going well, this should result in no error when you run it, and you now have a PDPrincipal object which is built from the iv-creds header. This object is the base from which we will extract all the credential attribute information. What we have done here is initialize the TAM Java authorization API using the PDWPM configuration file. If you don't have PDWPM installed, you will need to use the TAM SrvSslCfg utility to generate and then point to your own server configuration file. Information on how to do this is contained in Appendix A of the Authorization Java Classes Developer Reference.

Take a closer look at how we have initialized the authorization API. You will see we have used the constructor PDAuthorizationContext(Locale, URL). There are several other constructors available including those that take user name and password credentials. Interestingly for this particular application, we don't actually need to authenticate to TAM as we will only be performing local operations to unpack the credential. In fact, we do not even need the authorization server (pdacld) to be running in order for our JSP to successfully execute!

If we were performing operations which contacted pdacld for their execution (for example running in remote-mode to build a TAM credential from a username, or performing an authorization check), then we would need pdacld running, and we would need to authenticate as a user with the required TAM permissions to perform these operations.

Now let's start unpacking the TAM credential into it's basic data elements.


Defining and populating the attribute data element

We are now going to add sections to the JSP to store the attribute information from the credential into a standard Java objects. We will use a HashMap, which will map from the attribute name to a String[] of attribute values. This will be populated by using the Java authorization API to unpack the attributes of the PDPrincipal.

Make the changes indicated below to the JSP (between the sections marked BEGIN_ADD_CODE and END_ADD_CODE):

Listing 4. Storing credential attributes in a Java HashMap
      ...
      
      // BEGIN_ADD_CODE
      
      import = "java.util.HashMap"
      import = "com.tivoli.pd.jutil.PDAttrValue"
      import = "com.tivoli.pd.jutil.PDAttrs"
      import  = "java.util.Collection"
      import  = "java.util.Collections"
      import = "java.util.Iterator"
      import = "java.util.Vector"

      // END_ADD_CODE
      
    ...
    Exception error = null;
    String name = "";
    String cred = "";
    
    // BEGIN_ADD_CODE
    
    //
    // The attrs HashMap will map a String attribute name to a String[] of values.
    //
    HashMap attrs = new HashMap();
    
    // END_ADD_CODE
    
      ...
      
      // now build our PDPrincipal from the iv-creds header data
      PDPrincipal princ = new PDPrincipal(pdac, cred.getBytes());
      
      // BEGIN_ADD_CODE
      
      PDAttrs pdattrs = princ.getAttrlist(pdac);
      for ( Iterator i = pdattrs.keySet().iterator(); i.hasNext(); ) {
        String key = (String) i.next();

        // use vector for string values so we can sort it
        Vector vvalues = new Vector();

        Collection values = pdattrs.getValues(key);
        if ( values != null ) {
          for ( Iterator j = values.iterator(); j.hasNext(); ) {
            PDAttrValue value = (PDAttrValue) j.next();
            Object o = value.getValue();
            if (o instanceof String) {
              String strval = (String) value.getValue();
              if (strval != null && strval.length() > 0) {
                vvalues.add(strval);
              }
            } else {
              /*
              * The class of this value object was not a string, 
              * so I am going to skip it. I have never actually 
              * seen this happen, but the API allows for it.
              */
            }
          }
        }

        // add the key and sorted String[] of values to the attrs HashMap
        Collections.sort(vvalues);
        attrs.put(key, vvalues.toArray(new String[]{}));
      }

      // END_ADD_CODE
    
    } catch ( Exception e ) {
      error = e;
    }
    ...

The additions we made above demonstrate how to parse out the set of String values of all attributes in the credential. For a more consistent user experience, we sort the set of attribute values before converting them to an array of strings. Now we actually have all the data we want to display - the final step is to display it to the user in a presentable HTML table.


Displaying the attribute data element

We are now going to add sections to the JSP to display our attribute data in an HTML table. We will sort the attribute keys so that the same credential is presented identically each time.

Make the changes indicated below to the JSP (between the sections marked BEGIN_ADD_CODE and END_ADD_CODE):

Listing 5. Displaying the credential attributes
    ...
<%
    } else {
      //
      // print our credential data
      //
%>
      <p>Hello <%=name%>.</p>
      <p>Your raw credential is: <%=cred%></p>
      
<!-- BEGIN_ADD_CODE -->

      <table border="">
        <tr>
          <td><b>Index</b></td>
          <td><b>Name</b></td>
          <td><b>Value(s)</b></td>
        </tr>
<%
        /* use a vector for the attribute names so we can sort it */
        Vector v = new Vector(attrs.keySet());
        Collections.sort(v);
        int index = 0;
        for( Iterator i = v.listIterator(); i.hasNext() ; ) {
          String key = (String) i.next();
          String[] values = (String[]) attrs.get(key);

          // first the attribute name as the first column of the row, and start next 
          column
%>
        <tr>
          <td><%=index++%></td>
          <td><%=key%></td>
          <td>
<%
          // now each of the values
          if ( values == null || values.length == 0 ) {
            // no values - print a space so the table element still draws a border
%>
            &nbsp;
<%
          } else {
            // there are values - put one on each line, indexed so we can tell them apart
            for ( int j = 0; j < values.length; j++ ) {
%>
              [<%=j%>]:&nbsp;<%=values[j]%>
<%
              // add a "newline" if there are more values to come for this attribute
              if ( j+1 < values.length ) {
%>
                <br />
<%
              }
            }
          } //now end of column, and end of row
%>
          </td>
        </tr>
<%
        } //end for (i.e. done processing this attribute)
%>
      </table>
      
<!-- END_ADD_CODE -->

<%
    }
%>
...

The additions we made above display the attributes in sorted order - and the results can be seen in the figure below:

Figure 2. The final output of our epac.jsp
epac_2

The Downloads section contains a completed epac.jsp ,which includes one additional feature – to parse iv-creds headers that are very large and split over multiple header elements. This is beyond the scope of this tutorial, but a useful feature for the robustness of the application. Enjoy.


Download

DescriptionNameSize
Sample JSP for this tutorialepac_jsp.zip3KB

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Tivoli (service management) on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Tivoli
ArticleID=215933
ArticleTitle=Practical TAM Authorization API
publish-date=04262007