Setting up single sign-on with MobileFirst 7.0 | HCL Digital Experience
You can set up single sign-on with MobileFirst so users can share a session between a HCL Portal and MobileFirst server.
Before you begin
Both HCL Portal and MobileFirst® servers must be configured to use the same user registry, LTPA keys, and be set with a specified domain for SSO. If you are using the WebSphere® Application Server, go to the WebSphere Application Server documentation.
For more information about system support requirements, see System requirements.
Procedure
-
Run the following configEngine tasks. These
configEngine tasks are available only on
the HCL Portal server. If the MobileFirst server is on WebSphere Application Server, run the following commands
from the WebSphere Integrated Solutions Console. You can use steps B
and C if MobileFirst is on the
same instance as HCL Portal.
-
ConfigEngine.bat configure-single-signon -Ddomain=domain name -DWasRemoteHostName=hostname -DWasSoapPort=port -DWasPassword=password -Dinteroperable=true -DattributePropagation=true -DrequiresSSL=false
- Optional:
ConfigEngine.bat export-ltpakeys-single-signon -DkeyFile=c:\ltpa.txt -DkeyPass=<testpass> -DdmgrFlag=false -DWasRemoteHostName=hostname -DWasSoapPort=port -DWasPassword=password
- Optional:
ConfigEngine.bat import-ltpakeys-single-signon -DkeyFile=c:\ltpa_demo.txt -DkeyPass=<somepassword> -DdmgrFlag=false -DWasRemoteHostName=hostname -DWasSoapPort=port -DWasPassword=password
-
-
To prepare the MobileFirst
server, you must update the MobileFirst WAR to enable
applications to authenticate with the user registry. Update
authenticationConfig.xml in your MobileFirst project. IT is in
MobileFirst
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>
-
Find the
-
Modify the MobileFirst project
WAR by adding two new HTML files to the WAR. The project WAR is in the
/MobileFirst Project/bin
directory. 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" id="j_username" name="j_username" /> <br /> <label for="j_password">Password:</label> <input type="password" id="j_password" name="j_password" /> <br /> <input type="submit" id="login" 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.
-
Create a login.html file with the following
contents:
-
Modify the MobileFirst project
WAR that was updated in the previous step by editing the
web.xml file 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 MobileFirst project WAR:
<security-constraint id="SecurityConstraint_1"> <web-resource-collection id="WebResourceCollection_1"> <web-resource-name>mobilefirst</web-resource-name> <description>Protecting mobilefirst application</description> <url-pattern>/*</url-pattern> <http-method>GET</http-method> <http-method>POST</http-method> </web-resource-collection> <auth-constraint id="AuthConstraint_1"> <description>MobileFirst applications</description> <role-name>Administrator</role-name> </auth-constraint> <user-data-constraint id="UserDataConstraint_1"> <transport-guarantee>NONE</transport-guarantee> </user-data-constraint> </security-constraint> <security-role id="SecurityRole_1"> <description>Only specific users</description> <role-name>Administrator</role-name> </security-role>
- When the MobileFirst project WAR is updated, deploy it to the MobileFirst server.
- Restart the server where MobileFirst is installed. If you added the security constraint, map the group or user to the EAR file.
- Update the application-descriptor.xml file to add the security tests you configured. Open MobileFirst Project/apps/mobilefirst 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 that is called WASLTPARealmTests in the Common (optional) section.
- In Android phones and tablets > Details, add the Security test called mobileTests.
-
After you create the server-side WAR, change the client side to allow
authentication between the two servers. In a demonstration application, modify
the HTML of MobileFirst
Project/apps/mobilefirst app/common/index.html to
include a log in form and JavaScript to handle the response. In a demonstration,
index.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 id="content" style="display: none"> <div id="AppBody"> <div class="wrapper"> </div> </div> <div id="AuthBody" style="display: none"> <div id="loginForm"> Username:<br/> <input type="text" id="usernameInputField" autocorrect="off" autocapitalize="off" /><br /> Password:<br/> <input type="password" id="passwordInputField" autocorrect="off" autocapitalize="off"/><br/> <input type="button" id="loginButton" value="Login" /> <input type="button" id="cancelButton" 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 MobileFirst to force the
application to connect to the MobileFirst server on start by
adding
WL.Client.connect();
in MobileFirst Project/apps/mobilefirst app/common/js/main.js. -
Add JavaScript to handle the response from the MobileFirst and HCL Portal servers. In this SSO
demonstration application, create a file that is called
challengeResponse.js, in MobileFirst
Project/apps/mobilefirst
app/common/js. Add the following example to the
contents of the file. Update the line
goToPortalServer("http://server:port/wps/myportal");
to point to your HCL Portal server./* * Licensed Materials - Property of IBM * 5725-G92 (C) Copyright HCL Technologies Limited 2006, 2012, 2019. 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(); WL.Client.getCookies().then(function (cookies) { busyIndicator.hide(); goToPortalServer("http://server:port/wps/myportal"); }); } }; $('#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); } }
-
Create a Cordova Plugin that adds the token the WebView's cookie store so HCL Portal can receive the LtpaToken
from an Android application.
-
Create a Java file called CookieInjector.java in
MobileFirst
Project/apps/mobilefirst
app/android/native/src/com/mobilefirst
app. Add the following code to it. Replace
mobilefirst app with your app name.
package com.mobilefirst_app; import java.util.List; import org.apache.cordova.CallbackContext; import org.apache.cordova.CordovaArgs; import org.apache.cordova.CordovaPlugin; import org.apache.http.client.CookieStore; import org.apache.http.cookie.Cookie; import org.json.JSONException; import android.webkit.CookieManager; import com.worklight.common.Logger; import com.worklight.wlclient.HttpClientManager; public class CookieInjector extends CordovaPlugin { Logger l = Logger.getInstance(CookieInjector.class.getName()); @Override public boolean execute(String action, CordovaArgs args, CallbackContext callbackContext) throws JSONException { if ("INJECT-COOKIES-TO-WEBVIEW".equals(action)){ l.debug("Started injecting cookies"); CookieStore cookieStore = HttpClientManager.getInstance().getHttpClient().getCookieStore(); List<Cookie> list = cookieStore.getCookies(); for (Cookie cookie : list){ String cookieName = cookie.getName(); l.debug("Found cookie :: " + cookieName); if ("LtpaToken".equals(cookieName)){ l.debug("Found LtpaToken cookie"); CookieManager cookieManager = CookieManager.getInstance(); String cookieValue = cookie.getName() + "=" + cookie.getValue(); cookieManager.setCookie(cookie.getDomain(), cookieValue); break; } l.debug("LtpaToken cookie not found"); } l.debug("Done injecting cookies"); callbackContext.success(); return true; } return false; } }
-
Add the following code to MobileFirst
Project/apps/mobilefirst
app/android/native/res/xml/config.xml before
the closing
</widget>
tag. Replace mobilefirst app with your app name.<feature name="CookieInjector"> <param name="android-package" value="com.mobilefirst_app.CookieInjector" /> </feature>
-
Create a Java file called CookieInjector.java in
MobileFirst
Project/apps/mobilefirst
app/android/native/src/com/mobilefirst
app. Add the following code to it. Replace
mobilefirst app with your app name.
-
Add the following function to MobileFirst
Project/apps/mobilefirst
app/android/apps/mobilefirst app/android/js/main.js.
function goToPortalServer(url) { cordova.exec(function () { location.href = url; }, function () { alert('failure injecting cookies'); }, "CookieInjector", "INJECT-COOKIES-TO-WEBVIEW",[]); }
- Build your MobileFirst application for your MobileFirst server by right-clicking the MobileFirst application and selecting Run As > Build Settings and Deploy Target.
- Select Build the application to work with a different MobileFirst server.
- Add the information for your MobileFirst server to the Server and Context path fields.
- Build your application by right-clicking the MobileFirst application and selecting Run As > Build All Environments.
- Install the MobileFirst application to your MobileFirst server. Open the MobileFirst console at http://server:port/worklightconsole and upload the MobileFirst application by adding it to the Deploy application or adapter field. Your MobileFirst application file can be found in your Eclipse workspace in the bin folder. The MobileFirst application file has the .wlapp extension.