Skip to Content

Back to Getting Started With Kapsel

Appendix F: Using OAuth with Kapsel

With OAuth and SAML, the application does not itself request your user name and password but redirects to a service such as SAP Cloud Identity (or for more info Identity Authentication) which does. The application does not receive your credentials but an access token which is valid for a specified period and which can be revoked. In theory, multiple different applications would use this service to authenticate users and limit what they are authorized to do. In this scenario, one common user name and password could be used across multiple applications which simplifies things for the user.

The following are some additional links on OAuth.
Configuring OAuth Authentication
OAuth2 and Google
https://www.youtube.com/watch?v=YLHyeSuBspI
https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2
Configuring OAuth Authentication
Protecting Applications with OAuth 2.0
Modernizing OAuth interactions in Native Apps for Better Usability and Security

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

Registering using OAuth with SAP Cloud Platform Mobile Services

The following steps demonstrate how to configure the Logon example to use OAuth 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 OAuth.

    Note the access token value can be very short such as 1 minute as it is used to set up an SAP Cloud Platform Mobile Services session which by default lasts 20 minutes. The refresh token lifetime value can be much longer. The user will need to re-enter and authorize once this lifetime value expires.
  • Edit the destination for the app and set the SSO Mechanism to be Basic Authentication and specify 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 OAuth should be used. Note the values below such as such as authorizationEndpoint, tokenEndpoint and clientID can be copied from the SAP Cloud Platform Mobile Services cockpit.
    "auth": [{
        "type": "oauth2",
        "config": {
            "oauth2.authorizationEndpoint": "https://oauthasservices-i82xxxxtrial.hanatrial.ondemand.com/oauth2/api/v1/authorize",
            "oauth2.tokenEndpoint": "https://oauthasservices-i82xxxxtrial.hanatrial.ondemand.com/oauth2/api/v1/token",
            "oauth2.clientID": "4b908018-bdf5-40c5-bed2-a9e472a658ef",
            "oauth2.grantType": "authorization_code"
        }
    }],
    "communicatorId": "REST",  //required for OAuth registration
    
  • 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>

    In a SAML or OAuth registration, the user field returned from the registrationContext is empty so this is an alternative way for your application to know the currently registered user.

  • 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.

    Note this screen can be hidden by checking the Skip Consent Screen checkbox in the Edit OAuth Client screen shown previously.

    The consent screen can be customized in the SAP Cloud Platform.

  • Also note that it is possible to revoke access to a previously granted Access Token.

Client Certificates and OAuth

Android

If the client is presented 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 is to use a Mobile Device Management (MDM) software such as SAP Afaria or Mobile Iron to provision the user certificate into the app keychain or a shared keychain.

In SP16 there is a new plugin named kapsel-plugin-keychaincertprovider that enables a certificate that has been renamed to have a .fccert extension that is clicked on to open the Kapsel app and add the certificate to the apps keychain. The following is a quick demonstration.

  • Add the keychaincertprovider plugin.
    cordova plugin add kapsel-plugin-keychaincertprovider --searchpath %KAPSEL_HOME%/plugins
    on a Mac
    cordova plugin add kapsel-plugin-keychaincertprovider --searchpath $KAPSEL_HOME/plugins
    
  • Rename a client certificate to have an extension of fccert (configurable in the plugin’s xml file) and on the device, open it. A few ways to do this would be to open a web page that has a link to the certificate or email it.
  • When the link is clicked on, it will open the application and import the certificate into the applications keychain.
  • Close and reopen the app. Notice that this time, the certificate is available to be used for the registration.
  • Note, if multiple apps are installed on the device that need access to the client certificate, the certificate can be imported into one app that the other apps enable keychain sharing with.
  • 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);

    This setting is also available in the config.xml as of SP 15.

    <preference name="SAPAutoSelectSingleCertificate" value="true" />
    

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 SAP Cloud Platform Mobile Services or SMP 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 refreshOAUTHSessionOnResume 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 HTTP result is 400 Bad Request and the response contains the below header.

OAuthCheckOnServer: Bearer token for OAuth is missing

This differs from a SAML response in which a redirect is part of the response.
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 refreshSessionSuccessCallback() {
     updateStatus2("Session refreshed");
}

function refreshOAuthSession() {
    updateStatus2("Calling refreshSession");
    sap.Logon.refreshSession(refreshSessionSuccessCallback, logonErrorCallback);
}

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

<button onclick="logout()">Logout</button>
<button onclick="refreshOAuthSession()">Refresh Session</button>

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 read request is made after the session has been terminated, the SAP Cloud Platform Mobile Services server responds with a 400 Bad Request error. Note, the session between the app and the SAP Cloud Platform Mobile Services server can also be terminated by removing the app from memory.

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("OAuthCheckOnServer")) {
            if (e.response.headers.hasOwnProperty("X-SMP-AUTHENTICATION-STATUS-MESSAGE") && e.response.headers["X-SMP-AUTHENTICATION-STATUS-MESSAGE"] == "Bearer token for OAuth2 is missing") {
                alert("OAuth session has expired.  Please retry the operation after the session has been re-established.");
                sap.Logon.refreshSession(refreshSessionSuccessCallback, errorCallback);
                return;
            }
        }
    }
    ...

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 token. For an offline app that opens when there is no network connectivity this request will fail.
To disable this refresh attempt on startup add the following value to the serverContext.js file.

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

This indicates that after the initial registration, it is up to the application to renew the OAuth session by calling sap.Logon.refreshSession method before sending the first server request. In order for this setting to take effect, you may need to unregister and re-register if a previous registration exists.

A Sample OAuth Flow

When a Kapsel secured by OAuth starts, a request is made to the following URL.

https://oauthasservices-XXXXXXXtrial.hanatrial.ondemand.com/oauth2/api/v1/authorize?response_type=code&client_id=1d04af3b-8a72-4cd6-9737-143d97d13b3c

Notice that the client_id parameter is passed.
The response contains a redirct to the below URL which will prompt the user to either provide an X.509 certificate or provide their user name and password.

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

After valid credentials are provided the below URL will ask the user to authorize the application to access the SAP Cloud Platform Mobile Services server.

GET https://oauthasservices-XXXXXXXtrial.hanatrial.ondemand.com/oauth2/api/v1/authorize?response_type=code&client_id=1d04af3b-8a72-4cd6-9737-143d97d13b3c

A post is made to the below URL and the response contains an access token, a refresh token and the time that the access token is valid for.

https://oauthasservices-XXXXXXXtrial.hanatrial.ondemand.com/oauth2/api/v1/token
{"access_token":"4beca7d4bcdd7fe847c5b9932134328a","token_type":"Bearer","expires_in":0,"refresh_token":"3236d71f6e28733398f54d4cc53c4a8e","scopes":[""],"scope":""}

Next a request is made to generate an authorization code.

https://oauthasservices-XXXXXXXtrial.hanatrial.ondemand.com/oauth2/generate_authz_code
302 Found
Location: https://oauthasservices-XXXXXXXtrial.hanatrial.ondemand.com?code=8f974df5-fbe4-3b34-b03e-5389208eb40c 

Finally, the application will make a POST request against the SAP Cloud Platform Mobile Services server and will include the access code.

https://oauthasservices-XXXXXXXtrial.hanatrial.ondemand.com/oauth2/api/v1/token
grant_type=authorization_code&client_id=1d04af3b-8a72-4cd6-9737-143d97d13b3c&code=8f974df5-fbe4-3b34-b03e-5389208eb40c

Back to Getting Started With Kapsel

To report this post you need to login first.

1 Comment

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

  1. Former Member

    Hey Daniel. Thank you for a great guide. Do you know how to enable OAuth when using the “Fiori Mobile” -> Build Packaged App option from the Full stack WebIde?

    (0) 

Leave a Reply