Remember Me with WebSphere Portal

Retain user credentials for portal applications by extending the WebSphere security infrastructure

Provide a better user experience by implementing a "Remember Me" feature in your portal applications using IBM® WebSphere® Portal V5.1 or V6.0. This content is part of the IBM WebSphere Developer Technical Journal.

Ahmed Abbass (aabbass@eg.ibm.com), IT Architect, IBM

Ahmed Abbas is an IT Architect at Cairo Technology Development Center. Through his involvement in lab services, Ahmed has been interested in bridging the gap between the theories behind technology and the practicality of implementations to serve customer business needs. You can reach him at aabbass@eg.ibm.com.



Hamza Darwish, Software Engineer, IBM

Hamza Darwish is a software engineer at Cairo Technology Development Center. He is working on security solutions for Web Sphere Portal projects through customizing the security infrastructure or integration with external security products.



07 November 2007

Also available in Chinese

Introduction

"Remember Me" is a popular feature provided by many Web sites that simplifies the sign in process -- and provides a better user experience -- by challenging a user only once for credentials. When selected by a user upon signing in, this feature enables the browser to "remember" the user's identity on subsequent visits to the site. User credentials remain stored as cookies in the browser until either the cookies expire, or the user signs out of the site.

This article explains how you can realize the Remember Me feature on WebSphere Portal with security enabled, and shows a sample implementation of the steps involved. For your convenience, the complete example is available in the download files included with this article.

This article assumes a good understanding of servlet programming, portlet programming, and WebSphere security,


How Remember Me works

In general terms, there are essentially three parts to the Remember Me process scenario:

  1. Sign in, in which a user enters a user name and password using the login portlet, and selects the Remember Me option to initiate the feature. Figure 1 shows the flow of the Sign in part of the process:

    1. The flow begins when the user enters a user name and password using a custom login portlet, and checks the Remember Me option.
    2. WebSphere Application Server validates these credentials against the user registry. This flow follows the default behavior for WebSphere form-based authentication, where user name and password are included in the request.
    3. If authentication is successful, the application server forwards the request to WebSphere Portal so that the rest of the information can be retrieved from the user profile for authorization and personalization purposes. If authentication is unsuccessful, the user is forwarded to the login page that contains the custom login portlet.
    4. If the Remember Me option was selected upon sign in, the custom login portlet encrypts the user password and stores it along with user name in the corresponding browser cookies. The user is then forwarded to the requested page. If Remember Me was not selected, the portal simply displays requested page.

    In Figure 1, the white boxes on the diagram indicate standard functions performed by IBM WebSphere Application Server or WebSphere Portal. Other boxes represent functions performed by custom components (see the diagram key).

    Figure 1. Sign in and Browsing flow
    Figure 1. Sign in and Browsing flow
  2. Browsing, during which the user requests any URL under the portal, whether it be secured or non-secured, and explores the site. Figure 1 shows the flow of the Browsing part of the process also.

    When you request any page under the portal, a custom developed servlet filter intercepts the request to check whether the user already has a valid authenticated session, or if Remember Me was selected when the user signed in the last time. If either of these is true, the servlet filter forwards the request to the secured portal page that is equivalent to the page requested. For example, if http://myportal/wps/portal/mypage was requested, the user gets forwarded to http://myportal/wps/myportal/mypage.

    If the user had already been authenticated by the application server before (that is, he has a valid authenticated session), then the application server forwards the user credentials to WebSphere Portal. The flow then continues as in the Sign in process.

    On the other hand, if the user does not have a valid, authenticated session, the Remember Me solution overrides the default WebSphere security authentication behavior by delegating control to the custom developed Trust Association Interceptor (TAI) which, in turn, tries to extract user credentials from cookies (created during the Sign in process), in case they exist. If no such cookies exist, the user is forwarded to the portal login page so he can enter his credentials. The flow continues as in the Sign in process.

  3. Sign out, in which the user selects the Sign out option to end the session (Figure 2).

    When logging out, the custom login portlet removes the cookies that were created when the user signed in with the Remember Me option.

    Figure 2. Sign out flow
    Figure 2. Sign out flow

The sample code provided with this article presents the sign in and sign out functions from within the same portlet, but you can implement the two functions in separate portlets, if you wish.


Implementing the feature

As you likely figured out, based on the three-step process described above, there are three custom developed components that enable this solution:

  1. Servlet filter forwards user requests from non-secure to secure portal pages.
  2. Custom Trust Association Interceptor implements the default authentication behavior against a user registry, given a user name and a password. It can also retrieve user credentials from cookies for authentication.
  3. Custom login portlet encrypts the user password and stores it with user name in browser cookies. The same portlet is also responsible for removing these cookies, when the user decides to sign out.

The outstanding components that contribute to this scenario are standard functions of WebSphere Application Server and WebSphere Portal and do not require any custom development.

Table 1. Remember Me components
ComponentDeployable formatProject type
Servlet filterJAR fileJava project
Custom TAIJAR fileJava project
Custom login portlet Portlet WARPortlet project

The sample source for these components, also listed in Table 1, are available in the download file included with this article. You can import this material as project interchange files into your IBM Rational® Application Developer workspace, and explore them as you continue with the next sections, which describe the development of these components.

1. Servlet filter

A servlet filter represents a pluggable point to the container where you can register filters to listen for specific request patterns. Filters enable you to control the request before it reaches its target resource, meaning you can perform any checking or preprocessing required at this phase, modify request attributes, or even, in some circumstances, redirect the request to another resource.

This example uses the server filter to redirect a request to the secured portal zone (/myportal) in these two cases:

  • User is logged in, has a valid authentic session, and tries to access a resource under /portal during this session, avoiding having portal log the user out.
  • User tries to access a resource under /portal with Remember Me enabled.

(The portal default behavior is to log the user out if he tries to access a resource under /portal at any point in time.)

To achieve this, implement the doFilter() method in the javax.servlet.Filter interface. Listing 1 shows a snapshot of doFilter(); the complete implementation is available in the download materials.

Listing 1. Source code of the servlet filter
public void doFilter(ServletRequest request, ServletResponse response,
	FilterChain chain) throws IOException, ServletException {

	HttpServletRequest req = (HttpServletRequest) request;
	HttpServletResponse resp = (HttpServletResponse) response;

	//Retrieve name/pwd from cookies
	//Full implementation of getCookie method is in FilterUtils class available
	//for download
	String name = FilterUtils.getCookie(req, PredefinedConstants.USER_ID);
	String password = FilterUtils.getCookie(req,PredefinedConstants.USER_PASSWORD);

	//Check if the user has an authentic portal session
	//Full implementation of hasSession method is in FilterUtils class available 
	//for download
	boolean hasSession = FilterUtils.hasSession(req);

	//If no credentials sent and no session then just go on
	if ((!hasSession && (name == null || password == null))
			|| req.getRequestURL() == null) {
		if (chain != null)
			chain.doFilter(request, response);
	} else {
		//Redirect to /myportal
		//Constants are defined in PredefinedConstants class available for 
		//download
		String newURL = req.getRequestURL().toString().replaceAll
			(UNSECURED_PORTAL, SECURED_PORTAL);
		resp.sendRedirect(newURL);
	} 
}

The code above assumes that the portal is not configured to give public sessions. Otherwise, the usage of the method FilterUtils.hasSession() would be insufficient to determine whether the user has an authenticated session.

2. Trust Association Interceptor

Trust association interceptors (TAI) represent the extension point to the WebSphere Application Server authentication mechanism, and therefore to WebSphere Portal, which relies on WebSphere Application Server security infrastructure.

Enabling trust association and registering your custom trust association interceptor to WebSphere Application Server delegates the process of authenticating requests that target secured resources to your own authentication logic. Hence, you have the ability to grant valid portal sessions and access to secured resources to requests that WebSphere Application Server can't authenticate with its default authentication mechanism. In this example, for instance, you need to extract the user credentials from the request cookies and use them to authenticate the user against the user registry.

Implementing a TAI is a two step process:

  1. The interceptor is asked if it can authenticate a certain request or not; in this case you check if valid user credentials are sent in request cookies.
  2. If the answer to the first question is yes, the interceptor is trusted and is then asked to provide the user name of the authentic user that issued the request.

In RememberMeTAI.java, you will find two implemented methods that correspond to the two steps above:

  1. isTargetInterceptor(), shown in Listing 2, handles step 1.
  2. getAuthenticatedUsername(), shown in Listing 3, handles step 2.
Listing 2. isTargetInterceptor()
public boolean isTargetInterceptor(HttpServletRequest req)
		throws WebTrustAssociationException {
		
	//This method is invoked when a request to a secured resource is initiated and 
	//there is no session.
	//This interceptor should handle this request if the request has valid cookies 
	//in the header.
		
	//Retrieve name/pwd from cookies
	//Full implementation of getCookie method is in TAIUtils class available 
	//for download
	String name = TAIUtils.getCookie(req,PredefinedConstants.USER_ID);
	String password = TAIUtils.getCookie(req,PredefinedConstants.USER_PASSWORD);
	
	//If no credentials sent, then let portal redirect to the login page
	if(name == null || password == null){
		return false;
	}
		
	//Authenticating user
	//Full implementation of decryptText method is in Cryptography class available 
	//for download
	password = Cryptography.decryptText(password, PredefinedConstants.CIPHER_KEY);

	//Check name/pwd combination in the user registry
	//Make sure you cache the context to avoid performance leaks, I'm leaving it 
	//for simplicity
	InitialContext ctx;
	try {
		ctx = new InitialContext();
		UserRegistry reg = (UserRegistry) ctx.lookup
			(PredefinedConstants.USER_REGISTRY_SERVICE);
		String res = reg.checkPassword(name, password);
		return res != null;
	} catch (Exception e) {
		throw new WebTrustAssociationException(e.getMessage());
	}			
}
Listing 3. getAuthenticatedUsername ()
public String getAuthenticatedUsername(HttpServletRequest req)
		throws WebTrustAssociationUserException {
		
	//If this method is called then this interceptor has verified the cookies and 
	//authenticated the user in isTargetInterceptor method, so we just need to return 
	//the username from the corresponding cookie 
		
	//Full implementation of getCookie method is in TAIUtils class available for 
	//download
	String userName = TAIUtils.getCookie(req, PredefinedConstants.USER_ID);
	if(userName == null)
		throw new WebTrustAssociationUserException("No credentials are sent");
		
	return userName;
}

3. Custom login portlet

With your TAI and servlet filter implemented, the final step is to implement a login portlet with a Remember Me option that lets users select this feature. This portlet project has a single portlet that uses a portal authentication service to login users and render two pages to the user, based on his logged-in status. This scenario illustrates how this project supports the Remember Me feature implementation:

  1. The user opens the portal page for the first time, and login.jsp is rendered in the portlet.
    Figure 3. Login page with Remember Me option
    Figure 3. Login page with Remember Me option
  2. The user enters the credentials, selects the checkbox, and submits the form. The action phase of the portlet invokes the out-of-the-box login portlet behavior through the WebSphere Portal authentication service to log the user in, and then, if Remember Me had been selected, passes the user's credentials to the render phase.
  3. The loggedIn.jsp page is rendered back to the user, which saves the username and encrypted password to the browser cookies, and offers a logout button to clear the cookies.
    Listing 4. Cookies action in loggedIn.jsp
    <%
    
    //Set cookies
    if(renderRequest.getPortletSession().getAttribute(PredefinedConstants.USER_ID, 
    	PortletSession.APPLICATION_SCOPE) != null 
    && renderRequest.getPortletSession().getAttribute(PredefinedConstants.USER_PASSWORD, 
    	PortletSession.APPLICATION_SCOPE) != null){
    	
    	String name = (String)renderRequest.getPortletSession().getAttribute
    (PredefinedConstants.USER_ID, PortletSession.APPLICATION_SCOPE);
    	String password = 
    (String)renderRequest.getPortletSession().getAttribute(PredefinedConstants.USER_PASSWORD,
    PortletSession.APPLICATION_SCOPE);
    	
    	//Encrypt password
    	//Full implementation of encryptText() method is in Cryptography class available 
    	//for download
    	password = Cryptography.encryptText(password, PredefinedConstants.CIPHER_KEY);
    	
    	renderRequest.getPortletSession().removeAttribute(PredefinedConstants.USER_ID,
    PortletSession.APPLICATION_SCOPE);
    	renderRequest.getPortletSession().removeAttribute(PredefinedConstants.USER_
    PASSWORD, PortletSession.APPLICATION_SCOPE);
    
    %>
    	set_cookie ( "<%=PredefinedConstants.USER_ID %>", "<%=name%>", 2100, 01, 15, "/",
    		 "", "" );
    	set_cookie ( "<%=PredefinedConstants.USER_PASSWORD %>", "<%=password%>", 2100, 01,
    		15, "/", "", "" );
    <%
    }
    %>

Be sure to review MyLogInPortlet.java, login.jsp, and loggedIn.jsp in the download material for full implementation details.


Deploying the feature

Now that you have seen the anatomy of each component, you can deploy them.

1. Servlet filter

To deploy the servlet filter to WebSphere Application Server:

  1. Export RememberMeServletFilter project as a JAR file to your <portal installation directory>/shared/app directory.
  2. Export the WebSphere Portal EAR file, wps.ear, according to your network configuration. If you have a cluster environment, the WebSphere Portal EAR must be exported from the WebSphere Application Server Network Deployment machine:
    1. From a command line, change to the <WAS installation directory>/bin directory.
    2. Invoke the wsadmin command to export the wps.ear to a temporary directory (make sure that all commands are entered on one line); this command is for Windows:

      wsadmin.bat -user admin_user_id -password admin_password -c "$AdminApp export wps c:/directory/wps.ear"

      Where:

      • admin_user_id is the administrator's user ID
      • admin_password is the administrator's password.
  3. Create the /wps_expanded subdirectory. Use the EARExpander tool to expand the contents of the exported EAR file (make sure that all commands are entered on one line); this command is for Windows:

    EARExpander.bat -ear c:\directory\wps.ear -operationDir c:\directory\wps_expanded -operation expand

  4. Edit web.xml in wps.ear/wps.war/WEB-INF/web.xml. Add this filter tag before any other filter tags:
    <filter>	
    <filter-name>Portal Filter</filter-name>
    <filter-class> com.ibm.filter.RememberMeFilter</filter-class>
    </filter>
    b.	Add the following filter-mapping tag before any other filter-mapping tags
    <filter-mapping>
           <filter-name>Portal Filter</filter-name>
           <url-pattern>/portal/*</url-pattern>
    </filter-mapping>

    Note that the <filter-class> tag should include the fully qualified name of the filter class above, and that the <url-pattern> tag states which URL pattern this request is interested in.

  5. Delete the original wps.ear file from the directory where you initially exported it.
  6. Use the EARExpander command to collapse the EAR directory back into an EAR file; this command is for Windows:

    EARExpander.bat -ear c:\directory\wps.ear -operationDir c:\directory\wps_expanded -operation collapse

  7. Use the wsadmin command to update the WebSphere Portal EAR file. (If you have a managed cell (with or without a cluster), perform this step on the deployment manager machine.)

    wsadmin.bat -user admin_user_id -password admin_password -c "$AdminApp install /directory/wps.ear {-update -appname wps -nodeployejb}"

    Where:

    • admin_user_id is the administrator's user ID
    • admin_password is the administrator's password
  8. Restart WebSphere Portal. In a cluster configuration, restart the cluster.

2. Custom Trust Association Interceptor

To deploy and register the custom TAI to WebSphere Application Server:

  1. Deploy your custom interceptor to WebSphere Application Server:
    1. Export your RememberMeTAI project as a JAR file.
    2. Copy and paste the JAR file to this local path on the WebSphere Application Server machine:

      <WAS installation directory>/lib/ext

  2. Register TAI to WebSphere Application Server:
    1. Login to the WebSphere Application Server admin console (typically at https://server-ip:9043/admin).
    2. From the left menu, select Security => Global security.
    3. From the Authentication section, select Authentication mechanisms => LTPA.
    4. Select Trust association from the Additional properties
    5. Mark the Enable trust association check box and click OK.
    6. You'll be prompted to save your changes twice, always click Save.
    7. Make sure you're at the page you reached after step d above (or move to it) and click Interceptors.
    8. Select all existing interceptors and click Delete.
    9. Click New to add a new interceptor, and fill in the class name attribute with the fully qualified name of your interceptor class.
    10. Click OK and Save when you're prompted to save your configurations.
  3. Restart WebSphere Application Server and WebSphere Portal.

3. Custom login portlet

To deploy the custom login portlet to WebSphere Portal:

  1. Export the RememberMePortlet project as a WAR file.
  2. Use the WebSphere Portal administration interface to install the WAR file as a portal application.
  3. Add your custom login portlet to portal default login page (wps.login), and remove the default login portlet from this page.
  4. Give anonymous user access to your custom login portlet.

Conclusion

The Remember me feature can be implemented on IBM WebSphere Portal by extending the WebSphere Application Server security infrastructure. The solution described here involves the deployment of a servlet filter, a custom Trust Association Interceptor, and a portlet. By using this combination of customized modules and standard product features, you will be able to show your users that your applications care enough to "remember" them.


Acknowledgements

The authors would like to thank Ahmed El-Maadawy, Hassan Ali, and Mohamed Shaheen for reviewing this article and providing their comments.


Downloads

DescriptionNameSize
Sample portlet projectRememberMePortletProject.zip12 KB
Sample servlet filterRememberMeServletFilter.zip4 KB
Sample TAIRememberMeTAI.zip5 KB

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 WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=266825
ArticleTitle=Remember Me with WebSphere Portal
publish-date=11072007