Implementing SSO in a hybrid app with SAML

1
Hi All, I have followed this tutorial to the tee: https://docs.mendix.com/howto/mobile/implement-sso-on-a-hybrid-app-with-mendix-and-saml. I have SAML working on the desktop application.  The hybrid app keeps opening the default login page and does not call the samlLogin function in config.ui.customLoginFn.   I have the cordova in app browser plugin in config.xml as: <plugin name="cordova-plugin-inappbrowser" source="npm" spec="3.0.0" /> Whitelisting is configured:          <access origin="*" />     <allow-navigation href="*://*.mendix.com/*" />     <allow-navigation href="*://*.mendixcloud.com/*" />     <allow-navigation href="*://*.mxapp.io/*" />     <allow-navigation href="about:*" /> Entry.js is:   MxApp.onConfigReady(function(config) {     var samlLogin = function() {         var samlWindow = cordova.InAppBrowser.open(window.mx.remoteUrl + "SSO/", "_blank", "location=no,toolbar=no");         var exitFn = function(){             navigator.app.exitApp();         };         samlWindow.addEventListener("exit", exitFn);         var cb = function(event) {             if (event.url.indexOf(window.mx.remoteUrl) == 0 && event.url.indexOf("SSO") == -1) {                 samlWindow.removeEventListener("loadstop", cb);                 samlWindow.removeEventListener("exit", exitFn);                 samlWindow.executeScript({                     code: "document.cookie;"                 }, function(values) {                     var value = values[0] + ";";                     var token = new RegExp('AUTH_TOKEN=([^;]+);', 'g').exec(value);                     var authPromise = new Promise(function(resolve, reject) {                         if (token && token.length > 1) {                             window.localStorage.setItem("mx-authtoken", token[1]);                             window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fs) {                                 fs.root.getFile(".mx-token", { create: true, exclusive: false }, function (fileEntry) {                                     fileEntry.createWriter(function (fileWriter) {                                         fileWriter.onwriteend = resolve;                                         fileWriter.onerror = reject;                                         fileWriter.write(token[1]);                                     });                                 }, reject);                             }, reject);                         } else {                             resolve();                         }                     });                     var closeWindow = function() {                         samlWindow.close();                         if (window.mx.afterLoginAction) {                             window.mx.afterLoginAction();                         }                     };                     authPromise.then(closeWindow, closeWindow);                 });             };         }         samlWindow.addEventListener("loadstop", cb);     }     config.ui.customLoginFn = samlLogin; });   After adding many log message it appears the samlLogin function is never called and after doing a console.log(JSON.stringify(config)) the ui and customLoginFn is not set:   [INFO:CONSOLE(15)] "onConfigReady:{"appbase":"file:///data/user/0/io.conocophillips.chemtracker01/files/resources/","remotebase":"https://chemicaltracker100-accp.mendixcloud.com/","baseUrl":"file:///data/user/0/io.conocophillips.chemtracker01/files/resources/mxclientsystem/dojo/","async":true,"cacheBust":"636875829434019320","server":{"timeout":30000},"data":{"offlineBackend":{}},"store":{},"session":{"shouldGenerateToken":true,"tokenStore":{}},"ui":{},"offline":true}" Does anyone have any ideas?   
asked
2 answers
3

Ok so finally after some blood, sweat and tears I finally fixed our SAML integration issue on mendix hybrid applications. My issue was 2 fold:

  1. We use a custom guest user login page in which apparently the config.ui.customLoginFn function asigned in entry.js is never called. To solve this I included the following script in our login page through a JavascriptSnippet. Kudos to Remco Snijders for his scripts here 


 

var  mxMobile = {};

mxMobile.enableSamlLogin = function() {
    var register = function(){
        if (window.dojoConfig.ui.customLoginFn && typeof(window.dojoConfig.ui.customLoginFn) == 'function') {
            console.log('enableSamlLogin: config.ui.customLoginFn available');
            window.dojoConfig.ui.customLoginFn();

        } else {
            console.log('enableSamlLogin: config.ui.customLoginFn NOT available');            
        }
    }
    mxMobile.waitForDojoConfig(register);
}

mxMobile.waitFor = function(fnCondition, succesCallback, errorCallBack, timeoutMs, interval) {
    var waitTime = 0;
    var id = setInterval(function() {
        waitTime += interval;
        if (waitTime > timeoutMs) {
            clearInterval(id);
            errorCallBack();
            return;
        }
        if (fnCondition()) {
            clearInterval(id);
            succesCallback();
            return;
        }
    }, interval);
}

mxMobile.waitForDojoConfig = function(fnCallback) {
    mxMobile.waitFor(function() {
        return window.dojoConfig;
    }, function() {
        console.log("enableSamlLogin: dojoConfig available");
        fnCallback();
    }, function() {
        console.log("enableSamlLogin: dojoConfig not created");
    }, 60000, 10);
}

mxMobile.enableSamlLogin();

 

 

  1. The second issue I ran into was a ClassNotFound exception in the current cordova in app browser 3.0.0. and cordova-android 1.7.3 which is included in the current mendix hybrid-app-base which was fixed after I upgraded to 1.7.4. I will also log a ticket on github for them to look at this. If this is not resolved by the time you experience a similar issue do the following to upgrade cordova-android to 1.7.4:
    1. do a “npm run platform:android” as usual.
    2. this will create package.json file in your .\build path.
    3. Edit the above file and change "cordova-android": "7.1.3" to "cordova-android": "7.1.4"
    4. remove/delete the android folder from .\build\platforms path.
    5. “npm run platform:android” again.

 

Hope this helps someone in the future!

                 

 

 

 

answered
0

Schalk,  I implemented this code in our application to get SAML working on mobile for a custom login page as well.  It did resolve the issue with the mobile app and SAML logins are now working.

One question though – in my browser console I am seeing the following error:

HTMLSnippet_widget_HTMLSnippet_0.postCreate
mxui.js?636928216015980052:67 HTMLSnippet_widget_HTMLSnippet_0._setupEvents
mxui.js?636928216015980052:67 HTMLSnippet_widget_HTMLSnippet_0.executeCode
mxui.js?636928216015980052:67 HTMLSnippet_widget_HTMLSnippet_1.postCreate
mxui.js?636928216015980052:67 HTMLSnippet_widget_HTMLSnippet_1._setupEvents
mxui.js?636928216015980052:67 HTMLSnippet_widget_HTMLSnippet_1.executeCode
mxui.js?636928216015980052:67 HTMLSnippet_widget_HTMLSnippet_1.evalJS
mxui.js?636928216015980052:67 JDEAccountSync.AnonymousLogIn.dataView5: fetching object through microflow 'JDEAccountSync.DS_LogIn'
mxui.js?636928216015980052:67 enableSamlLogin: dojoConfig available
mxui.js?636928216015980052:67 TypeError: Cannot read property 'customLoginFn' of undefined
    at register (HTMLSnippet_widget_HTMLSnippet_1.js:5)
    at eval (HTMLSnippet_widget_HTMLSnippet_1.js:38)
    at eval (HTMLSnippet_widget_HTMLSnippet_1.js:27)
HTMLSnippet_widget_HTMLSnippet_1.js:5 Uncaught TypeError: Cannot read property 'customLoginFn' of undefined
    at register (HTMLSnippet_widget_HTMLSnippet_1.js:5)
    at eval (HTMLSnippet_widget_HTMLSnippet_1.js:38)
    at eval (HTMLSnippet_widget_HTMLSnippet_1.js:27)
mxui.js?636928216015980052:67 JDEAccountSync.AnonymousLogIn.dataView5: received 1 objects 
[e]
mxui.js?636928216015980052:67 HTMLSnippet_widget_HTMLSnippet_0.update
mxui.js?636928216015980052:67 HTMLSnippet_widget_HTMLSnippet_0._executeCallback from update
mxui.js?636928216015980052:67 HTMLSnippet_widget_HTMLSnippet_1.update
mxui.js?636928216015980052:67 HTMLSnippet_widget_HTMLSnippet_1._executeCallback from update

From my interpretation, the window.dojoconfig object is created and the enableSAMLLogin function is called, but when it tries to evaluate the

if (window.dojoConfig.ui.customLoginFn && typeof(window.dojoConfig.ui.customLoginFn) == 'function')

test, it fails.  Are you also seeing this on your custom login page?

answered