Sunday, March 1, 2009

Custom Login Portlet: WebSphere Portal 6.1 vs WebSphere Portal 6

Question
You may want to create a custom Login Portlet if the base portlet is not in the desired format or you would like to add additional checking to the login. This technote will tell you how to accomplish this and how to add user credentials to the credential vault upon login.
Answer
In IBM WebSphere® Portal 6.0.1 and later versions, there is a new portlet service that allows you to log into Portal. This service still takes advantage of the LoginUserAuth in the login process. You can also write your own LoginPortlet and handle any validation or processing before or after the login process.
In the example in this document, we have created a Login Portlet that, after a successful login, adds or saves the login credentials to the credential vault. This behavior can be helpful if later in the portal experience, you have several systems that do not support LTPA SSO but you want to automate the experience of logging in.

To use this service with Rational Application Developer (RAD), you must be sure to add the following to your build path:

wp.auth.cmd.jar
wp.auth.base.jar


You can find these two .jar files in the \base\wp.auth.base\shared\app and \base\wp.auth.cmd\shared\app directories in your WebSphere Portal 6.1 install.

The first portlet service is the following:

com.ibm.portal.portlet.service.login.LoginService


To access this service, you can code similar to the following (this is best done in the "init" method of the portlet):

PortletServiceHome psh;
javax.naming.Context ctx = new javax.naming.InitialContext();
psh = (PortletServiceHome) ctx.lookup(LoginHome.JNDI_NAME);
loginHome = (LoginHome) psh.getPortletService(LoginHome.class);

Then, in your processAction, you can log the user in using code such as:

LoginService loginService = (LoginService) loginHome.getLoginService(request, response);
String userId = request.getParameter(FORM_ID);
String password = request.getParameter(FORM_PASSWORD);
Map contextMap = new HashMap();
contextMap.put(LoginService.DO_RESUME_SESSION_KEY, new Boolean(false));
try {

loginService.login(userId, password.toCharArray(), contextMap, null);

} catch (Exception ex) {

System.err.println("this login failed with = " + ex.getMessage());
ex.printStackTrace();

} finally {

setCredential(request,userId,password);

}

You must also add a login form to the JSP page which has already been done and is in the first portlet provided.

At this point, you would be logged in or not depending on the response from the loginService. Remember that once you call the login service method, the control will not return to your portlet code if the user is logged in because Portal will do a redirect to the proper portal page (unless there is an authentication error or a block).

Next ,we want to add the credential vault handling. Therefore, in the init method, use the following code:

javax.naming.Context ctx = new javax.naming.InitialContext();
PortletServiceHome cvsHome = (PortletServiceHome)ctx.lookup("portletservice/com.ibm.portal.portlet.service.credentialvault.CredentialVaultService");
vaultService = (CredentialVaultService)cvsHome.getPortletService (CredentialVaultService.class);


The setCredential method takes care of actually accessing the credential vault and setting this value. In this example, we are using a Shared User slot. This slot is shared across all portlets to which this user has access and there is one secret per user. The full code for this is in the second version of the portlet

NOTE: In 6.1, the JSP folder cannot match the portlet name and therefore has a "_" in front of the JSP folder name. If you try to use the custom 6.0 portlet on 6.1, it will not work.