Skip to Content

Back to Getting Started With Kapsel

Appendix D: Using SAML with Kapsel

Here are a few terms that are used with SAML.
An identity provider (IdP) maintains a directory of users and provides authentication.
A service provider is the web site or service that is being accessed.
A user is the person who has an account with the identity provider.

When a user starts a Kapsel app that has been configured to use SAML, the SMP or SAP Cloud Platform Mobile Services server will send a request to the app to redirect to the identity provider if it does not have a valid token. Once the identity provider validates the user, a SAML token is returned that grants the application access for a certain length of time. If the SAML token is compromised it is only valid for a limited length of time against a specific application. Multiple applications can use the same identity provider so multiple applications can use the same user name and password, X.509 certificate or perhaps even a biometric like a fingerprint.

For additional details on SAML see the following links.
Enabling Secure Onboarding Using SAML
SAML 101 Video
Enabling Secure Onboarding Using SAML
Authenticate Applications Using SAML 2.0
Default Identity Federation with SAP ID Service

The following sections demonstrate using SAML in a Kapsel app.
Registering using SAML with SAP Cloud Platform Mobile Services
Client Certificates and SAML
Handling Session Timeout
Offline Considerations

Registering using SAML with SAP Cloud Platform Mobile Services

The following steps demonstrate how to configure the Logon example to use SAML as the authentication provider for the application.

  • Using the SAP Cloud Platform Mobile Services cockpit, modify the Security Configuration of the application com.kapsel.gs from Basic to Form.

    Form indicates SAML should be used. The identity provider for the SAP Cloud Platform Mobile Services trial server is

    https://accounts.sap.com/saml2/idp/sso/accounts.sap.com

    and it requests your SAP Community credentials.

  • On the Backend tab, delete the SSO provider and add a new Basic Authentication provider but this time specify the user name and password required to access the OData service.
    https://sapes4.sapdevcenter.com/sap/opu/odata/IWFND/RMTSAMPLEFLIGHT.
  • Modify the context variable in LogonDemo\www\serverContext.js to indicate that SAML should be used by adding.
    "auth": [ {
        "type": "saml2.web.post",
        "config": {
            "saml2.web.post.authchallengeheader.name": "com.sap.cloud.security.login",
            "saml2.web.post.finish.endpoint.uri": "/SAMLAuthLauncher",
            "saml2.web.post.finish.endpoint.redirectparam": "finishEndpointParam"
        }
    } ],
  • Add the settings plugin so that the user name of the authenticated user can be queried.
    cordova plugin add kapsel-plugin-settings --searchpath %KAPSEL_HOME%/plugins
    or 
    cordova plugin add kapsel-plugin-settings --searchpath $KAPSEL_HOME/plugins
  • Modify the index.html file and add the following button.
    <button onclick="sap.Settings.getConfigProperty(function(value) {alert(value)}, errorCallback, 'UserName')">Get User Name</button>
  • Prepare, build and deploy the app with the following command.
    cordova run android
    or
    cordova run ios
    or
    cordova run windows -- --archs=x64

    Note, if the Remember me checkbox is checked, a cookie will be set that will remain valid for three months so the user name and password will not need to be re-entered.

Client Certificates and SAML

Android

If the SAML IdP presents the client with a certificate challenge the following screens will appear to allow the user to register with an installed certificate.

This screen will appear if the user has not configured a PIN or password on their device.

If you do not wish the user to see this screen, handling of client certificate challenges can be disabled by the following setting in the config.xml.

<preference name="SAPKapselHandleX509Challenges" value="false" />

iOS

Note that certificates installed on the system store (Settings > General > Profiles & Device Management) on iOS are not available to the app. For further information see Making Certificates and Keys Available To Your App. One technique to get a certificate into the apps keychain is to use a Mobile Device Management software such as SAP Afaria or Mobile Iron to provision the user certificate into the shared keychain.

Another technique where the certificate is loaded by one app and its keychain is shared with another app is demonstrated in the OAuth section.

If there are no certificates in the shared keychain the certificate dialog will not appear.

If there is only one certificate and the following method is called in the deviceready event, the certificate will be used automatically.

sap.AuthProxy.setAutoSelectCertificateConfig(successCB, errorCB, true);

If there are multiple certificates in the shared keychain the user will be prompted to select one.

Windows

On windows, if you do not wish the app to use a client certificate, remove the Shared User Certificates capability as shown below.

Handling Session Timeout

Note, the following information applies to SP14 and previous versions. In SP15, the Kapsel plugins were updated to automatically handle the expiration of a session.

A session is maintained between the client and the SMP or SAP Cloud Platform Mobile Services server. By default, it times out after 20 minutes of inactivity. See also Authentication and Handling Session Timeout.
When the application starts an attempt is made to refresh the session. This behavior can be disabled via the setting refreshSAMLSessionOnResume which is discussed further in the Offline Considerations.

If the WebView makes a request such as to open a page proxied through the SAP Cloud Platform Mobile Services server and the session has timed out, the WebView is redirected to the IdP to refresh the session. The original requested page is then shown after the redirect.
To simulate this add the following code to index.html.

function logout() {
    updateStatus2("Calling logout");
    var sUrl = "https://" + applicationContext.registrationContext.serverHost + ":" + applicationContext.registrationContext.serverPort + "/mobileservices/sessions/logout";
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.onreadystatechange = function() {
        console.log(xmlhttp.responseText);
        if (xmlhttp.readyState == 4) {
            updateStatus2("Successfully Logged Out");
            console.log("SUCCESS " + xmlhttp.responseText + " " + xmlhttp.status)
        }
    }
    
    xmlhttp.open("POST", sUrl, true);
    xmlhttp.setRequestHeader("Content-Type", "application/json");
    xmlhttp.send();
}

function openProxiedURL() {
    var sUrl = "https://" + applicationContext.registrationContext.serverHost + ":" + applicationContext.registrationContext.serverPort + "/" + appId;
    window.open(sUrl, "_self"); 
}

Then near the bottom of the index.html file add the following two buttons.

<button onclick="logout()">Logout</button>
<button onclick="openProxiedURL()">Open Proxied URL</button>

Modify the config.xml and add the following line which enables the WebView to be navigated to a new URL.

<allow-navigation href="*" />

Deploy and run the modified app. Notice that it is now possible to end the session between the app and the SAP Cloud Platform Mobile Services server by pressing the Logout button. If a request is then made to open a proxied URL, the SAP Cloud Platform Mobile Services server directs the app to the IdP to first get a SAML session. Note, the session between the app and the SAP Cloud Platform Mobile Services server can also be terminated by removing the app from memory.

If the request is made with an XMLHttpRequest or with datajs, extra code is required to detect that the session has expired and needs to be refreshed.
Try pressing Logout and then Read. Notice that an HTML page was returned rather than an ODATA result.

Add the below code to the top of the errorCallback method to handle this case.

function errorCallback(e) {
    if (e.hasOwnProperty("response")) {
        if (e.response.hasOwnProperty("headers")) {
            if (e.response.headers.hasOwnProperty("com.sap.cloud.security.login")) {
                alert("SAML session has expired.  Please retry the operation after the session has been re-established.");
                sap.Logon.performSAMLAuth(function () {}, errorCallback);
                return;
            }
        }
    }

Note, a handler could also be added with the below code. The method mySAMLHandler would be called whenever the app receives a response that includes the com.sap.cloud.security.login header.

function mySAMLHandler(calledURL) {
    //TODO display error, call performSAMLAuth
}

sap.AuthProxy.setSAMLChallengeHandler(function() {}, function() {}, mySAMLHandler, context.auth[0].config);

Offline Considerations

Note, the following information applies to SP14 and previous versions. In SP15, the Kapsel plugins were updated to automatically handle the expiration of a session.

When the application starts an attempt is made to refresh the SAML token. For an offline app that opens when there is no network connectivity this request will fail.

LogonJSView: error sending initial SAML request{"errorCode":-1,"description":"Unknown Error. Details : Unable to resolve host \"hcpms-i826567trial.hanatrial.ondemand.com\": No address associated with hostname."}

To disable this refresh attempt on startup, add the following value to the serverContext.js file.

"refreshSAMLSessionOnResume": "skip",  //skip, always(default)

This indicates that after the initial registration, it is up to the application to renew the SAML session. Before this setting takes effect, you may need to unregister and re-register if a previous registration exists.

Back to Getting Started With Kapsel

To report this post you need to login first.

8 Comments

You must be Logged on to comment or reply to a post.

    1. Daniel Van Leeuwen Post author

      Thanks for the feedback.  I added a link back to the first part of the blog series at the top in addition to the existing one at the bottom.

      Regards,

      Dan van Leeuwen

      (1) 
  1. Edmund Hupf

    Hi,

    Thanks for this blog post .. very helpful hints.

    I was wondering if there is any good tutorial on using oauth with kapsel applications. Is there any blog describing how to implement this?

    Best Regards,

    Edmund Hupf

    (0) 
    1. Daniel Van Leeuwen Post author

      I believe you could change the IDP used by the SAP Cloud Platform Mobile Services server (HCP) but I think the SAP Cloud Platform Mobile Services server is required.
      Regards,

      Dan van Leeuwen

      (0) 
  2. Oscar Espinar Lázaro

    Hello Daniel,

    Thanks for your Kapsel blog, very helpful.

    I have a related issue on HCPms (Mobile Service for Development and Operations into SAP Cloud Platform).

    Is it possible to remove HCPms sessions from the Kapsel App, just in a similar way you do in the function logout() of your sample?

    Trying “logoutPage”: “<path to logout page>” into neo-app.json does not seem to work.

    I’m using SAP Business ByDesign as backend of my Kapsel App. Also provide a Form in order to login into ByD with a specific ByD User. This is working fine, the problem is in the logout. I didn’t fine the way to remove the ByD session created by the form, so even I try to login again, the old session still continue.

    Here is the problem description post (just in case):

    https://blogs.sap.com/2017/03/13/how-to-login-to-an-sap-business-bydesign-system-with-javascript/

    Thanks in advance and regards,

    Óscar Espinar Lázaro

     

    (0) 

Leave a Reply