Access Keys:
Skip to content (Access Key - 0)

WebSSO

WebSSO 1.3 Acegi Client Developers Guide

Table of Contents


Web Single Sign-On/Sign-Out Acegi Client (WebSSO Client) Installation and Configuration


The Web Single Sign-On/Sign-Out Acegi Client (WebSSO Acegi Client) is distributed both as a standalone project and a component other projects (such as caGrid). Each distribution contains a websso-client-acegidirectory, herein referred to as WEBSSO_CLIENT_LOCATION. To install and configure the WebSSO Acegi Client, please follow the steps below.

Step 1: Install Prerequisite Software


In order to install and run the WebSSO Acegi Client, the following pre-requisite software must be installed:

The WebSSO Server has been configured and installed. The URL to this server would be used for configuring the WebSSO Client. Make sure host-identityof WebSSO Client was added as delegated application in websso-properties.xml for WEBSSO-Server. Details on how to install and configure a WebSSO Server can be found at following location WebSSO Administrators Guide

Also, the target web application is a standard Java Web Application packaged in a war file. Details about a creating and packing a J2EE Web Application can be found on Sun's site at Packaging Web Components

Step 2: Building WebSSO Client


If you have obtained a source release of the WebSSO Client, you will need to build it. Type the following from a command prompt:

%> cd WEBSSO_LOCATION
%> ant clean all
Depending on the the WebSSO Client distribution, it may be required to build the entire project that the WebSSO Client is distributed with prior to building the WebSSO Client. For example, if you have obtained a caGrid source distribution, this is required. If you received a WebSSO Client standalone distribution, this is not required.

Step 3: Obtain a Host Credential


The WebSSO Client provides capability to retrieve user's delegated credentials by connecting to the Credentials Delegation Service (CDS). To use this feature, a host credential needs to be obtained for the container/server hosting the web application which will integrate with WebSSO Client. A host credential consist of an X.509 certificate and private key. Dorian provides the ability to issue and manage host credentials. There are many methods of retrieving host credentials, including:

  1. Requesting a credential from a known/trusted certificate authority ([caGrid Certificate Authority|websso13:Request a Host Certificate
    ]).
  2. Standing up a Dorian service.
  3. Standing up a simple certificate authority.

Once a host credentials are obtained and stored on the server, the path to the certificate file and the key file should be noted. This will be used to configure the Delegation Lookup filter.

Step 4: Configure Server to Trust the Certificate Authority


To connect to the Credential Delegation Service (CDS), one must configure the server hosting the Web Application to trust the CA that issued the host credentials obtained in the previous step.

NOTE: If you opt to start syncGTS programmatically execute the following. For detailed steps refer Step 7 and Step 8.

In order for SyncGTS to 'sync' up the CA certificates on the server hosting the web application, the master GTS Certificate Authority .0 file must be copied from GTS to server.
Copy the MASTER GTS CA.0 file from the GTS server that is at the $HOME/.globus/certificates to the $HOME/.globus/certificates folder on the server hosting the web application.

Note: If you don't opt to start syncGTS programatically execute the following. For detailed steps refer Step 7 and Step 8.

Place a copy of the certificate for the CA that issued the host credentials in the Globus trusted certificates directory. Unless otherwise specified during installation, this is usually USER_HOME/.globus/certificates. Globus requires all CA certificates in its trusted certificates directory to be in PEM format and to have a digit extension (0-9). For example, if a CA certificate is stored in the file cacert.pem, it should be copied to the directory USER_HOME/.globus/certificates (create directory if needed) with the file name "cacert.0"

Step 5: Create Host Credential Keystore


  1. Download and unzip gridca.
  2. Bring up a command prompt and change to the gridca directory which you recently unzipped.
  3. At the command line type ant createTomcatKeystore, this will execute a command line program which will guide you through creating the keystore.
  4. In the Enter a location and name for your keystore: prompt enter a file name and location to create your keystore.
  5. In the Enter a password for your keystore: prompt enter a password for your keystore.
  6. In the Enter the location of the certificate (PEM format): prompt enter the location of the host certificate you just created.
  7. In the Enter the location of the private key (PEM format): prompt enter the location of the private key you just created.
  8. In the Enter the current password of the private key: prompt enter the password for your private key, if you private key does not have a password (most cases) just hit enter.
  9. At this point the program will create your keystore at the location you specified. Below is a sample output of the program just described:
Enter a location and name for your keystore:mykeystore
Enter a password for your keystore:password
Enter the location of the certificate (PEM format):w:\certificates\dwight.bmi.ohio-state.edu-cert.pem
Enter the location of the private key (PEM format):w:\certificates\dwight.bmi.ohio-state.edu-key.pem
Enter the current password of the private key:

Step 6: Configuring Tomcat


Since the WebSSO Client would be running using SSL we need to configure Tomcat to enable SSL. To do so complete the following:

  1. Edit the file CATALINA_HOME/conf/server.xml (example shown below).
  2. Uncomment connector element for port 8443 (SSL)
  3. Add a keystoreFile parameter containing the location of the keystore you just created.
  4. Add a keystorePass parameter containing the the password of the keystore you just created.
  5. Restart tomcat
<!-- Define a SSL HTTP/1.1 Connector on port 8443 -->
<Connector port="8443" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" disableUploadTimeout="true"
acceptCount="100" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="C:/Documents and Settings/user_account/mykeystore"
keystorePass="password" />

Step 7: Integrating the WebSSO Client


Once host credentials have been obtained, you can integrate the WebSSO Client into your Web Application.The WebSSO Client is released as a set of jar and configuration files found in WEBSSO_CLIENT_LOCATION/build folder.

The WEBSSO_CLIENT_LOCATION/build contains the following three configuration files:

web-acegi-1.3-dev.xml
cas-client-template-acegi-1.3-dev.properties
applicationContext-acegi-1.3-dev.xml

The applicationContext-jasig-1.3-dev.xml file is a spring configuration files which contains the configuration setting for CAS Filters which are packaged as part of WebSSO Client. Rename this file to applicationContext.xml and copy to WEBAPP_LOCATION/WEB-INF/ folder.

The cas-client-template-jasig-1.3-dev.properties is the file which contains configuration for connecting to the Central CAS Single Sign On Server. Rename this file to cas-client.properties, resolve the tokens @WEBSSO.SERVER@, @WEBSSO.SERVER.HTTPS.PORT@, @WEBSSO.CLIENT.SERVER@, @WEBSSO.CLIENT.HTTP.PORT@, @WEBSSO.CLIENT.HOST.CERTIFICATE@, @WEBSSO.CLIENT.HOST.KEY@, @WEBSSO.CLIENT.HTTP.PORT@ and @WEBSSO.CLIENT.HTTPS.PORT@ with respective values and copy to WEBAPP_LOCATION/WEB-INF/classes folder

The web-acegi-1.3-dev.xml is a sample file provided to show entries which needs to be made to your web.xml file to enable the WebSSO Client capabilities in your application.Rename the file to web.xml.

Step 7.1: Configuring the applicationContext.xml File

applicationContext.xml has bean id defaultUserDetailsService. It implements default implementation,you must override this bean id to extend abstract class org.cagrid.websso.client.acegi.BaseUserDetailsService and implement loadUserByGridId(String gridId) method to add the authorization for the application using gridId.

Filter Entries:

When a WebSSO Server session ends or user logouts from web application, WebSSO server will callback to each of the services that are registered with the system and send a POST request:

 <samlp:LogoutRequest ID="[RANDOM ID]" Version="2.0" IssueInstant="[CURRENT DATE/TIME]">
  <saml:NameID>@NOT_USED@</saml:NameID>
  <samlp:SessionIndex>[SESSION IDENTIFIER]</samlp:SessionIndex>
  </samlp:LogoutRequest>

applicationContext.xml has a bean id filterChainProxy. It has two customized filters for handling of single sign out:

  1. casLogoutCallbackFilter - Filter parses SAML LogoutRequest message and reterives [SESSION IDENTIFIER or service Ticket] and add to expiredTicketCache.
  2. casLogoutFilter - retrieves service Ticket from expiredTicketCache and logs out user from WebSSO Client Application.

Step 7.2: Configuring the cas-client.properties File

The cas client is configured through a properties file: WEBSSO_CLIENT_LOCATION/build/cas-client-template-jasig-1.3-dev.properties. Below is an template of the cas-client-template-jasig-1.3-dev.properties file, followed by a description of each of the properties:

cas.server.url=https://@WEBSSO.SERVER@:@WEBSSO.SERVER.HTTPS.PORT@/webssoserver
cas.client.service=http://@WEBSSO.CLIENT.SERVER@:@WEBSSO.CLIENT.HTTP.PORT@/webssoclientacegiexample-1.3-dev

host.credential.certificate=@WEBSSO.CLIENT.HOST.CERTIFICATE@
host.credential.key=@WEBSSO.CLIENT.HOST.KEY@

http.port.number=@WEBSSO.CLIENT.HTTP.PORT@
https.port.number=@WEBSSO.CLIENT.HTTPS.PORT@

https.port.number=@WEBSSO.CLIENT.HTTPS.PORT@
cas-client.properties

  1. cas.server.url - This is the URL to the WebSSO's CAS Server.
    Note The CAS Server is generally installed in a secured container as a result of which the URL should have 'https'.
  2. cas.client.service - This is the URL to WebSSO client server.
  3. host.credential.certificate - This is the absolute path of websso acegi client server host credential certificate.
  4. host.credential.key - This is the absolute path of websso acegi client server host credential key.
  5. http.port.number - This is the http port for websso acegi client server.
  6. https.port.number - This is the https port for websso acegi client server.

An example file is show below

cas.server.url=https://localhosta:8443/webssoserver
cas.client.service=http://localhostb:8443/webssoclientacegiexample-1.3-dev

host.credential.certificate=C:\Documents and Settings\Garmillas\.cagrid\certificates\NCI-GARMILLAS-1-cert.pem
host.credential.key=C:\Documents and Settings\Garmillas\.cagrid\certificates\NCI-GARMILLAS-1-key.pem

http.port.number=8443
https.port.number=8443

Here localhosta is hosting the CAS Central Single Sign On Server and localhostb is hosting client application. Note - Also since both the applications are assumed to be running securely hence the default SSL ports for tomcats are shown.

This file should be placed in the WEB_LOCATION/WEB-INF/ folder of the client web application.

Step 7.3: Modifying the web.xml File

Once the cas-client.properties file is configured, you need to enable spring acegi integration with the WebSSO Client Application. To do this, make an entry into the web.xml. A sample web.xml is show below. This file can be found in the WEBSSO_CLIENT_LOCATION/build/ location of the WebSSO Client Release:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC '-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN' 'http://java.sun.com/dtd/web-app_2_3.dtd'>

<web-app>
	<display-name>Websso Acegi Client Application</display-name>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/applicationContext.xml</param-value>
	</context-param>

	<!--
		- Location of the Log4J config file, for initialization and refresh checks.
		- Applied by Log4jConfigListener.
	-->
	<context-param>
		<param-name>log4jConfigLocation</param-name>
		<param-value>/WEB-INF/classes/log4j.properties</param-value>
	</context-param>
	<context-param>
		<param-name>log4jExposeWebAppRoot</param-name>
		<param-value>false</param-value>
	</context-param>
	<filter>
		<filter-name>CAS Client Info Logging Filter</filter-name>
		<filter-class>org.inspektr.common.web.ClientInfoThreadLocalFilter</filter-class>
	</filter>
	<filter>
		<filter-name>Acegi Filter Chain Proxy</filter-name>
		<filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
		<init-param>
			<param-name>targetClass</param-name>
			<param-value>org.acegisecurity.util.FilterChainProxy</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>Acegi Filter Chain Proxy</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<listener>
		<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
	</listener>
	<servlet>
		<servlet-name>Start Auto Sync GTS</servlet-name>
		<servlet-class>org.cagrid.websso.common.StartSyncGTSServlet</servlet-class>
		<init-param>
			<param-name>start-auto-syncgts</param-name>
			<param-value>no</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet>
		<servlet-name>jsp</servlet-name>
		<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
		<init-param>
			<param-name>fork</param-name>
			<param-value>false</param-value>
		</init-param>
		<init-param>
			<param-name>xpoweredBy</param-name>
			<param-value>false</param-value>
		</init-param>
		<init-param>
			<param-name>mappedfile</param-name>
			<param-value>true</param-value>
		</init-param>
		<init-param>
			<param-name>compilerTargetVM</param-name>
			<param-value>1.5</param-value>
		</init-param>
		<init-param>
			<param-name>compilerSourceVM</param-name>
			<param-value>1.4</param-value>
		</init-param>
		<load-on-startup>2</load-on-startup>
	</servlet>

	<servlet>
		<servlet-name>TestUserInfoServlet</servlet-name>
		<servlet-class>test.TestUserInfoServlet</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>TestUserInfoServlet</servlet-name>
		<url-pattern>/protected/testuser</url-pattern>
	</servlet-mapping>


	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>

Following are the entries in the web.xml file which should be added to the Client Web Application's web.xml file:

Start-up Entries

  1. Start Auto Sync GTS - This entry is to load the "org.cagrid.gaards.websso.client.utils.StartSyncGTSServlet" Servlet on start up. This Servlet uses the sync-description.xml file from the classpath and starts the SyncGTS Daemon. If the target application doesnt want to automatically start the SyncGTS Daemon then they should remove this entry from the web.xml or edit the param value to no eg: <param-value>no</param-value>.
NOTE: Depending on how many start up servlets are configured for your application you would need to give appropriate number (based on start up order) to the load-on-startup entry

Other Entries

  1. contextConfigLocation - This entry is to define the spring based applicationContext.xml file entry which is needed by the CAS Client. This entry should be copied as it is in the client web application's web.xml file
  2. listener-class - This entry points to the listner class which should be used.

Step 8: Copying Sync Description File


In order to sync with the Grid Trust Fabric, the WebSSO Server needs a sync-description.xml file in its classpath to start SyncGTS programatically if the Start Auto Sync GTS Servlet is configured in the web.xml file above. Depending upon the grid you are trying to connect to, you need to obtain the sync-description.xml file from the corresponding Grid Administrator. This file needs to be placed in the classpath within the target application. This can be done by placing the file in the classes folder of the target application web archive (war file).

NOTE: if you haven't configure the Start Auto Sync GTSstart up servlet, then the onus of syncing with the trust fabric relies on the administrator. This can be done manually by starting the syncGTS Daemon on the target web application. For detailed steps refer to GTS

Step 9: Establish Trust with WebSSO CAS Server


In order for the client to trust the WebSSO Server you need to install the WebSSO Server's Public CA Cert into its truststore. This can be done by the following steps

  1. On the target application server, simply copy the cacerts to cacerts.old (to save it just in case)
  2. Run the java program given below by giving the following command - run java InstallCert <<CAS_SERVER_ADDRESS>>:<<CAS_SERVER_PORT>> (i.e. provide the argument "<<CAS_SERVER_ADDRESS>>:<<CAS_SERVER_PORT>>" to the executable "InstallCert"). (adapted source code for InstallCert.java from Sun blog by Andreas Sterbenz is shown below)
  3. Answer 1 to the prompt
/*
 * @(#)InstallCert.java 1.1 06/10/09
 *
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 * Use is subject to license terms.
 */


import java.io.*;
import java.net.URL;

import java.security.*;
import java.security.cert.*;

import javax.net.ssl.*;

public class InstallCert {

    public static void main(String[] args) throws Exception {
    String host;
    int port;
    char[] passphrase;
    if ((args.length == 1) || (args.length == 2)) {
        String[] c = args[0].split(":");
        host = c[0];
        port = (c.length == 1) ? 443 : Integer.parseInt(c[1]);
        String p = (args.length == 1) ? "changeit" : args[1];
        passphrase = p.toCharArray();
    } else {
        System.out.println("Usage: java InstallCert <host>[:port] [passphrase]");
        return;
    }

    File file = new File("jssecacerts");
    if (file.isFile() == false) {
        char SEP = File.separatorChar;
        File dir = new File(System.getProperty("java.home") + SEP
            + "lib" + SEP + "security");
        file = new File(dir, "jssecacerts");
        if (file.isFile() == false) {
        file = new File(dir, "cacerts");
        }
    }
    System.out.println("Loading KeyStore " + file + "...");
    InputStream in = new FileInputStream(file);
    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
    ks.load(in, passphrase);
    in.close();

    SSLContext context = SSLContext.getInstance("TLS");
    TrustManagerFactory tmf =
        TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(ks);
    X509TrustManager defaultTrustManager = (X509TrustManager)tmf.getTrustManagers()[0];
    SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
    context.init(null, new TrustManager[] {tm}, null);
    SSLSocketFactory factory = context.getSocketFactory();

    System.out.println("Opening connection to " + host + ":" + port + "...");
    SSLSocket socket = (SSLSocket)factory.createSocket(host, port);
    socket.setSoTimeout(10000);
    try {
        System.out.println("Starting SSL handshake...");
        socket.startHandshake();
        socket.close();
        System.out.println();
        System.out.println("No errors, certificate is already trusted");
    } catch (SSLException e) {
        System.out.println();
        e.printStackTrace(System.out);
    }

    X509Certificate[] chain = tm.chain;
    if (chain == null) {
        System.out.println("Could not obtain server certificate chain");
        return;
    }

    BufferedReader reader =
        new BufferedReader(new InputStreamReader(System.in));

    System.out.println();
    System.out.println("Server sent " + chain.length + " certificate(s):");
    System.out.println();
    MessageDigest sha1 = MessageDigest.getInstance("SHA1");
    MessageDigest md5 = MessageDigest.getInstance("MD5");
    for (int i = 0; i < chain.length; i++) {
        X509Certificate cert = chain[i];
        System.out.println
            (" " + (i + 1) + " Subject " + cert.getSubjectDN());
        System.out.println("   Issuer  " + cert.getIssuerDN());
        sha1.update(cert.getEncoded());
        System.out.println("   sha1    " + toHexString(sha1.digest()));
        md5.update(cert.getEncoded());
        System.out.println("   md5     " + toHexString(md5.digest()));
        System.out.println();
    }

    System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]");
    String line = reader.readLine().trim();
    int k;
    try {
        k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1;
    } catch (NumberFormatException e) {
        System.out.println("KeyStore not changed");
        return;
    }

    X509Certificate cert = chain[k];
    String alias = host + "-" + (k + 1);
    ks.setCertificateEntry(alias, cert);

    OutputStream out = new FileOutputStream(file);
    ks.store(out, passphrase);
    out.close();

    System.out.println();
    System.out.println(cert);
    System.out.println();
    System.out.println
        ("Added certificate to keystore 'cacerts' using alias '"
        + alias + "'");
    }

    private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();

    private static String toHexString(byte[] bytes) {
    StringBuilder sb = new StringBuilder(bytes.length * 3);
    for (int b : bytes) {
        b &= 0xff;
        sb.append(HEXDIGITS[b >> 4]);
        sb.append(HEXDIGITS[b & 15]);
        sb.append(' ');
    }
    return sb.toString();
    }

    private static class SavingTrustManager implements X509TrustManager {

      private final X509TrustManager tm;
      private X509Certificate[] chain;

      SavingTrustManager(X509TrustManager tm) {
          this.tm = tm;
      }

      public X509Certificate[] getAcceptedIssuers() {
          throw new UnsupportedOperationException();
      }

      public void checkClientTrusted(X509Certificate[] chain, String authType)
          throws CertificateException {
          throw new UnsupportedOperationException();
      }

      public void checkServerTrusted(X509Certificate[] chain, String authType)
          throws CertificateException {
          this.chain = chain;
          tm.checkServerTrusted(chain, authType);
      }
    }

}

Step 10: Retrieving User Attributes Inside Client Application


Once the WebSSO Client has been configured, you need to program your application to retrieve the session attributes which are injected by the WebSSO Client. Following is the list of session attributes which hold values of the corresponding User Attributes:

Session Attribute Name Information
CAGRID_SSO_GRID_IDENTITY User's Grid Identity
CAGRID_SSO_FIRST_NAME User's First Name
CAGRID_SSO_LAST_NAME User's Last Name
CAGRID_SSO_EMAIL_ID User's Email Id
CAGRID_SSO_DELEGATION_SERVICE_EPR Delegation Service's End Point Reference
CAGRID_SSO_GRID_CREDENTIAL User's Grid Credential
These attributes can be retrieved from the HTTP Session programmatically by specifying the individual session attribute name. Below is anexample servlet which retrieves all the attribute and prints them on the screen.

package test;
import java.io.*;


import javax.servlet.http.*;
import javax.servlet.*;

public class TestUserInfoServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// Returns a writer to write to the browser
		PrintWriter out = response.getWriter();
		out.println("<br>");
		out.println("<<<<< ATTRIBUTE NAME >>>>>  CAGRID_SSO_GRID_IDENTITY     <<<<< ATTRIBUTE VALUE >>>>>   " +
                request.getSession().getAttribute("CAGRID_SSO_GRID_IDENTITY"));

		out.println("<br>");

		out.println("<<<<< ATTRIBUTE NAME >>>>>  CAGRID_SSO_FIRST_NAME        <<<<< ATTRIBUTE VALUE >>>>>   " +
                request.getSession().getAttribute("CAGRID_SSO_FIRST_NAME"));

		out.println("<br>");

		out.println("<<<<< ATTRIBUTE NAME >>>>>  CAGRID_SSO_LAST_NAME         <<<<< ATTRIBUTE VALUE >>>>>   " +
                request.getSession().getAttribute("CAGRID_SSO_LAST_NAME"));

		out.println("<br>");

		out.println("<<<<< ATTRIBUTE NAME >>>>>  CAGRID_SSO_EMAIL_ID          <<<<< ATTRIBUTE VALUE >>>>>   " +
                request.getSession().getAttribute("CAGRID_SSO_EMAIL_ID"));

		out.println("<br>");

		out.println("<<<<< ATRIBUTE NAME >>>>>   CAGRID_SSO_DELEGATION_SERVICE_EPR  <<<<< ATTRIBUTE VALUE >>>>>  " +

                request.getSession().getAttribute("CAGRID_SSO_DELEGATION_SERVICE_EPR"));

		out.println("<br>");

		out.println("<<<<< ATTRIBUTE NAME >>>>> CAGRID_SSO_GRID_CREDENTIAL    <<<<< ATTRIBUTE VALUE >>>>>   " +
                request.getSession().getAttribute("CAGRID_SSO_GRID_CREDENTIAL"));

		out.println("<br>");
  }
}
Last edited by
Santhosh Garmilla (1477 days ago) , ...
Adaptavist Theme Builder Powered by Atlassian Confluence