Technical Articles
Step by Step with the SAP Cloud Platform SDK for Android — Part 10 — SAML and OAuth
Previous (Configuration Provider and the Discovery Service) Home Next (Trace Client Network Requests)
The SDK provides multiple methods to authenticate the application such as Basic, certificate, SAML and OAuth with the SAP Cloud Platform Mobile Services. This blog post will demonstrate how to modify the app to use SAML and then OAuth.
One of the benefits of these approaches is that the application does not deal directly with a user name and password. The application opens a browser window to the SAP Identity service where the authentication occurs. The application receives a cookie (SAML) or a token for OAuth that is valid for a set duration and which can be revoked.
With OAuth another benefit is that the authentication can be done in Chrome which means that if one application has registered with the server, a second application authenticating to the same server can reuse the stored token. Chrome also has a feature to save credentials.
The following are some additional sources of documentation on SAML and OAuth.
SAML 2.0
OAuth 2.0
Foundation APIs
The below examples will modify the sample to use SAML with the discovery service, then to use OAuth using OAuth2WebViewProcessor and finally to use the OAuth2BrowserProcessor. A second app will be created demonstrating how credentials can be shared between apps using the OAuth2BrowserProcessor.
Using SAML for Authentication
Using OAuth for Authentication
OAuth with OAuth2BrowserProcessor
Using SAML for Authentication
- Modify the app to use SAML.
- In the onRegister method, replace the new OkHttpClient.Builder() line (5 lines or so) with the below code.
SamlConfiguration samlConfiguration = new SamlConfiguration.Builder() .authUrl(serviceURL + "/SAMLAuthLauncher") .build(); myOkHttpClient = new OkHttpClient.Builder() .addInterceptor(new AppHeadersInterceptor(appID, deviceID, "1.0")) .addInterceptor(new SamlInterceptor(new SamlWebViewProcessor(samlConfiguration))) .cookieJar(new WebkitCookieJar()) .build();
- Uninstall the app and then run it. The authentication page from the SAP Identity service is shown in an HTML page being shown by the WebView component of the app.
Notice that the SAP ID service has an option to Remember me which if checked will persist a cookie for 3 months or until the user logs off, so the credentials will not need to be entered during that time.
Using OAuth for Authentication
- Modify the app to use OAuth.
- Unpublish and then publish the app to the Discovery Service. Add the following custom values after replacing p1743065160 with your user ID.
{ "serviceURL":"https://hcpms-p1743065160trial.hanatrial.ondemand.com", "appID":"com.sap.stepbystep", "connectionID":"com.sap.edm.sampleservice.v2" }
- Create a class named SAPOAuthTokenStore and replace its contents with the below code.
package com.sap.stepbystep; import android.net.Uri; import com.sap.cloud.mobile.foundation.authentication.OAuth2Token; import com.sap.cloud.mobile.foundation.authentication.OAuth2TokenStore; import com.sap.cloud.mobile.foundation.securestore.SecureKeyValueStore; /** * Singleton class which is used for store of OAuth tokens. The tokens are persisted simple * in the application's secure store. */ public class SAPOAuthTokenStore implements OAuth2TokenStore { SecureKeyValueStore store; public SAPOAuthTokenStore(SecureKeyValueStore secureKeyValueStore) { store = secureKeyValueStore; } @Override public void storeToken(OAuth2Token oAuth2Token, String url) { if (store != null && store.isOpen()) { store.put(this.key(url), oAuth2Token); } } @Override public OAuth2Token getToken(String url) { OAuth2Token token = null; if (store != null && store.isOpen()) { token = (OAuth2Token) store.getSerializable(key(url)); } return token; } @Override public void deleteToken(String url) { if (store != null && store.isOpen()) { store.remove(key(url)); } } public void deleteAllTokens() { if (store != null) { String[] keys = store.keys(); for (String key:keys) { store.remove(key); } } } private String key(String url) { return Uri.parse(url).getHost(); } }
- Add the following variable definitions to MainActivity.
private SAPOAuthTokenStore oAuthTokenStore; private String oAuthAuthorizationEndpoint; private String oAuthClientID; private String oAuthRedirectURL; private String oAuthTokenEndpoint;
- Add the below code to the getConfigurationFromDiscoveryService method below the line connectionID = config.getString(“connectionID”);.
oAuthAuthorizationEndpoint = config.getJSONArray("auth").getJSONObject(0).getJSONObject("config").getString("oauth2.authorizationEndpoint"); oAuthTokenEndpoint = config.getJSONArray("auth").getJSONObject(0).getJSONObject("config").getString("oauth2.tokenEndpoint"); oAuthClientID = config.getJSONArray("auth").getJSONObject(0).getJSONObject("config").getJSONArray("oauth2.clients").getJSONObject(0).getString("clientID"); oAuthRedirectURL = config.getJSONArray("auth").getJSONObject(0).getJSONObject("config").getJSONArray("oauth2.clients").getJSONObject(0).getString("redirectURL");
The values being extracted are shown below using Fiddler which is a tool that can examine network requests.
- Comment or replace the below line in the onCreate method.
//bapStore = new BasicAuthPersistentStore(myStore); oAuthTokenStore = new SAPOAuthTokenStore(myStore);
- In MainActivity.java, in the onUnregister method replace the bapStore.deleteAllCredentials() with the below lines.
oAuthTokenStore.deleteAllTokens(); CookieManager.getInstance().removeAllCookies(null);
- In MainActivity.java, in the logout method, replace the line onRegister(null) in the onResponse callback with the below line.
System.exit(0);
- In the onRegister method, comment out the SamlConfiguration and new OkHttpClient.Builder() lines (7 lines or so) and add the below code.
OAuth2Configuration oAuth2Configuration = new OAuth2Configuration.Builder(getApplicationContext()) .clientId(oAuthClientID) .responseType("code") .authUrl(oAuthAuthorizationEndpoint) .tokenUrl(oAuthTokenEndpoint) .redirectUrl(oAuthRedirectURL) .build(); myOkHttpClient = new OkHttpClient.Builder() .addInterceptor(new OAuth2Interceptor(new OAuth2WebViewProcessor(oAuth2Configuration), oAuthTokenStore)) .addInterceptor(new AppHeadersInterceptor(appID, deviceID, "1.0")) .cookieJar(new WebkitCookieJar()) .build(); ClientProvider.set(myOkHttpClient); //The OAuth flow will use this for requesting the token
- Uninstall the app and then run it. The authentication page from the SAP Identity service is shown in an HTML page being shown by the WebView component of the app.
Notice that the SAP ID service has an option to Remember me which if checked will persist a cookie for 3 months so the credentials will not need to be entered during that time.
The next section presents some additional options for saving credentials as the Remember me checkbox is vendor specific. - It is also possible to configure the validity period for OAuth tokens in the management cockpit and if an authorization screen should be shown or not under the Security feature screen.
- The OAuth token can also be revoked in the SAP Cloud Platform Cockpit (not the Mobile Services cockpit). You may wish to do so if an OAuth token was compromised.
OAuth with OAuth2BrowserProcessor
This example will change the processor from the OAuth2WebViewProcessor to use OAuth2BrowserProcessor and will highlight the additional functionality this provides which includes making use of the Chrome browser’s ability to save credentials, access the System Certificate store and ability to share tokens between apps that are authenticating against the same IDP. Note, not all devices have Chrome installed on them.
- Edit the Security configuration.
Change the protocol from https to the app id (com.sap.stepbystep).
- Unpublish and then publish the app to the Discovery Service. Add the following custom values after replacing p1743065160 with your user ID.
{ "serviceURL":"https://hcpms-p1743065160trial.hanatrial.ondemand.com", "appID":"com.sap.stepbystep", "connectionID":"com.sap.edm.sampleservice.v2" }
- In the onRegister method, change the OAuth processor from OAuth2WebViewProcessor to OAuth2BrowserProcessor.
- Uninstall and then run the app.Authentication screen shown using the OAuth2BrowserProcessor.
Notice the user is presented with an option to save the entered credentials.
In the example above, the authorization screen is shown because the Skip Consent Screen option in the cockpit was left unchecked. If this screen is not shown, the question Do you want Google Chrome to save your password for this site is not displayed long enough for the user to click on the Save button.The saved passwords can be configured via the Chrome’s Settings, Save passwords menu.
OAuth tokens can be cleared via the Unregister button in the app followed by clearing the cookies in Chrome’s Settings, Privacy, Clear browsing data menu as shown below.
- If the device or emulator is provisioned with an X.509 certificate, it can also be used instead of entering a user name and password for authentication.
- If an another app was created, perhaps using the SAP Wizard after modifying it to use the OAuth2BrowserProcessor the app can be started without the need to authenticate. It requires adding the following entry to the second app’s AndroidManifest.xml.
<activity android:name="com.sap.cloud.mobile.foundation.authentication.OAuth2RedirectActivity"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="com.sap.someotherapp" /> </intent-filter> </activity>
This can improve the user experience when a user makes uses of multiple apps using the same IDP daily.
Previous (Configuration Provider and the Discovery Service) Home Next (Trace Client Network Requests)
Hi Team,
How to custom registration using saml authentication?.Please provide some code snippet.
Regards
Ramakrishna.Amathi
I would recommend providing a few more details regarding the custom registration and asking this as a question using the SAP Cloud Platform SDK for Android tag (https://answers.sap.com/tags/73555000100800001281).
Regards,
Dan van Leeuwen
Hi Daniel,
Yes i am using SAP Cloud Platform SDK for Android.
I have already implemented basic authentication for custom registration of the android app with SCP. Now I want to understand how to authenticate using SAML for custom registration (without webview).
Regards
Ramakrishna. Amathi
I believe this question is now being discussed at https://answers.sap.com/questions/12630403/custom-login-screen-with-saml-sap-cloud-platform-s.html.