Set up single sign-on with Worklight
We can set up single sign-on with Worklight so users can share a session between a HCL WebSphere Portal and Worklight server. Both HCL WebSphere Portal and Worklight servers must be configured to use the same user registry, LTPA keys, and be set with a specified domain for SSO.
- From the primary node of the portal evironment, run ConfigEngine tasks.
Execute the last two steps if Worklight is on the same instance as HCL WebSphere Portal.
ConfigEngine.bat configure-single-signon \ -Ddomain=<domain name> \ -DWasRemoteHostName=host \ -DWasSoapPort=port \ -DWasPassword=<password> \ -Dinteroperable=true \ -DattributePropagation=true \ -DrequiresSSL=false ConfigEngine.bat export-ltpakeys-single-signon \ -DkeyFile=c:\ltpa.txt \ -DkeyPass=<testpass> \ -DdmgrFlag=false \ -DWasRemoteHostName=host \ -DWasSoapPort=port \ -DWasPassword=<password> ConfigEngine.bat import-ltpakeys-single-signon \ -DkeyFile=c:\ltpa_demo.txt \ -DkeyPass=<somepassword> \ -DdmgrFlag=false \ -DWasRemoteHostName=host \ -DWasSoapPort=port \ -DWasPassword=<password>
- To enable applications to authenticate with the user registry, update...
Worklight Project/server/conf/authenticationConfig.xml
Find the <securityTests> element and add the mobile and web security tests.
- Find the <securityTests> element and add the mobile and web security tests from the following example.
<mobileSecurityTest name="mobileTests"> <testDeviceId provisioningType="none" /> <testUser realm="WASLTPARealm" /> </mobileSecurityTest> <webSecurityTest name="WASLTPARealmTests"> <testUser realm="WASLTPARealm"/> </webSecurityTest>
- Uncomment the security realm.
<!-- For websphere --> <realm name="WASLTPARealm" loginModule="WASLTPAModule"> <className>com.worklight.core.auth.ext.WebSphereFormBasedAuthenticator</className> <parameter name="login-page" value="/login.html"/> <parameter name="error-page" value="/loginError.html"/> </realm>
- Uncomment the login module for WebSphere.
<!-- For websphere --> <loginModule name="WASLTPAModule"> <className>com.worklight.core.auth.ext.WebSphereLoginModule</className> </loginModule>
- Modify the Worklight project WAR by adding two new HTML files to the WAR.
The project WAR is in...
/Worklight Project/bin
Copy this WAR to another location for editing.
- Create a login.html file with the following contents.
<html> <head> <title>Login</title> </head> <body> <form method="post" action="j_security_check"> <label for="j_username">User name:</label> <input type="text" name="j_username" /> <br /> <label for="j_password">Password:</label> <input type="password" name="j_password" /> <br /> <input type="submit" name="login" value="Log In" /> </form> </body> </html>
- Create a loginError.html file with the following contents.
<html> <head></head> <body> Login Error </body> </html>
- Add the login.html and loginError.html files to the highest level directory of the WAR.
- Modify the Worklight project WAR updated in the previous step by editing web.xml in the WEB-INF directory.
<login-config> <auth-method>FORM</auth-method> <form-login-config> <form-login-page>/login.html</form-login-page> <form-error-page>/loginError.html</form-error-page> </form-login-config> </login-config>
- Optional: Add a security constraint to protect the web resource by modifying web.xml in the updated Worklight project WAR
<security-constraint > <web-resource-collection > <web-resource-name>worklight</web-resource-name> <description>Protecting worklight application</description> <url-pattern>/*</url-pattern> <http-method>GET</http-method> <http-method>POST</http-method> </web-resource-collection> <auth-constraint > <description>Worklight applications</description> <role-name>Administrator</role-name> </auth-constraint> <user-data-constraint > <transport-guarantee>NONE</transport-guarantee> </user-data-constraint> </security-constraint> <security-role > <description>Only specific users</description> <role-name>Administrator</role-name> </security-role>
- When the Worklight project WAR is updated, deploy it to the Worklight server.
- Restart the server where Worklight is installed.
If we added the security constraint, map the group or user to the EAR file.
- Update the application-descriptor.xml file to add the security tests we configured. Edit...
worklight project/apps/worklight app/application-descriptor.xml
...in the design view and update it to have the correct realms and security tests.
- In the main application, add a security test called WASLTPARealmTests in the Common (optional) section.
- In Android phones and tablets > Details, add the Security test called mobileTests.
- Edit...
worklight project/apps/worklight app/application-descriptor.xml
...and add the <securityTests> element.
<securityTests> <mobileSecurityTest name="mobileTests"> <testDeviceId provisioningType="none" /> <testUser realm="WASLTPARealm" /> </mobileSecurityTest> <customSecurityTest name="WASLTPARealmTests"> <test realm="WASLTPARealm" isInternalUserID="true"/> </customSecurityTest> </securityTests>
- Add the example <realm> for WASLTPARealm.
<realm loginModule="WASLTPAModule" name="WASLTPARealm"> <className>com.worklight.core.auth.ext.FormBasedAuthenticator</className> </realm> </realms>
- Add the example <loginModule> for WASLTPAModule.
<loginModule name="WASLTPAModule"> <className>com.worklight.core.auth.ext.NonValidatingLoginModule</className> </loginModule>
- After creating the server-side WAR, change the client side to allow authentication between the two servers.
In an SSO demonstration application, modify the HTML of...
Worklight Project/apps/worklight app/common/hcl294.html
...to include a login form and JavaScript to handle the response. In a demonstration, hcl294.html includes the code in the following example.
<!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <title>index</title> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=0"> <link rel="shortcut icon" href="images/favicon.png"> <link rel="apple-touch-icon" href="images/apple-touch-icon.png"> <link rel="stylesheet" href="css/main.css"> <script>window.$ = window.jQuery = WLJQ;</script> </head> <body style="display: none"> <div > <div class="wrapper"> </div> </div> <div style="display: none"> <div > Username:<br/> <input type="text" autocorrect="off" autocapitalize="off" /> <br /> Password:<br/> <input type="password" autocorrect="off" autocapitalize="off"/> <br/> <input type="button" value="Login" /> <input type="button" value="Cancel" /> </div> </div> <!--application UI goes here--> Hello Worklight <script src="js/initOptions.js"></script> <script src="js/main.js"></script> <script src="js/messages.js"></script> <script src="js/challengeResponse.js"></script> </body> </html>
- Update the initialization options for Worklight to force the application to connect to the Worklight server on startup by changing connectOnStartup from false to true in...
Worklight Project/apps/worklight app/common/js/initOptions.js
- Add JavaScript to handle the response from the Worklight and HCL WebSphere Portal servers.
In this SSO demonstration application, create a file...
Worklight Project/apps/worklight app/common/js/challengeResponse.js
...and add the following example to the file. Be sure to update the following line to point to the HCL WebSphere Portal server...
<code>location.href= "http://server:port/wps/myportal"</code>
/* * Licensed Materials - Property of IBM * 5725-G92 (C) Copyright IBM Corp. 2006, 2012. All Rights Reserved. * US Government Users Restricted Rights - Use, duplication or * disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ var sampleAppRealmChallengeHandler = WL.Client.createChallengeHandler("WASLTPARealm"); var busyIndicator = new WL.BusyIndicator('content', {text: "Loading..."}); sampleAppRealmChallengeHandler.isCustomResponse = function(response) { if (!response || response.responseText === null) { return false; } var indicatorIdx = response.responseText.search('j_security_check'); if (indicatorIdx >= 0){ return true; } return false; }; sampleAppRealmChallengeHandler.handleChallenge = function(response) { busyIndicator.show(); $('#AppBody').hide(); WL.EncryptedCache.open("wpsadmin", true, onReadOpen, onOpenError); }; sampleAppRealmChallengeHandler.submitLoginFormCallback = function(response) { var isLoginFormResponse = sampleAppRealmChallengeHandler.isCustomResponse(response); if (isLoginFormResponse){ sampleAppRealmChallengeHandler.handleChallenge(response); } else { $('#AppBody').show(); $('#AuthBody').hide(); sampleAppRealmChallengeHandler.submitSuccess(); setTimeout(function(){ busyIndicator.hide(); location.href= "http://server:port/wps/myportal"; }, 1000); } }; $('#loginButton').bind('click', function () { busyIndicator.show(); WL.EncryptedCache.write("username", $('#usernameInputField').val(), onWriteSuccess, onWriteFailure); function onWriteSuccess(status){ WL.EncryptedCache.write("password", $('#passwordInputField').val(), onWriteSuccess2, onWriteFailure); function onWriteSuccess2(status2){ WL.EncryptedCache.close(onCloseCompleteHandler, onCloseFailureHandler); } } function onWriteFailure(status){ alert("Encrypted cache closed, writing failed"); } }); function onCloseCompleteHandler(status){ var reqURL = '/j_security_check'; var options = {}; options.parameters = { j_username : $('#usernameInputField').val(), j_password : $('#passwordInputField').val() }; options.headers = {}; sampleAppRealmChallengeHandler.submitLoginForm(reqURL, options, sampleAppRealmChallengeHandler.submitLoginFormCallback); } function onCloseFailureHandler(status){ alert("close faiure"); } $('#cancelButton').bind('click', function () { sampleAppRealmChallengeHandler.submitFailure(); $('#AppBody').show(); $('#AuthBody').hide(); }); function onReadOpen(status){ WL.EncryptedCache.read("username", onDecryptReadSuccess, onDecryptReadFailure); function onDecryptReadSuccess(value){ WL.EncryptedCache.read("password", onDecryptReadSuccess2, onDecryptReadFailure); function onDecryptReadSuccess2(value2){ if (value && value2){ // submit 1 & 2 var reqURL = '/j_security_check'; var options = {}; options.parameters = { j_username : value, j_password : value2 }; options.headers = {}; sampleAppRealmChallengeHandler.submitLoginForm(reqURL, options, sampleAppRealmChallengeHandler.submitLoginFormCallback); } else { // Didn't find any cached info, ask for login. busyIndicator.hide(); $('#AuthBody').show(); $('#passwordInputField').val(''); } } } function onDecryptReadFailure(status){ alert("Encrypted cache closed, reading failed"); } } function onOpenError(status){ switch(status){ case WL.EncryptedCache.ERROR_KEY_CREATION_IN_PROGRESS: alert("ERROR: KEY CREATION IN PROGRESS"); break; case WL.EncryptedCache.ERROR_LOCAL_STORAGE_NOT_SUPPORTED: alert("ERROR: LOCAL STORAGE NOT SUPPORTED"); break; case WL.EncryptedCache.ERROR_NO_EOC: alert("ERROR: NO EOC"); break; case WL.EncryptedCache.ERROR_COULD_NOT_GENERATE_KEY: alert("ERROR: COULD NOT GENERATE KEY"); break; case WL.EncryptedCache.ERROR_CREDENTIALS_MISMATCH: alert("ERROR: CREDENTIALS MISMATCH"); break; default: alert("AN ERROR HAS OCCURED. STATUS :: " + status); } }
- Build the Worklight application for the Worklight server by right-clicking the Worklight application and selecting Run As > Build Settings and Deploy Target....
- Select Build the application to work with a different Worklight server.
- Add the information for the Worklight server to the Server and Context path fields.
- Build the application by right-clicking the Worklight application and selecting Run As > Build All Environments.
- Install the Worklight application to the Worklight server.
Open the Worklight console at...
http://server:port/worklight/console
...and upload the Worklight application by adding it to the Deploy application or adapter field. Your Worklight application file can be found in the Eclipse workspace in the bin folder. The Worklight application file has the .wlapp extension.