Understanding Single Signon and Pagelets

This section discusses:

  • Single signon.

  • The PeopleSoft authentication process.

  • The PeopleSoft authentication API.

The examples shown thus far have used publicly-available URLs. Even if the examples represent third-party applications, the discussion has concentrated on retrieving data and rendering a pagelet. The topic has not yet discussed the possible need to sign in to a non-PeopleSoft system.

When two or more systems need separate authentication, automating the sign in process is preferable. Needing to manually sign in to several different systems each day is inconvenient and annoying. Users often expect a business portal to be similar to accessing a variety of internet websites. Once signed in to the portal, a user should rarely (if ever) need to sign in to another system.

Implementing single signon between PeopleSoft and other systems can be done in several ways. First, you need to determine the primary (or master) and secondary authentication systems.

  • PeopleSoft system as primary.

    Once a PeopleSoft user has signed in, an authentication cookie is sent to the browser's memory. Other applications can choose to authenticate using this cookie. Oracle provides an API that other applications can leverage. This is the option that is discussed in detail in this section.

  • PeopleSoft system as secondary.

    The PeopleSoft authentication process is flexible enough to enable accessing another system.

    See Enabling Signon PeopleCode for LDAP Authentication.

  • PeopleSoft system and other applications as secondary to third-party authentication system.

    A variant of the previous option would be for all applications (including PeopleSoft) to leverage, or trust, a third-party authentication system such as Netegrity, Oblix, or Securant.

    If you are writing a pagelet for the PeopleSoft portal, you have no guarantee that all possible customers for the pagelet will have access to a third-party authentication system. Thus, this option is not discussed in this PeopleBook.

Before discussing how your pagelet could leverage PeopleSoft authentication, you need to understand the authentication process.

After the first application server or node authenticates a user, the PeopleSoft application delivers a web browser cookie containing an authentication token. PeopleSoft Pure Internet Architecture uses web browser cookies to store a unique access token for all users after they are initially authenticated. When the user connects to another PeopleSoft application server/node, the second application server uses the token in the browser cookie to reauthenticate the user in the background so that they do not have to complete the sign-in process again. Your non-PeopleSoft application could do something similar.

Single signon is critical for PeopleSoft portal implementations because the portal integrates content from various data sources and application servers and presents them in a unified interface. When users sign in through the portal, they always take advantage of single signon. Users need to sign in once and be able to navigate freely without encountering numerous sign-in screens.

The following table presents the fields that appear in the PeopleSoft authentication token.

Field

Description

User ID

Contains the user ID of the user to which the server issued the token. When the browser submits this token for single sign-on, this is the user that the application server signs in to the system.

Language Code

Specifies the language code of the user. When the system uses this token for single sign-on, it sets the language code for the session based on this value.

Date and Time Issued

Specifies the date and time that the token was first issued. The system uses this field to enforce a time-out interval for the single sign-on token. Any application server that accepts tokens for sign-in has a time-out minutes parameter configured at the system level.

A system administrator sets this parameter using the Single Signon page. The value is in Greenwich Mean Time (GMT), so the application server’s time zone is irrelevant.

Issuing System

Specifies the name of the system that issued the token. When it creates the token, the application server retrieves this value from the database. Specifically, it retrieves the defined local node. Single sign-on is not related to PeopleSoft Integration Broker messaging, except that single sign-on functionality leverages the messaging concept of nodes and local nodes.

You configure only a node to trust single sign-on tokens from specific nodes. Consequently, an application server needs an Issuing System value so that it can check against its list of trusted nodes to determine whether it trusts the issued token.

Signature

Contains a digital signature that enables the application server using a token for single sign-on to ensure that the token hasn't been tampered with after it was originally issued. The system issuing the token generates the signature by concatenating the contents of the token (all of the fields that appear in this table) with the message node password for the local node. The system then hashes the resulting string using the SHA1 hash algorithm for example,

signature = SHA1_Hash ( UserID + Lang + Date Time issued + Issuing System + Local Node Pswd )

Note: The "+" indicates concatenation.

Only one way is available to derive the 160 bits of data that make up the signature, and that is by hashing exactly the same user ID, language, date time, issuing system, and node password.

Note: If you are using digital certificate authentication, the signature of the digital certificate occupies this space. The preceding description applies only to using password authentication.

Note: Single signon does not depend on the use of an LDAP (Lightweight Directory Access Protocol) directory. You can store user credentials in an LDAP directory if desired, but it is not required.

These are the key security features of the cookie authentication token:

  • The cookie exists in memory; it is not written to disk.

  • No password is stored in the cookie.

  • You can set the expiration of the cookie to be a matter of minutes or hours. This expiration option is a useful security feature.

  • The cookie is encrypted and digitally signed using a checksum to prevent tampering.

Oracle delivers a component interface named PRTL_SS_CI, which enables external applications to seamlessly integrate a single sign-on solution with the PeopleSoft portal applications. This component interface helps ensure that users who have already signed in to the portal don't have to sign in again for every system that you reference in your portal.

Component interfaces are the focal points for externalizing access to existing PeopleSoft components. They provide real-time synchronous access to the PeopleSoft business rules and data associated with a component outside the PeopleSoft online system. Component interfaces can be viewed as black boxes that encapsulate PeopleSoft data and business processes, and hide the details of the structure and implementation of the underlying page and data.

To take advantage of the Single Signon API, you need to create a custom API, which includes building the dynamic link libraries, classes, and registry settings necessary to enable an external application to communicate with the portal. This can be done automatically through PeopleTools. More information about building dynamic link libraries, classes, and registry settings, as well as other details about PeopleSoft component interfaces, can be found in PeopleTools: Component Interfaces

See Understanding the Authentication DomainSecurity Properties.

Only external applications, such as COM, C/C++, or Java programs require a component interface API. PeopleCode programs do not require a component interface API and, in fact, Oracle does not recommend building a component interface API if the component interface is to be accessed from PeopleCode only.

The files of your custom API need to reside on the client machine, that is, the web server for ASP and the machine running the Java program for Java. The registry file may also need to be run to update the registry with the new libraries.

The Signon Process with the API

The PRTL_SS_CI component interface contains two user-defined methods:

  • Authenticate( ).

    Your external authentication program distributes an authentication token that can be retrieved from a cookie in the browser. The Authenticate function determines whether an authentication token is valid.

  • GetUserID( ).

    If the token is valid, you use the GetUserID function to retrieve the user ID associated with the authentication token.

Before reading about the development requirements of your API, examine the steps that occur internally when you use the API in conjunction with the delivered PRTL_SS_CI:

  1. The user enters the user ID and password into the PeopleSoft portal sign-in page.

  2. If the sign-in to the portal application server is successful, the server generates a single signon token. The web server receives the single sign-on token from the application server and issues a cookie to the browser.

  3. The user navigates in the portal and encounters a link to the external system. The user clicks the link.

  4. The browser passes the PS_TOKEN cookie to the external web server.

  5. The external web server checks for the PS_TOKEN cookie before displaying a sign-in page.

  6. After the system determines that the user is accessing the application through the PeopleSoft portal, you retrieve the authentication token and send it to the PRTL_SS_CI component interface to verify authentication. For instance, it calls PRTL_SS_CI.Authenticate(Auth. token string).

  7. After the system authenticates the token, it can then make calls to the PRTL_SS_CI.Get_UserID() function to return the appropriate user ID.

In general, cookies are not transferable across domains. The only domain that can access the cookie is the domain that created it. Therefore, the web server for the non-PeopleSoft system must be on the same domain as the PeopleSoft system so that the cookies are passed appropriately.

External Application Support for Single Sign-on

Developers of external applications need to alter the sign-on process to conform to the following requirements:

  1. Check for the PS_TOKEN cookie. If the cookie doesn't exist, continue with the normal sign-in process. Otherwise, bypass the sign-in page.

  2. Retrieve the authentication token from the PS_TOKEN cookie.

  3. Connect to the PeopleSoft portal through the PRTL_SS_CI API.

  4. Pass the authentication token to the Authenticate() function of the API.

  5. If Authenticate() returns True, retrieve the user ID associated with the authentication token using the Get_UserID() function.

Authentication API PeopleCode Example

The following PeopleCode example shows the process of validating your authentication token and retrieving the user ID. This example is designed to provide a general idea of the process involved and to help you incorporate the PRTL_SS_CI API into your sign-in process.

Local ApiObject &THISSESSION;
Local ApiObject &THISCI;
Local string &AUTHTKN;
/* Assigns the Authentication Token to a variable */
		&AUTHTKN = %AuthenticationToken;
/* Open a session and make a connection */
		&THISSESSION = GetSession();
			If &THISSESSION.connect(1, "EXISTING", "", "", 0) <> True Then
				WinMessage(MsgGet(30000, 1, "Session Connect Failed."));
				Exit (1);
			End-If;
/* Retrieves the component interface PRTL_SS_CI */
		&THISCI = &THISSESSION.GetCompIntfc(CompIntfc.PRTL_SS_CI);
/* Checks to see if the component interface is NULL */
			If &THISCI = Null Then
				WinMessage("Component Interface PRTL_SS_CI not found. 
				Please ensure Component Interface Security access is granted 
				to this user.");
				Exit (1);
			End-If;
/* Key fields would usually be set before the Get() function is 
called in order to map the component interface to a particular 
set of data. This component interface is not mapped to data.
* Therefore, the component interface is retrieved and then the 
user defined methods are retrieved */
		&THISCI.get();
		PRTL_AUTH = &THISCI.Authenticate(&AUTHTKN);
		PRTL_USER_ID = &THISCI.Get_UserID();

Note: The component interface is not mapped to data because the key field for the data would be the authentication token. This token is dynamically assigned when the user signs in to the portal, and it is not stored as data anywhere in the system. Therefore, no key fields are needed and the token is passed directly to the user-defined functions.

Authentication API Java Example

Here is an example of a similar operation written in Java. This is a file named SingleSignon.java.

package examples.migration.sso;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
import psft.pt8.joa.*;
import PeopleSoft.Generated.CompIntfc.*;

public class SingleSignon extends HttpServlet {
  public static ISession oSession;
  String psfttoken;
  public static void ErrorHandler() {
  		//***** Display PeopleSoft Error Messages *****
if (oSession.getErrorPending() || oSession.getWarningPending()) {
  			IPSMessageCollection oPSMessageCollection;
  			IPSMessage oPSMessage;

  			oPSMessageCollection = oSession.getPSMessages();
for (int i = 0; i < oPSMessageCollection.getCount(); i++) {
  				oPSMessage = oPSMessageCollection.item(i);
  				if (oPSMessage != null)
  					System.out.println("(" + oPSMessage.getMessageSetNumber() + ","
 + oPSMessage.getMessageSetNumber() + ") : " + oPSMessage.getText());
  			}
  			//***** Done processing messages in the collection; 
OK to delete *****
  			oPSMessageCollection.deleteAll();
  		}
	}

  public void doGet(HttpServletRequest request,
                    HttpServletResponse response)
      throws ServletException, IOException {
		  try {
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();

    Cookie[] cookies = request.getCookies();
	    if (cookies == null) {
	      out.println("<TR><TH COLSPAN=2>No cookies");
	    } else {
	      Cookie cookie;
	      for(int i=0; i<cookies.length; i++) {
	        cookie = cookies[i];

	        String pstoken = cookie.getName();
            psfttoken = cookie.getValue();
            if (pstoken.equals ("PS_TOKEN"))

               out.println("<TR>\n" +
	                  "  <TD>" + pstoken + "\n" +
	                  "  <TD>" + psfttoken);
	      }

	    }

     String strServerName, strServerPort, strAppServerPath;
		String strUserID, strPassword;
		strServerName = "jfinnon09";
                strServerPort = "9500";
                strUserID = "VP1";
                strPassword = "password";

		//Build Application Server Path
		strAppServerPath = strServerName + ":" + strServerPort;

      //***** Create PeopleSoft Session Object *****
      //       ISession oSession;

		oSession = API.createSession();

		//***** Connect to the App Server *****
		if (!oSession.connect(1, strAppServerPath, strUserID, strPassword,
 null)) {
			out.println("\nUnable for Jason to Connect to 
Application Server.");
			ErrorHandler();
			return;
		}

     //***** Get Component Interface *****
		IPrtlSsCi oPrtlSsCi;
		String ciName;
	 	ciName = "PRTL_SS_CI";
		oPrtlSsCi = (IPrtlSsCi) oSession.getCompIntfc(ciName);
		if (oPrtlSsCi == null) {
			out.println("\nUnable to Get Component Interface " + ciName);
			ErrorHandler();
			return;
		}

		//***** Set the Component Interface Mode *****
				oPrtlSsCi.setInteractiveMode(false);
				oPrtlSsCi.setGetHistoryItems(true);
				oPrtlSsCi.setEditHistoryItems(false);

		//***** Set Component Interface Get/Create Keys *****

				//***** Execute Get *****
				if (!oPrtlSsCi.get()) {
					out.println("\nNo rows exist for the specified keys.
	\nFailed to get the Component Interface.");
					ErrorHandler();
					return;
				}

				//***** BEGIN:  Set/Get Component Interface Properties *****

				//***** Set Level 0 Properties *****
				//out.println("oPrtlSsCi.PrtlToken: " +
 oPrtlSsCi.getPrtlToken());
				//out.println("Checking token: " + psfttoken);

				//oPrtlSsCi.setPrtlToken(<*>);
		                //String psfttoken;
		                //psfttoken = oPrtlSsCi.getPrtlToken();
		                //System.out.println("oPrtlSsCi.PrtlToken: "
 + psfttoken);

				//***** END:  Set Component Interface Properties *****

				//***** Execute Standard and Custom Methods *****
				//***** Execute Authenticate *****
				boolean auth;

		         auth = oPrtlSsCi.authenticate(psfttoken);
		         //out.println("Auth: " + auth);
				//Execute Get_UserID
		                String psftuser;
				psftuser = oPrtlSsCi.getUserid();
                //out.println("Psftuserid: " + psftuser);

                 String title = "Welcome  " + psftuser;

                //****** Get HTML ***********
                 out.println(ServletUtilities.headWithTitle(title));
                 out.println("</BODY></HTML>");

                //***** Disconnect from the App Server *****
		        oSession.disconnect();
		        return;
  }


  catch (Exception e) {
  		e.printStackTrace();
  		System.out.println("An error occurred: ");
  		ErrorHandler();
  	}
	}


  /** Let the same servlet handle both GET and POST. */

  public void doPost(HttpServletRequest request,
                     HttpServletResponse response)
      throws ServletException, IOException {
    doGet(request, response);
  }

}