Skip Headers
Oracle® Fusion Middleware Security Guide for Oracle WebLogic Portal
10g Release 3 (10.3.6)

Part Number E14251-08
Go to Documentation Home
Home
Go to Table of Contents
Contents
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

5 Securing Third-Party Applications

Some portlets need to connect to back-end systems or remote applications with a user name and password. If a remote application uses the same credentials as those used by the portal, the portlets can re-use the credentials. However, in most cases, the credentials required by remote systems are not same as user credentials used for logging into the portal. For optimal user experience, a single sign-on is needed. The Credential Vault provides a safe storage mechanism to securely set and retrieve credentials for portlets accessing remote applications.

5.1 Understanding the Credential Vault

In previous releases of WebLogic Portal, you could implement functionality similar to the Credential Vault by storing credentials in user profiles. However, user profile properties are not encrypted and not a safe place for storing credentials. Although it is possible to encrypt properties using WebLogic Server encryption methods, they are complex, limited, and required custom programming. Additionally, JCA cannot be used because JCA adapters do not fit into the portlet scope.

The Credential Vault provides APIs that allow portlets to store and access user credentials and use those credentials to log into remote applications on behalf of the user. With these APIs, a developer can build secure repositories that store user names and passwords, plus optional metadata required by the resource, such as a URL. The user name and password are encrypted, while the metadata (name value pairs of String type) are stored in plain text. The Credential Vault does not provide the mechanism to pass the credentials to the remote system.

In addition to the APIs, the Credential Vault provides a GUI in the WebLogic Portal Administration Console, where a portal administrator can create a system credential vault. The three types of credential vaults are as follows:

5.1.1 User Credential Vault

A user credential vault securely stores a user's credentials for a remote system for individual portlets based only on the user name. In other words, a credential entry is accessible to all the resource instances of a logged-in user. In the Oracle Fusion Middleware Java API Reference for Oracle WebLogic Portal, this entry is called USER_TYPE.

Using the Credential Vault APIs in a typical implementation, a portlet is created that allows a user to provide their login information to a remote system. After that, whenever the user logs into the portal, the portlet code automatically reads the login information and passes it to the remote application without the user having to re-enter their credentials. The following figure shows an example of this type of credential vault, where two portlets on the same portal page connect to two different remote systems.

Figure 5-1 User Credential Vaults

Description of Figure 5-1 follows
Description of "Figure 5-1 User Credential Vaults "

5.1.2 User + Resource Credential Vault

Use this type of credential vault when a portal contains two or more portlets that connect to the same remote system for users who require different credentials. For example, one portlet might connect the user to the remote system as a generic user and the other portlet might connect the user as an administrator. In a User + Resource Credential Vault, credential entry is only accessible to a particular resource instance of the logged-in user. In the Oracle Fusion Middleware Java API Reference for Oracle WebLogic Portal, this entry is called RESOURCE_TYPE.

Figure 5-2 User + Resource Credential Vault

Description of Figure 5-2 follows
Description of "Figure 5-2 User + Resource Credential Vault"

5.1.3 System Credential Vault

An administrator can create a system credential vault that stores a global user name and password so that credential entry is accessible to all resource instances of all logged-in users. In the Oracle Fusion Middleware Java API Reference for Oracle WebLogic Portal, this entry is called SYSTEM_TYPE.

This type of credential vault allows multiple users to share the same password (and user name) to access a remote resource. It is best suited for use as a demonstration account, where a user has read-only access to a resource before getting an account. You can use either the Credential Vault APIs or the WebLogic Portal Administration Console to create a system credential vault. For more information, see Section 5.2, "Using the Credential Vault APIs" and Section 5.4, "Creating or Viewing System Credentials in the Administration Console."

5.1.4 Visibility

You can specify the scope of the three types of credential vaults entry across web applications, enterprise applications, and within a domain:

  • Web Application—web application-scoped credential entries are not visible to different web applications within the same enterprise application.

  • Enterprise application—enterprise application-scoped credential entries are not visible to a different enterprise application in the same domain.

  • Domain—domain-scoped credential entries are global entries, which are visible to all applications within the domain.

Scoping allows you to shadow the names of the credential vaults within the Java EE application. Within the same scope, the names must be unique. In different scopes you can shadow the name. From an outer scope, all the names are visible to any of its containing scope. For example, if both an EAR scope and WAR scope have a credential vault named foo, the credential vault in WAR scope is used because foo in WAR scope shadows the foo within the EAR scope.

The following figure shows an example.

Figure 5-3 Credential Vaults

Description of Figure 5-3 follows
Description of "Figure 5-3 Credential Vaults"

When accessing the credential vault, the code associated with a portlet traverses the credential vaults until it finds an entry for the user. If no credentials are found, you can use the APIs to present a login to the user. The following example provides more details:

Suppose an employee logs into a Human Resources portal page with their WebLogic authenticated user name and password. This page contains portlets to services such as payroll, stock options, and career development. The employee wants to change their payroll deduction and the payroll system exists on a remote SAP application. When the employee clicks the Payroll portlet, the system looks for the login credentials in the payroll credential vault (Web App). If it finds the employee's credentials, the portlet logs in the user to the SAP payroll application.

If the employee's credentials do not exist in that credential vault, the portlet looks for them in the enterprise credential vault (EAR). If the enterprise credential vault contains the employee's credentials, the portlet logs the employee into the SAP payroll application. If not, the system looks for the credentials in the global credential vault (domain). If the portlet finds the employee's credentials, the employee is logged on to the remote SAP application. If not, the portlet presents a login to the SAP application.

Once the user successfully logs onto the SAP application, the credentials are stored in one of the credential vaults; which credential vault is determined by the system design.

5.2 Using the Credential Vault APIs

The package com.bea.p13n.security.management.credentials, documented in Oracle Fusion Middleware Java API Reference for Oracle WebLogic Portal, lets you create entries and access the three types of credential vaults. The Javadoc provides the detailed information that you need for implementing credential vaults. The following sections provide the framework for using creating and accessing credential vaults.

Note:

Some of the following sections use RESOURCE_TYPE (User + Resource) as an example of the credential vault type. To change type, simply change RESOURCE_TYPE to either USER_TYPE or SYSTEM_TYPE.

5.2.1 Initialize the Credential Vault

The entry point to the credential vault API is through the Credential Vault Service interface:

CredentailVaultService cvs = com.bea.wlp.services.Services.getService(com.bea.p13n.security.management.credentials.CredentailVaultService.class)

5.2.2 Construct the Resource Key

The resource key contains the scope and Resource ID of the credential service. You must specify the scope because the portlet instance is a web-scoped resource.

ResourceKey rc = new ResourceKey(Scope.getWebApplicationScope(request), portletInstanceId);

Tip:

Although the resource ID is not required for User or System credential vaults, it is a best practice to use the actual Resource ID. This will allow you to easily convert the credential vault to a different type in the future.

5.2.3 Creating a Credential Entry

When you create an entry you set the resource key and entry type for the credential vault. The entry type is one of the following: USER_TYPE (User), RESOURCE_TYPE (User + Resource), or SYSTEM_TYPE (System).

return cvs.createCredentialEntry(entryName, EntryType.RESOURCE_TYPE, null, rc);

You can also provide a description for the entry. If you do not want a description, use null.

5.2.4 Accessing a Credential Entry

When you access an entry, you supply the resource key and entry type for the credential vault. The entry type is one of the following: USER_TYPE (User), RESOURCE_TYPE (User + Resource), or SYSTEM_TYPE (System).

return cvs.fetchCredentialEntry(entryName, EntryType.RESOURCE_TYPE, rc);

Note:

If more than one entry exists with same name but a different scope, the one with closest scope to requesting resource is retrieved.

5.2.5 Updating a Credential Entry

To add or change the user name and password, use UserPasswordCredential.

entry.setCredential(new UserPasswordCredential(username, password.getBytes("UTF-8")));

5.2.6 Deleting a Credential Entry

To remove a credential entry, use removeCredentialEntry.

cvs.removeCredentialEntry(entryName, EntryType.RESOURCE_TYPE, rc);

5.3 Credential Vault Examples

Sample code showing CRUD operations for each type of credential vault may be available on the Oracle Technology Network web site at http://www.oracle.com/technology/index.html. Search for Credential Vault.

The following examples show the CRUD operations for a user (USER_TYPE) credential vault. For User + Resource and System Credential Vaults, you only need to change the type to RESOURCE_TYPE or SYSTEM_TYPE respectively.

The CredentialVaultHelper class demonstrates all of the code you need for using the Credential Vault API.

Example 5-1 CredentialHelper Class

package examples.credential;
import javax.servlet.http.HttpServletRequest;
import com.bea.p13n.security.management.credentials.AlreadyExistsException;
import com.bea.p13n.security.management.credentials.CredentialVaultService;
import com.bea.p13n.security.management.credentials.ResourceKey;
import com.bea.p13n.security.management.credentials.Scope;
import com.bea.p13n.security.management.credentials.CredentialEntry;
import com.bea.p13n.security.management.credentials.CredentialEntry.EntryType;
public class CredentialHelper
{
   private static CredentialVaultService cvs = com.bea.wlp.services.Services.getService(CredentialVaultService.class);
   
   public static CredentialEntry createCredentialEntryForPortletInstance(String entryName, HttpServletRequest request)
      throws AlreadyExistsException 
   {
      String portletInstanceId = com.bea.netuix.util.PortalFrameworkUtils.getUniquePortletDesktopString(request);
      // need webapp scope since portlet instance is web scoped resource.
      ResourceKey rc = new ResourceKey(Scope.getWebApplicationScope(request), portletInstanceId);
      return cvs.createCredentialEntry(entryName, EntryType.RESOURCE_TYPE, null, rc);
   }
   public static CredentialEntry getCredentialEntryForPortletInstance(String entryName, HttpServletRequest request)
   {
      String portletInstanceId = com.bea.netuix.util.PortalFrameworkUtils.getUniquePortletDesktopString(request);
      // need webapp scope since portlet instance is web scoped resource.
      ResourceKey rc = new ResourceKey(Scope.getWebApplicationScope(request), portletInstanceId);
      return cvs.fetchCredentialEntry(entryName, EntryType.RESOURCE_TYPE, rc);
   }
   
   public static void removeCredentialEntryForPortletInstance(String entryName, HttpServletRequest request)
   {
      String portletInstanceId = com.bea.netuix.util.PortalFrameworkUtils.getUniquePortletDesktopString(request);
      // need webapp scope since portlet instance is web scoped resource.
      ResourceKey rc = new ResourceKey(Scope.getWebApplicationScope(request), portletInstanceId);
      cvs.removeCredentialEntry(entryName, EntryType.RESOURCE_TYPE, rc);
   }
   
   public static CredentialEntry createUserCredentialEntry(String entryName, HttpServletRequest request)
      throws AlreadyExistsException
   {
      // resourceId is not important in user type credential, you can use anything you like
      String dummyResourceId = com.bea.netuix.util.PortalFrameworkUtils.getUniquePortletDesktopString(request);
      // this case use enterprise scope, so all portal web can see this entry, but not another enterpise app target to external users.
      ResourceKey rc = new ResourceKey(Scope.getApplicationScope(), dummyResourceId);
      return cvs.createCredentialEntry(entryName, EntryType.USER_TYPE, null, rc);
   }
   public static CredentialEntry getUserCredentialEntry(String entryName, HttpServletRequest request)
   {
      // resourceId is not important in user type credential, you can use anything you like
      String dummyResourceId = com.bea.netuix.util.PortalFrameworkUtils.getUniquePortletDesktopString(request);
      // this case use enterprise scope, so all portal web can see this entry, but not another enterpise app target to external users.
      ResourceKey rc = new ResourceKey(Scope.getApplicationScope(), dummyResourceId);
      return cvs.fetchCredentialEntry(entryName, EntryType.USER_TYPE, rc);
   }
   public static void removeUserCredentialEntry(String entryName, HttpServletRequest request)
   {
      // resourceId is not important in user type credential, you can use anything you like
      String dummyResourceId = com.bea.netuix.util.PortalFrameworkUtils.getUniquePortletDesktopString(request);
      // this case use enterprise scope, so all portal web can see this entry, but not another enterpise app target to external users.
      ResourceKey rc = new ResourceKey(Scope.getApplicationScope(), dummyResourceId);
      cvs.removeCredentialEntry(entryName, EntryType.USER_TYPE, rc);
   }
   // only portal administrator have the privilige to create system type credential
   public static CredentialEntry createCommonCredentialEntry(String entryName, HttpServletRequest request)
      throws AlreadyExistsException
   {
      // resourceId is not important in system type credential, you can use anything you like
      String dummyResourceId = com.bea.netuix.util.PortalFrameworkUtils.getUniquePortletDesktopString(request);
      // this case use enterprise scope, so all portal web can see this entry, but not another enterpise app target to external users.
      ResourceKey rc = new ResourceKey(Scope.getApplicationScope(), dummyResourceId);
      return cvs.createCredentialEntry(entryName, EntryType.SYSTEM_TYPE, null, rc);
   }
   public static CredentialEntry getCommonCredentialEntry(String entryName, HttpServletRequest request)
   {
      // resourceId is not important in system type credential, you can use anything you like
      String dummyResourceId = com.bea.netuix.util.PortalFrameworkUtils.getUniquePortletDesktopString(request);
      // this case use enterprise scope, so all portal web can see this entry, but not another enterpise app target to external users.
      ResourceKey rc = new ResourceKey(Scope.getApplicationScope(), dummyResourceId);
      return cvs.fetchCredentialEntry(entryName, EntryType.SYSTEM_TYPE, rc);
   }
   // only portal administrator have the privilige to create system type credential
   public static void removeCommonCredentialEntry(String entryName, HttpServletRequest request)
   {
      // resourceId is not important in system type credential, you can use anything you like
      String dummyResourceId = com.bea.netuix.util.PortalFrameworkUtils.getUniquePortletDesktopString(request);
      // this case use enterprise scope, so all portal web can see this entry, but not another enterpise app target to external users.
      ResourceKey rc = new ResourceKey(Scope.getApplicationScope(), dummyResourceId);
      cvs.removeCredentialEntry(entryName, EntryType.SYSTEM_TYPE, rc);
   }
}

The EmailAccountBacking file shows an example of the portlet logic needed get and update an entry in a User (USER_TYPE) Credential Vault. For more information about backing files, see "Backing Files" in the Oracle Fusion Middleware Portlet Development Guide for Oracle WebLogic Portal.

Example 5-2 EmailAccountBacking File

package examples.credential;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.bea.netuix.servlets.controls.content.backing.AbstractJspBacking;
import com.bea.netuix.servlets.controls.portlet.backing.PortletBackingContext;
import com.bea.netuix.servlets.controls.window.WindowCapabilities;
import com.bea.p13n.security.management.credentials.AlreadyExistsException;
import com.bea.p13n.security.management.credentials.CredentialEntry;
import com.bea.p13n.security.management.credentials.UserPasswordCredential;
public class EmailAccountBacking extends AbstractJspBacking {
   private static final long serialVersionUID = -4933113295375846721L;
   
   private CredentialEntry entry;
   
   @Override
   public boolean handlePostbackData(HttpServletRequest request, HttpServletResponse response)
   {
      // retrieve credential entry from vault
      entry = CredentialHelper.getCredentialEntryForPortletInstance("emailAccount", request);
      
      if ( isRequestTargeted(request) )
      {
         // get submitted parameters if transit from config page
         String server = request.getParameter("server");
         String protocol = request.getParameter("protocol");
         String username = request.getParameter("username");
         String password = request.getParameter("password");
         if ( username != null && password != null)
         {
            if ( entry == null )
            {
               // create a new credential entry if not already exists
               try
               {
                  entry = CredentialHelper.createCredentialEntryForPortletInstance("emailAccount", request);
               }
               catch (AlreadyExistsException e)
               {
                  e.printStackTrace();
               }
            }
            // reset or update credential and/or properties
            try
            {
               entry.setCredential(new UserPasswordCredential(username, password.getBytes("UTF-8")));
               entry.setAttribute("server", server);
               entry.setAttribute("protocol", protocol);
            }
            catch (Exception e)
            {
               e.printStackTrace();
            }
         }
         else if (request.getParameter("delete") != null)
         {
            // delete the credential and move back to config page
            CredentialHelper.removeCredentialEntryForPortletInstance("emailAccount", request);
            PortletBackingContext.getPortletBackingContext(request).setupModeChangeEvent(WindowCapabilities.EDIT.getName());
            return true;
         }
         return false;
      }
      
      if ( entry == null )
      {
         // no credential has been set, switch to config page 
         PortletBackingContext.getPortletBackingContext(request).setupModeChangeEvent(WindowCapabilities.EDIT.getName());
         return true;
      }
      else if ( ! WindowCapabilities.VIEW.equals(PortletBackingContext.getPortletBackingContext(request).getWindowMode()) )
      {
         PortletBackingContext.getPortletBackingContext(request).setupModeChangeEvent(WindowCapabilities.VIEW.getName());
         return true;
      }
      
      return false;
   }
   
   @Override
   public boolean preRender(HttpServletRequest request, HttpServletResponse response)
   {
      // show this portlet for only login user
      if ( request.getUserPrincipal() == null )
         return false;
      return true;
   }
}

The index.jsp displays the e-mail account credential entry.

Example 5-3 Credential Vault index.jsp

<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib uri="http://www.bea.com/servers/portal/tags/netuix/render" prefix="render" %>
<%@page import="com.bea.p13n.security.management.credentials.UserPasswordCredential" %>
<%@page import="com.bea.p13n.security.management.credentials.CredentialEntry" %>
<%@page import="examples.credential.CredentialHelper" %>
<%
   CredentialEntry entry = CredentialHelper.getCredentialEntryForPortletInstance("emailAccount", request);
   if (entry == null)
   {
      out.println("Credential not exists. Click edit button on right of portlet title bar to config credential");
   }
   else
   {
      UserPasswordCredential credential = (UserPasswordCredential)entry.getCredential();
%>
Email account for this portlet instance is:
<form method="post" action="<render:windowUrl/>">
<table>
   <tr>
      <td>mail server: </td>
      <td><%=entry.getAttribute("server")%>
   </tr>
   <tr>
      <td>protocol: </td>
      <td><%=entry.getAttribute("protocol")%>
   </tr>
   <tr>
      <td>username: </td>
      <td><%=credential.getPrincipalName()%>
   </tr>
   <tr>
      <td>password: </td>
      <td><%=new String(credential.getPrincipalPassword(), "UTF-8")%>
   </tr>
   <tr>
      <td colspan="2" align="center">
         <input type="hidden" name="delete" value="1">
         <input type="submit" value="delete"/>
      </td>
   </tr>
</table>
</form>
<%
   }
%>

The config.jsp updates the e-mail account credential entry.

Example 5-4 Credential Vault config.jsp

<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib uri="http://www.bea.com/servers/portal/tags/netuix/render" prefix="render" %>
<%@ page import="com.bea.netuix.servlets.controls.window.WindowCapabilities" %>
<form method="post" action="<render:windowUrl windowMode='<%=WindowCapabilities.VIEW.getName()%>'/>">
Note: do not leave field empty, this simple demo does not validate input.<br/>
Otherwise, a NPE exception may appear.
<table>
   <tr>
      <td>mail server: </td>
      <td><input type="text" name="server"/>
   </tr>
   <tr>
      <td>protocol: </td>
      <td><input type="text" name="protocol" />
   </tr>
   <tr>
      <td>username: </td>
      <td><input type="text" name="username" />
   </tr>
   <tr>
      <td>password: </td>
      <td><input type="password" name="password" />
   </tr>
   <tr>
      <td colspan="2" align="center"><input type="submit" value="save"/></td>
   </tr>
</table>
</form>

5.4 Creating or Viewing System Credentials in the Administration Console

The WebLogic Portal Administration Console provides an administrator with the ability to create a system credential vault. A system credential vault is a vault for a global user name and password, as described in Section 5.1.3, "System Credential Vault."

Note:

When creating a system credential vault using the Portal Administration console, you are creating an enterprise application-scoped credential vault whose entries are not visible to a different enterprise application in the same domain.

To view system credentials:

  1. Start the Administration Console.

  2. Choose Configuration & Monitoring > Service Administration.

  3. In the Resource Tree, select Security > Credential Vault.

Figure 5-4 Credential Vault

Description of Figure 5-4 follows
Description of "Figure 5-4 Credential Vault"

  1. To create a new credential, click Create New Credential.

Specify the values specified in Table 5-1.

Table 5-1 System Credentials

Field Description

Credential Name

The name of the system credential

Description

An optional description of the credential

Username

The name of the portal administrator

Password

The password to access the resource.

Password (again)

Confirm the resource password.

Metadata Name and Value Pair.

The name of the metadata and any data needed by the external system, such as URL or directory path.


  1. To enter additional metadata, click Add Another.

  2. Click Save.