10 Developing Mobile Services Applications with the Android Client SDK

This chapter describes how to develop Mobile Services applications with the Android Client SDK. This SDK serves as a security layer for developing secure mobile applications on Android devices. It essentially simplifies the development of the applications by taking control of authentication, authorization, user profile services and secure storage. The minimum Android version supported by the Mobile and Social Android Client SDK is Android 2.2. This chapter provides the following sections:

10.1 Getting Started With the Android Client SDK

This SDK (oamms_sdk_for_android.zip) is included in the Oracle Access Management distribution package and can also be downloaded from the Oracle Technical Network (OTN) website.

In addition to this Developer's Guide, API documentation in HTML format is provided in the SDK. Refer to the API documentation for descriptions of API classes, interfaces, constructors, methods, and fields.

The Mobile Android Client SDK is provided as a library project. It contains four modules:

  • Authentication Module - Processes authentication requests on behalf of users, devices, and applications.

  • User Role Module - Provides User Profile Services that allow users and applications to get User and Group details from a configured Identity store.

  • REST Handler Module - Provides access to REST web services and automatic injection of tokens for Access Manager protected REST web services.

  • Cryptography Module - Provides simplified APIs to perform cryptography tasks like hashing, encryption, and decryption.

  • Secure Storage Module - Provides APIs to store and retrieve sensitive data using the preferences storage of Android.

Important:

The minimum Android version supported by the Mobile and Social Android Client SDK is Android 2.2.

10.1.1 Developing and Packaging Android Applications

Review the following notes prior to developing and packaging Android applications.

Import the Library Project Into Your Workspace

The oamms_sdk_for_android.zip archive contains an IDMMobileSDK folder. The IDMMobileSDK folder is a library project.

To import the library project into your workspace in Eclipse, choose File > Import > Existing projects into workspace.

Point Your Application to the Library

In Eclipse, choose Project > Properties > Android > Library and add a reference to the library project.

Add Permission Statements Before Compiling

Before compiling your application, add the following <uses-permission> statements to the application consuming Mobile and Social services. Add the statements to the AndroidManifest.xml file. Your application must include these statements, otherwise it will crash.

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

For more information about requesting permissions, see the Android Developer documentation:

http://developer.android.com/index.html

10.2 Invoking Authentication Services With the Android Client SDK

This section provides sample code that demonstrates how to authenticate with the Mobile and Social server. Refer to "Configuring Mobile Services" in Oracle Fusion Middleware Administrator's Guide for Oracle Access Management for information about configuring the Mobile and Social server.

Step 1: Initialize Required Objects and Declare the Endpoints

Create an object of OMMobileSecurityService as follows by providing the required Mobile and Social server details.

Note:

If your apps will authenticate against a single OAM server or a single ServiceDomain, there should be only one instance of the OMMobileSecurityService object throughout the application life cycle. This is required to maintain one valid session with the server at a time, and also to support the single sign-on feature.

To maintain one instance of OMMobileSecurityService throughout the application life cycle, either extend the Application class in the Android SDK, or create a custom static singleton class.

Refer to the Android documentation for information about extending the Application class:

http://developer.android.com/reference/android/app/Application.html

If your apps will authenticate against different OAM servers, or with the same OAM server but different authentication schemes, then one OMMobileSecurityService instance should be created for every server or authentication scheme. For example, if the same app authenticates against OAM server and against Facebook for different use cases, then create separate instances of OMMobileSecurityService to handle both use cases. On the OAM server, configure one ServiceDomain with a "Mobile Service Authentication" authentication scheme, and configure the other with an "Internet Identity Authentication" authentication scheme.

OMMobileSecurityService mss = OMMobileSecurityService(context, serverUrl, applicationId, serviceDomain, callback);

The context argument is the context of the Application object. Pass the context that is returned by Context#getApplicationContext().

Note:

See the following URL for more information about the getApplicationContext() method:

http://developer.android.com/reference/android/content/Context.html#getApplicationContext()

Do not pass an Activity reference because the OMMobileSecurityService instance exists throughout the application life cycle and if the OMMobileSecurityService instance has a reference to an Activity, it could lead to a memory leak.

The serverUrl argument is the URL (including protocol, host name, and port number) required to reach the Mobile and Social server. Only the HTTP and HTTPS protocols are supported.

The applicationId argument is a unique identifier that identifies the application. This String value must match the application "Name" value located in the Application Profile section of the Mobile and Social server administration console. For more information, see "Defining Application Profiles" in the Oracle Fusion Middleware Administrator's Guide for Oracle Access Management.

The serviceDomain argument specifies the name of the service domain that has been created on the Mobile and Social server. The application profile that the applicationId refers to should be defined as an application profile in this service domain. For more information, see "Defining Service Domains" in the Oracle Fusion Middleware Administrator's Guide for Oracle Access Management.

The callback argument specifies an instance of a class that has implemented the interface OMMobileServiceCallback. The SDK uses this to return control to the application after calling OMMobileSecurityService#setup() and OMMobileSecurityService#authenticate().

Be sure to register the current activity before invoking certain methods in the OMMobileSecurityService, such as setup(), authenticate(), authenticate(String userName, char[] password, OMAuthenticationRequest authRequest, String credentialKey), processSSORequest(Intent intent), and processHttpRequest(Intent intent). Deregister the activity when it is not in the foreground. Do this to ensure that there are no memory leaks. To give the reference to the current activity, register the current activity in onResume() and deregister the activity in onPause() for activities that call the methods mentioned previously. If you call any of these methods in onCreate() of the activity, register the activity before calling these methods. To deregister the activity, when the activity moves to the background, use the OMMobileSecurityService#deregisterActivity() method.

mss.registerActivity(this);

Next, call the OMMobileSecurityService setup method.

mss.setup();

The setup method gets the configured security policies and the application profile from the Mobile and Social server. This method also gets a list of the service endpoints (the URLs) that are required for connecting to the authentication, authorization, and user profile services on the Mobile and Social server.

This is an asynchronous call. When the application profile download completes, or if a problem like network unavailability is encountered, the SDK returns control to the calling activity by calling callback.processSetupResponse(OMApplicationProfile profile, OMMobileSecurityException mse). If the application profile could not be downloaded, the exception details can be found in OMMobileSecurityException mse.

The SDK downloads and stores the application profile. The SDK will not download the application profile on subsequent calls to OMMobileSecurityService#setup() until the ProfileCacheDuration setting has expired. The ProfileCacheDuration setting is defined in the application profile.

Additional Information

The following table lists the standard Application Profile attributes that you define on the Mobile and Social server. The SDK parses and stores these attributes after downloading the Application Profile.

Table 10-1 Configuration Attributes

Attribute Description

Access Service URL

The URL used to obtain access tokens from the Oracle Access Management server.

Allow Offline Authentication

Indicates if offline authentication should be allowed or not.

Android Application Signature

Signature of the Android application.

Claim Attributes

A comma separated string that represents the names of the various attributes that should be collected from the device as part of the identity claims.

Credential Level for Registration of Application

In the context of Mobile Single Sign-on, this specifies whether the business application is to be registered using either a user name / password combination or a user token.

Delete Service URL

The URL used to delete tokens from the Oracle Access Management server.

Mobile Authentication Scheme

Specifies the authentication scheme to use to authenticate the user. The values for this should be from the enum OMAuthenticationScheme.

Offline Authentication Retry Count

The maximum number of times that offline authentication should be tried before sending a failure back to the client.

Participation in SSO

Specifies if the application supports Mobile Single Sign-on.

Profile Cache Duration

The length of time in minutes that the system should cache the application profile.

Registration Service URL

The registration service URL used to register the device.

Relying Party Authentication Mode

Specifies if Internet Identity Authentication should be invoked from inside an embedded webview or from an external browser. Valid values are Embedded or External.

Relying Party Authentication URL

The relying party authentication URL.

Token Validation Service URL

The service URL used to validate tokens.

URL Scheme

Specifies the URL scheme to use for the Internet Identity return URL, for example:

rp://

User Authentication Service URL

The service URL used to authenticate a user against Oracle Access Manager server.

User Profile Service URL

The service URL used to access the user and group information from the configured directory server.


Configure the following attributes in the Mobile and Social administration console under the Custom Settings section of the application profile. For the attribute to be configured, enter the attribute "Name" in the console as it is given in the following table. The attribute values will be downloaded as part of the application profile and the SDK will populate the values internally.

Table 10-2 Attributes Configured in the Console UI

Attribute Description

ConnectionTimeout

The length of time in seconds after which the HTTP connection between the server and the SDK times out.

CryptoScheme

An enum of CryptoScheme that represents how the password will be hashed or encrypted to store for offline authentication. Valid values are SHA-1, SHA-256, SHA-384, SHA-512, SaltedSHA-1, SaltedSHA-256, SaltedSHA-384, SaltedSHA-512, MD2, MD5, AES or DES.

SessionTimeout

The length of time in seconds after which the offline authentication context is deleted.


Step 2: Complete the Authentication Process

Once the setup successfully completes, the business application can perform authentication by calling OMMobileSecurityService#authenticate(). This is an asynchronous call and the SDK will return control to the application once authentication is completed or if authentication has failed for some reason. The control will be returned to the application through OMMobileServiceCallback#processAuthenticationResponse(OMAuthenticationContext context, OMMobileSecurityException mse). All the details with respect to the authenticated session are available in the OMAuthenticationContext context. If authentication fails for some reason, the details are available in OMMobileSecurityException mse.

Set up the page as follows:

View view = mss.authenticate();

setContentView(view);

The authenticate() method will return a ViewFlipper object that holds the processing view. When the view is focused it will trigger the actual authentication flow.

If a valid authentication context is already available in the cache for the above request, then it will return control back to the calling business application without performing any request to the server.

The following sample code demonstrates the processAuthenticationResponse() method:

public void processAuthenticationResponse(OMAuthenticationContext context, OMMobileSecurityException mse)
 
{
    if (context != null)
    {       
        Toast.makeText(getApplicationContext(), "Logged in successfully.", Toast.LENGTH_LONG).show();
    }
    else
    {
        Toast.makeText(getApplicationContext(), "Failure in login due to " + mse.getLocalizedMessage(), Toast.LENGTH_LONG).show();
    }
}

Note:

To customize the login view or the knowledge-based authentication (KBA) view, see "Login View and KBA View Customization" later in this chapter.

10.3 Alternate Approach to Initializing the Android Client SDK

As an alternative to the constructor specified in Section 10.2, you can use the following constructor to initialize the Android Client SDK.

public OMMobileSecurityService(Context context, Map<String, Object> configProperties,OMMobileServiceCallback callback)

This constructor accepts details at the start and initializes the OMMobileSecurityService object using Map<String, Object>. This enables you to specify additional parameters such as OM_PROP_AUTH_KEY, OM_PROP_LOCATION_UPDATE_ENABLED, and OM_PROP_CRYPTO_SCHEME that cannot be specified during initialization using the constructor described previously. These properties are documented in Table 10-3. The same parameters can also be set using setters if you prefer to construct the OMMobileSecurityService object using the constructor described in Section 10.2. The following is an example:

OMMobileSecurityConfiguration mobileSecurityConfiguration = mobileSecurityService.getMobileSecurityConfig();
MobileSecurityConfiguration.setLocationUpdateEnabled(true);

Initialization Sample Code

        Map<String, Object> configProp = new HashMap<String, Object>();
 
          //The following strings should be available in configProperties. 
          //Otherwise, IllegalArgumentException will be thrown
          configProp.put(OMMobileSecurityService.OM_PROP_AUTHSERVER_TYPE, OMMobileSecurityService.AuthServerType.OAMMS);
          configProp.put(OMMobileSecurityService.OM_PROP_OAMMS_SERVICE_DOMAIN, "xyzDomain");
          configProp.put(OMMobileSecurityService.OM_PROP_APPNAME, "ShopCart");
          configProp.put(OMMobileSecurityService.OM_PROP_OAMMS_URL, "http://examplehost.us.example.com:14100");
 
          //This next line is optional. If you do not include it, a default key 
          //is used which is <OAMMS_URL>_<APPNAME>_<SERVICE_DOMAIN>
 
          //configProp.put(OMMobileSecurityService.OM_PROP_AUTH_KEY, "testKey"); 
 
 
          OMMobileSecurityService mss = new OMMobileSecurityService(getApplicationContext(), configProp, callback);
 
          //In the previous line, getApplicationContext() is the context of the
          //calling application, and callback is the instance of a class that has
          //implemented the interface OMMobileServiceCallback.

The following table documents the keys you use to put values in Map<String, Object>.

Table 10-3 Android Client SDK Initialization Properties

Property Name Property Value(s) Type

OM_PROP_AUTHSERVER_TYPE

  • OMMobileSecurityService.AuthServerType.OAMMS

Enum (OMMobileSecurityService.AuthServerType)

OM_PROP_OAMMS_URL

Required property. A String that contains the protocol, host, and port information as follows: <protocol>://<host>:<port>

String

OM_PROP_OAMMS_SERVICE_DOMAIN

Required property. Any valid Service Domain name passed as a String object.

String

OM_PROP_APPNAME

Required property. A valid application name passed as a String object.

String

OM_PROP_AUTH_KEY

The key that must be used to store the OMCredential object in shared preferences.

This is an optional property. If it is not specified, it is stored using the <login_url>_<applicationName>_<serviceDomain> key if all the values are not null. Otherwise, it is stored using <applicationName> alone.

String

OM_PROP_LOCATION_UPDATE_ENABLED

Use this property to enable or disable location updates. If it is enabled, then the SDK will collect location details of the device and send it to the server.

Boolean

OM_PROP_CONNECTIVITY_MODE

Specifies how authentication should happen, specifically whether authentication should be always done online/offline, or if it should happen online/offline depending on network connectivity.

This is an optional property. By default, authentication will happen online/offline depending on network connectivity.

Enum(OMConnectivityMode)


The following OM_PROP_CRYPTO_SCHEME cryptography property is an optional property. If the application requires offline authentication and this property is not specified, the default crypto scheme is SSHA512. This is used to hash / encrypt the password and store it for offline authentication later, if required by the application.

This property can also be set using the Mobile and Social server console. Choose Custom Settings > Mobile Custom Attributes and use the Attribute Name and Attribute Value listed in the last two columns in the table.

For information about the cryptography module included in the Mobile and Social Android Client SDK, see Section 10.11, "Using the Cryptography APIs."

Table 10-4 Cryptography Scheme Property Attributes for the Android Client SDK

Property Name Property enum Values Attribute Name Attribute Value

OM_PROP_CRYPTO_SCHEME

PLAINTEXT("PlainText")

CryptoScheme

PlainText

AES("AES")

AES

SHA1("SHA-1")

SHA-1

SHA224("SHA-224")

SHA-224

SHA256("SHA-256")

SHA-256

SHA384("SHA-384")

SHA-384

SHA512("SHA-512")

SHA-512

SSHA1("SaltedSHA-1")

SaltedSHA-1

SSHA224("SaltedSHA-224")

SaltedSHA-224

SSHA256("SaltedSHA-256")

SaltedSHA-256

SSHA384("SaltedSHA-384")

SaltedSHA-384

SSHA512("SaltedSHA-512")

SaltedSHA-512


10.4 About Offline Authentication

Mobile and Social supports offline authentication.

Specify the way that offline authentication should happen when creating the OMMobileSecurityService object. Use the OM_PROP_CONNECTIVITY_MODE key as documented in Table 10-3. This key accepts the following values:

  • OMConnectivityMode.ONLINE - Always authenticate with the server. Fails if device cannot reach the Internet.

  • OMConnectivityMode.OFFLINE - Authenticates locally with cached credentials. Offline authentication happens even if the device is online and can reach the server.

  • OMConnectivityMode.AUTO - Authentication happens with the server if the server is reachable and happens offline if the device is not connected to the Internet.

You can also set offline authentication after creating the OMMobileSecurityService object using the corresponding setter as shown below:

OMMobileSecurityConfiguration mobileSecurityConfiguration = mobileSecurityService.getMobileSecurityConfig();
mobileSecurityConfiguration.setConnectivityMode(OMConnectivityMode.OFFLINE);

Note:

Offline authentication only works if the "Offline Authentication" setting in the server is set to "Allowed." See "Editing or Deleting an Application Profile" in the Administrator's Guide for Oracle Access Management for more information.

10.5 Invoking Relying Party Authentication Using the Android Client SDK

This section provides sample code that shows how to do Relying Party Authentication with the Mobile and Social Server. Refer to the "Configuring Internet Identity Services" chapter in the Administrator's Guide for Oracle Access Management for information about configuring the Mobile and Social server.

To authenticate using a Relying Party, the data scheme in the main activity of the application should match the URL scheme configured in the Application profile. See the following page for details.

http://developer.android.com/guide/topics/manifest/data-element.html

Call OMMobileSecurityService#authenticate() as usual to authenticate. The SDK will retrieve the necessary settings from the server and authenticate with the Relying Party. Once authenticated, retrieve the authentication context from the mobile security service instance (OMMobileSecurityService#retrieveAuthenticationContext()). The retrieved authentication context object also contains Identity Provider specific information. The authentication context allows you to get the logged in username, the identity provider name, and the access token of the identity provider. Please refer to the SDK documentation for more details.

Note:

Include the following code snippet in the main activity of an app that authenticates against Internet Identity Providers like Facebook, Google, and so on. The main activity is the activity that is defined as the Android Package in the Application Profile settings on the Mobile and Social Server.

The Android Package field should be set to the fully qualified name of the activity in the Android application. The activity should have <data android:scheme="xyz" /> in its <intent-filter> and xyz should be the same as the URL scheme.

@Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState); 
        ...
        Intent intent = getIntent();
        if (intent.getExtras()!= null) 
        {
            try
            {
                mMobileSecurityService.processSSORequest(intent);
            } 
            catch (OMMobileSecurityException e)
            { 
                Log.w(TAG, e.getLocalizedMessage());
            }
        }
        ...
    }

10.6 Invoking the Mobile Single Sign-on Agent App

This section describes how to use the Android Client SDK to interact with a mobile single sign-on agent app. For conceptual information about mobile single sign-on in Mobile and Social, see the "Introducing Mobile Single Sign-on (SSO) Capabilities" and "Understanding Mobile and Social" in Oracle Fusion Middleware Administrator's Guide for Oracle Access Management.

The Sample Mobile SSO Agent App

Mobile and Social provides a sample SSO agent app that illustrates the required logic. You can adapt this logic to any business app and enable the app to function as a mobile SSO agent. The sample Mobile SSO Agent App can be downloaded from the Oracle Technical Network (OTN) website.

Note that the data scheme of the sample Mobile SSO Agent App is "osa". Enter this as the URL Scheme in the Application Profile on the Mobile and Social Server. Essentially, the URL Scheme of the iOS SSO Agent App and the data scheme of Android SSO Agent App should be the same. Finally, when adding the Application Profile to a Service Domain on the Mobile and Social server, configure the Mobile Single Sign-on (SSO) Configuration attributes (Participate in Single Sign-on and Agent Priority).

For more information about configuring SSO on the Mobile and Social server, see "Editing or Deleting the Service Domain" and "Editing or Deleting an Application Profile" in the Administrator's Guide for Oracle Access Management.

For single sign-on to work, enter the Android Application signature of both the SSO Agent app and the SSO Client app in the respective application profiles. The application signature can be obtained programmatically using the following snippet of code that you place inside an activity in your app.

        try
        {
            packageInfo = getPackageManager().getPackageInfo(getApplicationContext().getPackageName(), PackageManager.GET_SIGNATURES);
 
            for (Signature signature : packageInfo.signatures)
            {
                Log.i(TAG, "The signature is : " + signature.toCharsString());
            }
        }
        catch (NameNotFoundException e)
        {
            e.printStackTrace();
        }

If you want to create your own Mobile SSO Agent App, refer to Section 10.9, "Creating a Custom Mobile Single Sign-on Agent App Using the Android Client SDK."

10.6.1 Invoking the Mobile Single Sign-on Agent app from another application(SSO Client)

When applications that are configured as SSO clients make a call to OMMobileSecurityService#authenticate() , the Android Client SDK delegates the request to the SSO Agent application if it is already installed on the device. Otherwise it throws an exception. The Android Client SDK frames the authentication request and invokes the SSO Agent app using an intent.

Note:

If an application (SSO client) needs to authenticate using the SSO Agent App, the main activity has to call OMMobileSecurityService#processSSORequest(intent). This is required because after the SSO Agent app authenticates, it sends details to the main activity of the SSO Client App using some intent. The SDK will appropriately populate its data structures in the SSO Client App with the details present in the intent.

The main activity is the activity configured on the Mobile and Social server as the "Android Package" in the Application Profile.

Refer to the following sample code:

          @Override
          public void onCreate(Bundle savedInstanceState)
          {
              super.onCreate(savedInstanceState);
              …
              …
              Intent intent = getIntent();
              if (intent.getExtras()!= null)
              {
                  try
                  {
                      mMobileSecurityService.processSSORequest(intent);
                  }
                  catch (OMMobileSecurityException e)
                  {
                      Log.w(TAG, e.getLocalizedMessage());
                  }
              }
              …
              …
          }

10.6.2 Invoking the Mobile Single Sign-on Agent App Using a Mobile Browser

Web apps can also use the single sign-on authentication features provided by the mobile SSO agent. This functionality requires Access Manager.

  1. Log on to the Oracle Access Management Administration Console and click the Policy Configuration tab.

  2. Under Shared Components click Authentication Schemes, then click the Create button.

    The "Create Authentication Scheme" tab opens.

  3. Create a new Authentication Scheme by completing the form as follows:

    • Name: MobileSSOScheme

    • Authentication Level: 2

    • Challenge Method: FORM

    • Challenge Redirect URL: /oam/server/

    • Authentication Module: LDAP

    • Challenge URL: /mobilesso?serviceDomain=MobileServiceDomain

      where MobileServiceDomain is the name of the domain that is configured for single sign-on.

    • Context Type: customWar

    • Context Value: /oic_rest

  4. In the Oracle Access Management Administration Console, do the following:

    1. Create a new Authentication Scheme in an Application Domain:

      Authentication Scheme: MobileSSOScheme

      (MobileSSOScheme is the scheme that was created in step one.)

    2. Create an HTTP Resource, for example /protectedRes, and protect the resource using the created Authentication Scheme (MobileSSOScheme). This is the URI that will be accessed from the mobile web browser and protected by a Webgate.

When the protected resource is accessed using a mobile browser, the server will invoke the Mobile SSO Agent App. Because the agent app makes a call to OMMobileSecurityService#processSSORequest(intent) in the onResume() of the main activity, the agent app will delegate the control to the SDK to handle complexities like authenticating, obtaining the OAM_ID token, injecting it, and returning control back to the browser. The browser will now be able to access the protected resource as the required token has been set by the SSO Agent App.

10.7 Invoking User Profile Services With the Android Client SDK User Role Module

This section describes how to use the Android Client SDK to create, read, update, or delete users and groups in a directory server that has been configured to work with Mobile and Social. To configure the Mobile and Social server to work with a directory server, see "Defining, Modifying, or Deleting a User Profile Service Provider" and "Defining, Modifying, and Deleting a User Profile Service Profile" in the Oracle Fusion Middleware Administrator's Guide for Oracle Access Management.

You can configure the User Role module to be used anonymously or only after authentication by adjusting the settings on the Service Protection tab in the Service Domain.

In both cases, you first need to obtain a reference to an instance of OMUserProfileService from the OMMobileSecurityService instance: OMMobileSecurityService#getUserRoleProfileService(OMAuthenticationContext).

The second step is to obtain either an instance of UserManager or RoleManager, depending on the operations to be performed. An instance of UserManager can be used to get User Details, whereas an instance of RoleManager can be used to get Group details from the Identity Store associated with your application's domain on the Mobile and Social server.

  1. Obtain an instance of OMUserProfileService by passing in the AuthenticationContext obtained after successful authentication. You can obtain the authentication context after authentication using OMMobileSecurityService#retrieveAuthenticationContext().

    In the following sample, mMobileSecurityService is an instance of OMMobileSecurityService.

    OMUserRoleProfileService userProfileService = mMobileSecurityService.getUserRoleProfileService(authContext); 
    

    If anonymous access to these services is needed, pass null.

    OMUserRoleProfileService userProfileService = mMobileSecurityService.getUserRoleProfileService(null);
    
  2. Obtain either an instance of UserManager or RoleManger as shown.

    OMUserManager userManager = userProfileService.getUserManager();
     
    OMRoleManager roleManager = userProfileService.getRoleManager();
     
    
  3. The following methods can be invoked using userManager. All these methods interact with the Mobile and Social server over a network, so these methods should be called from a background thread rather than a UI thread.

    public List<OMUser> searchUsers(Map<String, String> searchFilter, List<String> attrsToFetch, int startIndex, int size, boolean isSimpleSearch) throws OMMobileSecurityException
     
    public OMUser searchUser(String userId, List<String> attrsToFetch, boolean shouldPrefetchManager) throws IOException, JSONException, OMMobileSecurityException
     
    public OMUser modifyUser(String uid, String telephoneNumber, String mobile, String mail, String address) throws OMMobileSecurityException
     
    public boolean deleteUser(String userId) throws OMMobileSecurityException
     
     
    public boolean createUser(Map<String, String> attrVals) throws OMMobileSecurityException 
    

    The following methods can be invoked using roleManager. As is the case with methods in OMUserManager, all the methods in OMRoleManager should also be called from a background thread.

    public OMRole getRole(String roleName) throws IOException, JSONException,OMMobileSecurityException
     
    public boolean createRole(Map<String, String> attrVals) throws OMMobileSecurityException
     
    public OMRole modifyRole(String rolename, Map<String, String> attrVals) throws OMMobileSecurityException
     
    public boolean deleteRole(String roleName) throws OMMobileSecurityException
     
    public OMUser getUserFromRole(String userId, String role) throws OMMobileSecurityException
     
    public void addUserToRole(String roleName, Map<String, String> attrVals) throws OMMobileSecurityException
     
    public boolean deleteUserFromRole(String roleName, String userId) throws OMMobileSecurityException 
    

10.8 Invoking REST Web Services

You can use the Mobile and Social SDK to authenticate against Access Manager using the Mobile and Social service. After authenticating against Access Manager, the SDK gets a token and persists it in the cookie store so that any Access Manager protected app can use the embedded Web browser. Access Manager protected REST Web services, however, cannot be accessed using the Web browser.

The Mobile and Social Android Client SDK provides the following method to access REST Web services or any Web resource protected by Access Manager:

OMMobileSecurityService#processHttpRequest(HttpRequest httpRequest)

To access them, however, the user should first authenticate. The Android Client SDK gets access tokens for any given resource using the user token obtained during authentication, provided the resource is protected by an Access Management 11g R2 Webgate.

In the following sample code, if a valid user token is not found for the current application (for example, if the user is not authenticated), the code throws an exception. Because this method contacts the server across the network, execute it in a background thread.

        HttpRequest httpRequest = new HttpGet("http://abc.example.com:7778/index.html");
        // It is important to set the User-Agent to the value configured for
        // "OAMAuthUserAgentPrefix" parameter in OAM 11g R2 Webgate in user defined parameters
        httpRequest.setHeader("User-Agent", "OAMMS-Agent");
        try
        {
            HttpResponse response = mss.processHttpRequest(httpRequest);
            // The developer may extract the useful information from the "response" object
        }
        catch (OMMobileSecurityException mse)
        {
            Log.d("processHttpRequest", mse.getLocalizedMessage());
        }

The OMMobileSecurityService#processHttpRequest(HttpRequest) method can obtain the required token from Access Manager only if the REST Web service is protected using an Oracle Access Management 11g R2 Webgate. The user defined parameter of the Access Management 11g R2 Webgate must contain the OAMAuthUserAgentPrefix property. The same OAMAuthUserAgentPrefix property value must be specified by the mobile application in its header as shown in the sample code.

The following steps describe the internal flow when this method is called:

  1. OMMobileSecurityService#processHttpRequest(HttpRequest) invokes the URL provided by the mobile application.

  2. The Oracle Access Management 11g R2 Webgate returns a 401 error with the following details:

       HTTP/1.1 401 Authorization Required
       WWW-Authenticate: OAM-Auth realm="<WebGateName>:<AuthenticationLevel>
       <RelativeRESTURL>", request-ctx="<RequestContext>"
    
  3. The Mobile and Social SDK maintains a cache of Access Tokens that it has obtained during the application's lifetime. If the Access Token for this Webgate is already present in the cache, the SDK injects the Access Token into the application request.

  4. If an Access Token for the Webgate is not available in the Mobile and Social SDK cache, it sends a REST request to the Mobile and Social server to obtain the Access Token for the Webgate.

  5. If the request is valid, Mobile and Social returns an Access Token in the response.

  6. The Mobile and Social SDK injects the token returned by the Mobile and Social server and accesses the protected URL.

10.9 Creating a Custom Mobile Single Sign-on Agent App Using the Android Client SDK

This section covers how a custom mobile single sign-on (SSO) agent app can be created using the Android Client SDK.

When applications that are configured as SSO clients make a call to OMMobileSecurityService#authenticate(), the Android Client SDK delegates the request to the SSO agent application if it is already installed on the device. Otherwise, it throws an exception. The Android Client SDK frames the authentication request and invokes the SSO agent app using an intent. In order to process the authentication request, the SSO Agent app needs to retrieve this intent and call OMMobileSecurityService#processSSORequest(intent). The SDK internally processes and validates the authentication request and returns control back to the client app with a valid authentication context.

If the OMMobileSecurityService object for the agent application is not initialized using the constructor OMMobileSecurityService(Context context, Intent intent, OMMobileServiceCallback callback), provide the OMCredentialStore object with the details shown in the following code snippet:

OMCredentialStore credentialService = mMobileSecurityService.getCredentialStoreService();
OMMobileSecurityConfiguration cnfg = mMobileSecurityService.getMobileSecurityConfig();
credentialService.putString("sdkInitParams_serverUrl", cnfg.getServerURL().toString());
credentialService.putString("sdkInitParams_serviceDomain", cnfg.getServiceDomain());
credentialService.putString("sdkInitParams_applicationId",appID);
//appID is the application ID string

The following code snippet shows the checks that you should perform in the agent app before processing the client requests.

        @Override
        protected void onResume()
        {
            super.onResume();
            mMobileSecurityService.registerActivity(this);
            if (!(SSOApplication) getApplication().isSetupCompleted())
            {
                mMobileSecurityService.setup();
            }
 
            Intent intent = getIntent();
            if (intent.getData() != null || intent.getExtras() != null)
            {
                try
                {
                    authView = mMobileSecurityService.processSSORequest(intent);
                    if (authView != null)
                    {
                        setContentView(authView);
                        // The developers have full control on how they want to
                        // display this view in their app.
                    }
                }
                catch (OMMobileSecurityException e)
                {
                    Log.w(TAG, e.getErrorMessage());
                }
            }
        }
 

Please note that you can use any design approach. The sample code is included to demonstrate the usage of the SDK.

    class SSOAgentCallback implements OMMobileServiceCallback
    {
        @Override
        public void processSetupResponse(OMApplicationProfile profile,
                OMMobileSecurityException mse)
        {
            if (profile != null)
            {
                // Setup successful you may go for authentication now
                ((SSOApplication) getApplication()).setSetupCompleted(true);
                Toast.makeText(SSOActivity.this, "Setup Done",
                        Toast.LENGTH_SHORT).show();
            }
            else
            {
                Toast.makeText(SSOActivity.this, "Setup failed",
                        Toast.LENGTH_LONG).show();
 
            }
        }
 
        @Override
        public void processAuthenticationResponse(
                OMAuthenticationContext context, OMMobileSecurityException mse)
        {
            /*
             * Handle post authentication in case of SSO self auth request, i.e.
             * when the SSO Agent app calls
             * OMMobileSecurityService#authenticate(). Note: If authentication
             * request comes from a client application , we will not get this
             * call back, as the sdk will redirect to the client app after
             * successful authentication
             */
        }
    }

The agent can have self-authentication logic in the app as shown here:

        @Override
        public void onClick(View v)
        {
            switch (v.getId())
            {
                case R.id.login_button:
                    try
                    {
                        if (!((SSOApplication) getApplication()).isSetupCompleted())
                        {
                            mMobileSecurityService.setup();
                        }
                        authView = mMobileSecurityService.authenticate();
                        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);
                        relLayout.addView(authView,params);
                    }
                    catch (OMMobileSecurityException e)
                    {
                        e.printStackTrace();
                    }
                    break;
                …
                …
            }
        }

10.10 Login View and KBA View Customization

The SDK displays a basic log in view and knowledge-based answer view by default. To create custom user-defined layouts do the following:

  1. The OMMobileSecurityService class provides a method with the following signature:

    public void setCredentialCollector(OMAuthenticationServiceType serviceType, OMCredentialCollector viewHandler)
    

    This method can be used to set a custom view as follows:

    mobileSecurityService.setCredentialCollector(OMAuthenticationServiceType.DEVICE_AUTHENTICATION, new MyLoginView(getApplicationContext()));
    mobileSecurityService.setCredentialCollector(OMAuthenticationServiceType.KBA_AUTHENTICATION, new MyKBAView(getApplicationContext()));
    

    Follow this approach to set custom views for any of the authentication service types supported by OMAuthenticationServiceType.

  2. MyLoginView is a custom class that implements the OMCredentialCollector interface. The custom view to be displayed by the SDK has to be returned from this method:

    OMCredentialCollector#processViewRequest(Map<String, String> inputParams, OMCredentialCollectorCallback callback)

    Write this method to collect a username and password or security answer, then pass these values to the SDK. Put the values in an object of type Map<String, String> and pass the object to the SDK using callback.processLoginResponse(Map<String, String>).

    For Log in View customization, use the following keys for the user name and password values:

    OMSecurityConstants.USERNAME
    OMSecurityConstants.PASSWORD 
    

    For KBA View customization, use the following key for the security answer:

    OMSecurityConstants.ANSWER_STR
    

    If any exception happens in a request, the SDK will populate it in the inputParams map, which is an input parameter to the following method:

    OMCredentialCollector#processViewRequest(Map<String, String> inputParams, OMCredentialCollectorCallback callback)
    

    Design the custom view such that, if the SDK sends an error message, it should be shown in the view. Use the following key to obtain the error message:

    OMSecurityConstants.ERROR_MESSAGE
    

    For the KBA view, the question will be available as part of the inputParams map with the key as follows:

    OMSecurityConstants.QUESTION_STR
     
    

    Define OMCredentialCollector#processViewRequest(Map<String, String> inputParams, OMCredentialCollectorCallback callback) such that it will retrieve the question from the inputParams map and display the question in the view.

    Refer to the following sample code for Log in View customization:

    class MyLoginView implements OMCredentialCollector
    {
        ...
        @Override
        public View processViewRequest(Map<String, String> inputParams, OMCredentialCollectorCallback callback)
        {
            // Create the basic auth view
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            basicAuthView = inflater.inflate(R.layout.mybasicauth, null);
     
            ...
            // You can enable username and password EditText Views, which may be disabled when the log in button is pressed
     
            Button button = (Button) basicAuthView.findViewById(R.id.login);
            button.setOnClickListener(new AuthenticationLoginListener(callback));
     
            Button cancelButton = (Button) basicAuthView.findViewById(R.id.cancel);
            cancelButton.setOnClickListener(new AuthenticationCancelListener(context, callback));
     
            String errorMsg = inputParams.get(ERROR_MESSAGE);
            TextView errorMsgTv = (TextView) basicAuthView.findViewById(R.id.errorMsg);
            if (errorMsg != null && !errorMsg.isEmpty())
            {
                errorMsgTv.setVisibility(View.VISIBLE);
                errorMsgTv.setText(errorMsg);
            }
            else
            {
                errorMsgTv.setVisibility(View.INVISIBLE);
            }
            inputParams.remove(ERROR_MESSAGE);
     
            return basicAuthView;
        }
        //-------------------------------------------------------------------------
        // Inner class which handles the OnClick event
        //-------------------------------------------------------------------------
     
        private class AuthenticationLoginListener implements OnClickListener
        {
            OMCredentialCollectorCallback callback;
     
            AuthenticationLoginListener(OMCredentialCollectorCallback callback)
            {
                this.callback = callback;
            }
     
            @Override
            public void onClick(View v)
            {
                // The developer may show a progress bar and disable the Login and Cancel buttons
                Map<String, String> outputParams = new HashMap<String, String>();
     
                outputParams.put(USERNAME, username);
                outputParams.put(PASSWORD, password);
     
                basicAuthView.invalidate();
     
                callback.processLoginResponse(outputParams);
            }
        }
    }
    // This class is a part of the samples for both Login View and KBA View 
    // Customization
     
    class AuthenticationCancelListener implements OnClickListener
    {
        private OMCredentialCollectorCallback callback;
        private Context context;
     
        AuthenticationCancelListener(Context context, OMCredentialCollectorCallback callback)
        {
            this.context = context;
            this.callback = callback;
        }
     
        @Override
        public void onClick(View view)
        {
            callback.processCancelResponse();
        }
    }
    

    Sample code for KBA View customization has been given below:

    class KBAView implements OMCredentialCollector
    {
        ...
        @Override
        public View processViewRequest(Map<String, String> inputParams,
                OMCredentialCollectorCallback callback)
        {
            // Create the view for KBA
            LayoutInflater inflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
     
            kbaAuthView = inflater.inflate(R.layout.mykbaview, null);
     
            Button button = (Button) kbaAuthView.findViewById(R.id.casubmit);
            button.setOnClickListener(new AuthenticationLoginListener(callback));
     
            Button cancelButton = (Button) kbaAuthView.findViewById(R.id.cacancel);
            cancelButton.setOnClickListener(new AuthenticationCancelListener(
                    context, callback));
     
            TextView question = (TextView) kbaAuthView.findViewById(R.id.cques);
            question.setText(inputParams.get(QUESTION_STR));
     
            return kbaAuthView;
        }
     
        //-------------------------------------------------------------------------
        // Inner class which handles the OnClick event
        //-------------------------------------------------------------------------
     
        private class AuthenticationLoginListener implements OnClickListener
        {
            OMCredentialCollectorCallback callback;
     
            AuthenticationLoginListener(OMCredentialCollectorCallback callback)
            {
                this.callback = callback;
            }
     
            @Override
            public void onClick(View v)
            {
               // You can show a progress bar and disable the submit and 
               // cancel buttons
     
                String answer = chalngAns.getText().toString();
                Map<String, String> outputParams = new HashMap<String, String>();
                outputParams.put(ANSWER_STR, answer);
     
                callback.processLoginResponse(outputParams);
            }
        }
    }
    

10.11 Using the Cryptography APIs

This section covers the cryptography APIs that are exposed by the SDK. The SDK uses these APIs to protect and store credentials for offline authentication. For detailed information about API methods, please refer to the API documentation included in the SDK download.

OMCryptoService is the class that supports all of the features like hashing, encryption, decryption, and matching whose instance can be obtained using OMMobileSecurityService#getCryptoService() as follows:

OMCryptoService cryptoService = mMobileSecurityService.getCryptoService();
 

Following is a high-level summary of the functionality provided by the cryptography API.

Hashing

Use the hashing capability to produce a hash of plain text based on the crypto scheme algorithm. If it is a salted algorithm, then it uses the salt length that is given as input. The last parameter in the API determines whether to prefix the algorithm name.

The output is of the following format:

<Algorithm Name><HashedContent><Salt>

  • The hashed content and salt are Base-64 encoded.

  • The algorithm name will be prefixed only if it is requested.

  • The salt will be present only if the algorithm is a salted algorithm.

cryptoService.hash(plainText, scheme, 10, true);

Symmetric Key Encryption

This API helps perform symmetric key encryption and decryption of data. The key used for encryption is generated automatically and stored in the credential store.

The output of encryption is of the following format:

<scheme/mode/padding> <Initialization Vector><Encrypted text>:

Both the initialization vector and the encrypted text are Base-64 encoded. The initialization vector will be used later for decryption as well.

cryptoService.encrypt(plainText, scheme, msc.getCryptoMode(), msc.getCryptoPadding(), true);

The key for decryption is automatically retrieved from the credential store and the decrypted text is given as output by the following method. The key is generated automatically by the SDK when the encrypt method is called for the first time.

cryptoService.decrypt(encodedText);

Matching of Plain Text and Encrypted/Hashed Text

The following method will check the encoded text given as input and find the oracle.idm.mobile.crypto.CryptoScheme that was used to encrypt or hash it. If it was encrypted, it will decrypt the encoded text and check whether it matches with plain text. It it was hashed, it will perform hashing on the plain text and check whether it matches with the encoded text. Depending on the match, it will return true or false.

cryptoService.match(password, passwordStored, mss.getMobileSecurityConfig().getSaltLength());

10.12 Invoking the CredentialStoreService With the Android Client SDK Secure Storage Module

The SDK CredentialStoreService stores and retrieves sensitive data. Internally, the SDK uses the SharedPreferences class provided in the Android SDK. For more information, see the following Web page:

mMobileSecurityService

Start using CredentialStoreService by getting a reference to an instance of OMCredentialStore using OMMobileSecurityService#getCredentialStoreService(). Once the reference to CredentialStoreService is obtained, credentials can be added, updated, deleted, or read from the Credential Store. Please refer to the SDK documentation for more details.

Following is a sample snippet of code illustrating the usage:

OMCredentialStore credentialStore = mss.getCredentialStoreService();
credentialStore.addCredential("sampleKey", "sampleUsername", "samplePassword", "sampleTenantName", properties);
// properties is a Map<String, String>. This method will convert all the
// parameters like username, password, tenant name and properties into a JSON
// string and store the same in CredentialStore
OMCredential credential = credentialStore.getCredential("sampleKey");
// This method will retrieve the credential information on supplying the correct
// key
        

10.13 Error Codes

This section describes the error codes and messages that are thrown by the Android Client SDK. The error codes and corresponding messages are coded as an enum and exposed as a public API.

Table 10-5 Mobile and Social Android Client SDK Error Codes and Messages

Error Code Description

COULD_NOT_CONNECT_TO_SERVER(1, "Could not establish a connection to the server.")

This exception is thrown when the SDK cannot connect to the server. This may occur because of a URISyntaxException, an IllegalArgumentException, and so on.

CHALLENGE_INVALID(2, "Challenge answer is invalid.")

This exception is thrown when the user does not provide a challenge answer in the case of knowledge-based authentication (KBA).

UN_PWD_INVALID(3, "Username and Password is invalid.")

This exception is thrown when the user does not provide a user name and password in the UI before executing the authentication call with the server, as well as when the response from the server is 401 Unauthorized.

TOKENS_NOT_MATCHED(4, R.string.tokensNoMatch)

This exception is thrown if the required tokens that you requested are not present in the tokens returned by the server.

COULD_NOT_PARSE_RESPONSE_FROM_SERVER(5, "Could not parse the response sent from the server.")

This exception is thrown when the HttpResponse from the server cannot be parsed by the SDK.

DEVICE_NOT_AUTHENTICATED(6, "This device is not yet authenticated with Mobile and Social Server.")

This exception is thrown when the authentication with RestAuthenticationService finds out that the device registration token is not found.

USER_CANCELED_CERTIFICATE(7, R.string.certificateNotAccepted)

This exception is thrown if the untrusted SSL certificate is rejected by the user.

NO_AUTHENTICATION_SCHEME(8, "No authentication scheme is specified.")

This exception is thrown when there is no authentication scheme provided in the mobile security configuration object.

INVALID_BASIC_AUTH_URL(9, R.string.invalidBasicUrl)

This exception is thrown if the supplied authentication URL is not valid.

USER_AUTHENTICATION_FAILED(10, "Authentication request failed for user %1$s.")

This exception is thrown when the user authentication fails due to some internal errors from the server.

UN_PWD_TENANT_INVALID(11, R.string.unPwdTenantMissing)

This exception is thrown if authentication is not successful due to an incorrect identity domain, username, or password.

UNABLE_TO_OPEN_RP_AUTHENTICATION_URL(12, "Unable to open RP Authentication URL.")

This exception is thrown when the SDK is not able to construct a valid RP login URL.

UNABLE_TO_OPEN_SSO_AUTHENTICATION_URL(13, "Unable to open SSO Authentication URL.")

This exception is thrown when the business application is not able to open an SSO agent application because it might not have been installed on the device. Another possible reason is that the Android Application signatures entered in the Application Profiles of the SSO Agent and the SSO Client on the server do not match the signatures of the SSO Agent and SSO Client installed on the device.

NOT_AUTHORIZED_TO_PARTICIPATE_IN_SSO(14, "Client application is not authorized to participate in SSO.")

This exception is thrown when the business application is not able to self-authenticate or is not able to participate in SSO. This is due to an invalid configuration in the server console.

SETUP_FAILED_MS(16, "Application profile cannot be downloaded due to missing configuration")

This exception is thrown when the application profile cannot be downloaded from the Mobile & Social Server. This happens when the server URL, application ID, or service domain is null or empty.

TOKENS_NOT_AVAILABLE(17, R.string.tokensNotAvailable)

This exception is thrown if the OAM_ID token is not available when accessing a protected URL through a browser that is configured to invoke the SSO agent app for authentication. This may result if the authentication scheme is not set as MobileOAMAuthentication.

SETUP_NOT_INVOKED(21, "Setup API is not invoked.")

This exception is thrown when the setup() method of the SDK is not invoked.

SERVICE_DOMAIN_MISMATCH(22, "Authentication is rejected by the agent as the service domain does not match.")

This exception is thrown when the service domain of the SSO application does not match the service domain of the SSO client application.

USER_NOT_YET_AUTHENTICATED(23, "The user is not yet authenticated.")

This exception is thrown when the user is trying to execute processHttpRequest() to access a resource before authenticating.

APP_SIGNATURE_INVALID(24, "Failed in validating calling application signature.")

This exception is thrown when the SSO application is not able to validate the application signature of the calling business application.

INITIALIZATION_FAILED(25, "Initialization of the SDK failed, as the required server information is not supplied.")

This exception is thrown when any application is initialized through the URL scheme and the appropriate fields are not supplied.

INTERNAL_ERROR(26, "Internal Error")

This exception is thrown for all other exceptions raised from the SDK.