10 Developing Mobile and Social Services Applications with the Android Client SDK

This chapter describes how to develop Mobile and Social 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 five 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 and Social Services" in Oracle Fusion Middleware Administrator's Guide for Oracle Access Management for information about configuring the Mobile and Social server.

Step 1: Create an Object of OMMobileSecurityService

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

OMMobileSecurityService mss = new OMMobileSecurityService(context, configProperties, callback);

Table 10-1 OMMobileSecurityService Parameters

Parameter Description

context

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

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.

configProperties

The Map that contains the configuration properties. See Table 10-5 in Section 10.4, "Initialization Properties" for the list of configuration properties.

callback

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(), OMMobileSecurityService#authenticate(), and OMMobileSecurityService#logout().


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, "MobileServiceDomain");
          configProp.put(OMMobileSecurityService.OM_PROP_APPNAME,  "MyApp");
          configProp.put(OMMobileSecurityService.OM_PROP_OAMMS_URL, "http://www.example.com:14100");
 
        OMMobileSecurityService mss = new         OMMobileSecurityService(getApplicationContext(), configProp, callback);
        //getApplicationContext():  context of the calling application; 
        //callback: Instance of a  class which has implemented the interface 
        //OMMobileServiceCallback
  • OM_PROP_OAMMS_URL - The URL (<protocol>://<host>:<port>) required to reach the Mobile and Social server. Only the HTTP and HTTPS protocols are supported.

  • OM_PROP_OAMMS_SERVICE_DOMAIN - Specifies the name of the service domain that has been created on the Mobile and Social server. The application profile that OM_PROP_APPNAME 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.

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

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 a "Social Identity Authentication" authentication scheme.

Step 2: Register the Activity

Register the current activity before invoking methods in OMMobileSecurityService, such as setup(), authenticate(), and processSSORequest(Intent intent). Deregister the activity when it is not in the foreground. Do this to ensure that there is not a memory leak. To give the reference to the current activity, register the current activity in onResume() and deregister the activity in onPause() for all activities that call the methods mentioned above. If any of these methods are called in onCreate() of the activity, then before calling these methods, register the activity using OMMobileSecurityService#registerActivity(activity). When the activity moves to the background, deregister the activity using the method OMMobileSecurityService#deregisterActivity()).

mss.registerActivity(this);

Step 3: Call the setup() Method

Call the setup() method, which initiates the download of your application profile from the Mobile and Social server.

mss.setup();

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 using the following callback:

OMMobileServiceCallback#processSetupResponse(OMOMMobileSecurityService mss, 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.

Step 4: Call the authenticate() Method

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(OMMobileSecurityService mss, 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(OMMobileSecurityService mss, 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.

Step 5: Call the logout() Method

Call the following method to logout the user:

mobileSecurityService.logout(boolen isForgetDevice)

Table 10-2 logout() Method Parameter

Parameter Name Parameter Values Type

isForgetDevice

true - Clears everything stored in the credential store, including hashed passwords for supporting offline authentication, client registration handles, and tokens.

false - Clears only user session-related items from the store, such as tokens.

Boolean


The Mobile and Social server logout operation involves invoking a REST Web service to delete tokens maintained on the server. Consequently, the callback OMMobileServiceCallback#processLogoutResponse(OMMobileSecurityService mss, OMMobileSecurityException mse) is called after the server interaction is completed. Below is a sample callback implementation:

public void processLogoutResponse(OMMobileSecurityService mss, OMMobileSecurityException mse)
{
            if(mse == null)
            {
                Toast.makeText(getApplicationContext(), "Logout is successful!", Toast.LENGTH_SHORT).show();
            }
            else
            {
                Toast.makeText(getApplicationContext(), "Logout failure. " + mse.getErrorMessage(), Toast.LENGTH_SHORT).show();
            }
} 

10.3 URL-Based Initialization

To initialize the SDK using a URL, use a URL that contains the required configuration properties. The URL should be of the following format:

<scheme>://[host]?<parameter1>::=<value1>&<parameter2>::=<value2>&...&<parameterN>::=<valueN>

where:

Following is a sample URL for initializing an app with Mobile and Social server details:

samplescheme://settings?AuthServerType::=OAMMSAuthentication&
ApplicationName::=SampleApp&
OAMMSURL::=http://www.example.com:14100&
OAMMSServiceDomain::=MobileServiceDomain

This URL can be sent to users by e-mail or another means and, once the user clicks the URL using their Android mobile device, the corresponding app is invoked. The intent, which contains the configuration URL, has to be passed to the following method. The method, in turn, parses the URL and extracts the SDK configuration properties:

Set<String> filters = new HashSet<String>();
filters.add(OM_PROP_AUTHSERVER_TYPE);
filters.add(OM_PROP_APPNAME);
filters.add(OM_PROP_OAMMS_URL);
filters.add(OM_PROP_OAMMS_SERVICE_DOMAIN);
OMMobileSecurityService.parseConfigurationURI(context, intent, persistInSharedPreferences,keyInSharedPreference, filters)

Table 10-3 parseConfigurationURI() Method Parameters

Parameter Name Description

context

The context of the calling application. Always passContext#getApplicationContext().

intent

The intent that contains the SDK configuration properties.

persistInSharedPreferences

Indicates if the SDK configuration properties have to be persisted in SharedPreferences. This has to be mentioned as true so that the constructor OMMobileSecurityService(Context context, String configurationPropertiesKey, OMMobileServiceCallback callback) can create an instance of OMMobileSecurityService based on the configuration properties stored in SharedPreferences.

keyInSharedPreference

The key against which the SDK configuration properties have to be stored.

filters

Set of property strings in the configuration URL to be returned in the Map of configuration properties and optionally persisted in SharedPreferences. The remaining parameters in the URL extracted from the configuration URL are ignored by the IDM Mobile SDK.


Once the configuration properties are stored in SharedPreferences by calling the parseConfigurationURI() method, an instance of OMMobileSecurityService can be created as follows:

OMMobileSecurityService mobileSecurityService = OMMobileSecurityService(Context context, String configurationPropertiesKey, OMMobileServiceCallback callback);

Table 10-4 OMMobileSecurityService Parameters for URL-Based Initialization

Parameter Description

context

The context returned by Context#getApplicationContext()

configurationPropertiesKey

The key against which the SDK configuration properties have been stored. This should be the same as the key that was mentioned as keyInSharedPreference in OMMobileSecurityService.parseConfigurationURI(context, intent, persistInSharedPreferences,keyInSharedPreference).

callback

An instance of a class that has implemented the interface OMMobileServiceCallback. This is used by the SDK to return control to the application after calling OMMobileSecurityService#setup() and OMMobileSecurityService#authenticate()


10.4 Initialization Properties

Use the following initialization properties to initialize the SDK. The property names starting with OM_PROP are a part of the OMMobileSecurityService class. Use these properties to specify the entries being passed in the Map to the constructor: OMMobileSecurityService(context, configProperties, callback). For URL-based initialization, the name of the parameters and their corresponding values are included in parentheses.

Table 10-5 Android Client SDK Initialization Properties

Property Name Property Value(s) Type

OM_PROP_AUTHSERVER_TYPE

(AuthServerType)

  • OMMobileSecurityService.AuthServerType.OAMMS

    (OAMMSAuthentication)

  • OMMobileSecurityService.AuthServerType.HTTPBasicAuth

    (HTTPBasicAuthentication)

Enum (OMMobileSecurityService.AuthServerType)

OM_PROP_OAMMS_URL

(OAMMSURL)

Required property. A String that contains the protocol, host, and port required to reach the Mobile and Social server. Only the HTTP and HTTPS protocols are supported.

<protocol>://<host>:<port>

String

OM_PROP_OAMMS_SERVICE_DOMAIN

(OAMMSServiceDomain)

Required property. Specifies the name of the service domain that has been created on the Mobile and Social server. The application profile that OM_PROP_APPNAME 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.

String

OM_PROP_APPNAME

(ApplicationName)

Required property. 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.

String

OM_PROP_MAX_LOGIN_ATTEMPTS

(MaxLoginAttempts)

The maximum number of login attempts allowed by the user. Optional. If this property is not specified, the default is 3.

Integer

OM_PROP_AUTH_KEY

(AuthKey)

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

(LocationUpdateEnabled)

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_AUTO_LOGIN_ALLOWED

(AutoLoginAllowed)

Optional. Specifies if auto-login is enabled. Either true or false. By default it is disabled.

Boolean

OM_PROP_REMEMBER_USERNAME_ALLOWED

(Remember User name Allowed)

Specifies if the Remember User Name feature is enabled. Either true or false. By default it is disabled.

Boolean

OM_PROP_REMEMBER_CREDENTIALS_ALLOWED

(RememberCredentialsAllowed)

Specifies if the Remember Credentials feature is enabled. Either true or false. By default it is disabled.

Boolean

OM_AUTO_LOGIN_DEFAULT

(AutoLoginDefault)

Represents the default preference for the auto-login option box. Either true or false. Default value is false.

Boolean

OM_REMEMBER_USERNAME_DEFAULT

(RememberUsernameDefault)

Represents the default preference for the Remember User Name option box. Either true or false. The default value is false.

Boolean

OM_REMEMBER_CREDENTIALS_DEFAULT

(RememberCredentialDefault)

Represents the default preference for the remember credentials option box. Either true or false. Default value is false.

Boolean


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.14, "Using the Cryptography APIs."

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

Property Name Property enum Values Attribute Name Attribute Value

OM_PROP_CRYPTO_SCHEME

(CryptoScheme)

PLAINTEXT("PlainText")

Enum(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.5 About Offline Authentication

Mobile and Social supports offline authentication. Use the enum OMConnectivityMode to specify how offline authentication should happen.

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

An example is shown here:

OMAuthenticationRequest authRequest = new OMAuthenticationRequest();
authRequest.setConnectivityMode(OMConnectivityMode.ONLINE);
View authView = authenticate(authRequest);

Because offline authentication is part of OMAuthenticationRequest, the setting is valid for the current request alone. During offline authentication if the number of failure attempts exceeds the value of the OM_PROP_MAX_LOGIN_ATTEMPTS property (discussed in the "Initialization Properties" section), the locally stored credentials are deleted and online authentication is attempted.

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.

To support offline authentication, the SDK captures and stores the user credentials. The password of the user will either be hashed or encrypted based on the value set for the property OM_PROP_CRYPTO_SCHEME. If the application requires offline authentication and this property is not specified, the default crypto scheme is SSHA512.

10.6 Invoking Social Identity Authentication Using the Android Client SDK

This section provides sample code that shows how to do Social Identity Authentication (also called Relying Party Authentication) with the Mobile and Social Server. Refer to the "Configuring Social Identity" 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 user name, 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 Social 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.7 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 "Understanding Mobile Single Sign-on (SSO) Capabilities" and "Understanding Mobile and Social" in Oracle Fusion Middleware Administrator's Guide for Oracle Access Management.

In order to create your own Mobile SSO Agent App, refer to Section 10.12, "Creating a Custom Mobile Single Sign-on Agent App Using the Android Client SDK."

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

    The Launch Pad opens.

  2. Under Access Manager click Authentication Schemes, then click the Create Authentication Scheme 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 URL 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.8 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.9 Authenticating Using Client Certificate

IDM Mobile SDK supports 2-way SSL mutual authentication. In addition to the client validating the identity of the server, if the authentication server is configured to perform 2-way SSL, the server will then require the client certificate to validate the identity of the client. In other words, this is an additional authentication scheme where the server identifies the client, to avoid anonymous access.

IDM Mobile SDK provides various APIs for the client application to import the client certificates in the application keystore.

The client application can use this feature as a standalone authentication scheme or can club this feature with any other authentication schemes that are supported by the IDM Mobile SDK.

For this feature, IDM Mobile SDK introduces a new AuthServerType.CBA for applications that want to perform only standalone client certificate-based authentication.

Sample code:

configMap.put(OMMobileSecurityService.OM_PROP_APPNAME, "CBAApp");
configMap.put(OMMobileSecurityService.OM_PROP_AUTHSERVER_TYPE, AuthServerType.CBA);
configMap.put(OMMobileSecurityService.OM_PROP_LOGIN_URL, "https://myserver.com:1234/cba/");

Client certificate authentication can also be clubbed with other authentication modules such as Mobile and Social Authentication. The application is only required to pass the OM_PROP_PRESENT_CLIENT_IDENTITY_ON_DEMAND property as true during initialization process and the SDK present the client identity when it is requested by the authentication server. If the client application does not provide this property, then the IDM Mobile SDK will not provide support for client certificate-based authentication with other authentication schemes. This is described in the following sample code:

configProp.put(OMMobileSecurityService.OM_PROP_APPNAME,
"OAuthTesterApp");
configProp.put(OMMobileSecurityService.OM_PROP_AUTHSERVER_TYPE,
OAUTH20);
configProp.put(OMMobileSecurityService.OM_PROP_BROWSER_MODE,
BrowserMode.EMBEDDED);
configProp
.put(OMMobileSecurityService.OM_PROP_LOGIN_FAILURE_URL,
.put(OMMobileSecurityService.OM_PROP_LOGIN_URL,"http://login.com");\\\\
configProp.put(OMMobileSecurityService.OM_PROP_LOGIN_SUCCESS_URL,
"http://loginsucess.coml");\\\\ configProp.put(OMMobileSecurityService.OM_PROP_LOGOUT_URL,
"http://logout.com");\\\\ configProp.put(OMMobileSecurityService.OM_PROP_PRESENT_CLIENT_IDENTITY_ON_DEMAND, true);

Note:

If an app wants to import or preload some server or client certificates using the IDM Mobile SDK's import certificate functionality, it must be done before making any network connections with the SDK setup, authentication, or resource access.

OPEN ISSUES: Prior to Android L android webview has inability to respond to the 2-way SSL challenges during the network request, hence SDK does not support client certificate authentication in webview on devices running below android L. The same is being tracked as issues(https://code.google.com/p/android/issues/detail?id=53491) in Android Open source project.

10.9.1 Importing Certificates

This section describes the ability of the IDM Mobile SDK to import or preload the certificates before initializing any of the authentication processes.

10.9.1.1 Importing Server Certificates

The IDM Mobile SDK provides the OMCertService class that can be initialized by passing the application context in the constructor. This class supports importing both server and client certificates, along with this it also support various certificate operations as described in the following sections.

If the application imports the server certificate or the root certificate before starting the authentication process, then no "untrusted server certificate" warning will be shown by the SDK during the authentication process.

10.9.1.1.1 Importing the X509 Certificate

The IDM Mobile SDK provides the ability to import the server certificate as an "X509 Certificate" Object. Assuming that the application has bundled the certificate and now needs to import the certificate from the application resources during the initialization process of the application. The following sample code snippets describe this process:

OMCertService certService = new OMCertService(this.getApplicationContext());
X509Certificate cert;
            try
            {
                InputStream is = getAssets().open("Cert.cer");
                cert = readCertificateFromStream(is);
                certService.importServerCertificate(cert);
            }
            catch (CertificateException e2)
            {
                // TODO Auto-generated catch block
                e2.printStackTrace();
            }
            catch (IOException e2)
            {
                // TODO Auto-generated catch block
                e2.printStackTrace();
            }
X509Certificate readCertificateFromStream(final InputStream is)
            throws CertificateException
    {
        CertificateFactory certFactory = CertificateFactory
                .getInstance("X.509");
        DataInputStream dis = null;
        dis = new DataInputStream(is);
        try
        {
            byte[] certBytes = new byte[dis.available()];
            dis.readFully(certBytes);
            Certificate cert = certFactory
                    .generateCertificate(new ByteArrayInputStream(certBytes));
            if (cert instanceof X509Certificate)
                return (X509Certificate) cert;
            else
                throw new CertificateException();
        }
        catch (Exception e)
        {
            throw new CertificateException(e);
        }
        finally
        {
            if (dis != null)
            {
                try
                {
                    dis.close();
                }
                catch (IOException e)
                {
                    // do nothing
                }
            }
        }
10.9.1.1.2 Importing the Certificate File

The IDM Mobile SDK also supports the ability to import certificates from a "file" object within the device, such as mnt, sdcard or any other external storage location, or in app storage locations such as /data/data/myapp/certFile.cer. The following sample describe this feature:

OMCertService certService = new OMCertService(this.getApplicationContext());
 
//assuming that the certificate file is "Cert.cer" and is present in /mnt/sdcard
File file = new File(Environment.getExternalStorageDirectory(),"Cert.cer");
        try
        {
            certService.importServerCertificate(file);
        }
 
        catch (CertificateException e1)
 
         {    
 
           // import cert failed, check for the cause.
         }

10.9.1.2 Importing Client Identity Certificates

Any application that uses IDM Mobile SDK can import a user or client identity certificate. The OMCertService class provides the ability for both UI and non-UI APIs to import the client certificates.

The two following APIs are available in the OMCertService class to import client certificates:

10.9.1.2.1 Importing Client Certificates With a Password

public void importClientCertificate(File file, char[] pwd)

This API imports the given client certificate file in the Keystore that is maintained locally by the application. To do so, the application must pass the "File" object and the password for the .p12 certificate file. The following sample code describes the usage of this API:

OMCertService certService = new OMCertService(getApplicationContext());
File file = new File(Environment.getExternalStorageDirectory() + "/"
+ "client.p12");
try
{
certService.importClientCertificate(file, "password".toCharArray());
}
catch (CertificateException e)
{
...
}
10.9.1.2.2 Importing Client Certificates Without a Password

public void importClientCertificate(Activity activity, File file, OMCertServiceCallback callback)

This API is also used to import the client certificate, but it does not accept a password. Instead, it alerts to the user to collect the password.

Note:

This API must always be called from the UI thread.

The following sample code describes the usage of this API:

certService.importClientCertificate(this,
new File(Environment.getExternalStorageDirectory() + "/"
+ "newuser.p12"), new OMCertServiceCallback()
{
 
@Override
public void processClientCertifcateImportResponse(CertificateInfo cert, OMMobileSecurityException mse)
{
if (cert != null)
{
... .... .. ..
}
 
}
});

10.9.2 Performing Operations on Imported Certificates

The OMCertService class provides various APIs to perform operations on the imported certificates. The IDM Mobile SDK allows you to perform the following operations on imported Server and Client certificates:

  • List all imported certificates.

  • Get the "Certificate Info" of a particular certificate.

  • Delete the imported certificates.

10.9.2.1 Server Certificates

The OMCertService class provides the following APIs to perform various operations on imported server certificates:

  • public List<OMCertInfo> getAllServerCertificateInfo()

    This API returns the list of all the server certificates installed in the SDK truststore. These certificates are represented by OMCertInfo.

  • public void deleteAllServerCertificates()

    This API deletes all the imported server certificates in the SDK truststore.

  • public void deleteServerCertificate(OMCertInfo)

    This API deletes the specified server certificate represented by the passed OMCertInfo object.

10.9.2.2 Client Certificates

The OMCertService class provides the following APIs to perform various operations on imported client certificates:

  • public List<OMCertInfo> getAllClientCertificateInfo ()

    This API returns the list of all the client certificates installed in the SDK KeyStore. These certificates are represented by OMCertInfo.

  • public void deleteAllClientCertificates()

    This API deletes all the imported client certificates in the SDK truststore.

  • public void deleteClientCertificate(OMCertInfo)

    This API deletes the specified client certificate represented by the passed OMCertInfo object.

10.10 Developing OAuth and Mobile OAuth Services Applications With the Android Client SDK

This section describes the capabilities of the OAuth Service. It includes the following topics:

10.10.1 Understanding OAuth2.0 for Android

The OAuth Service allows organizations to implement the open standard OAuth 2.0 Web authorization protocol in an Access Manager environment. OAuth enables a client to access Access Manager protected resources that belong to another user (that is, the resource owner). The OAuth Service allows organizations to implement OAuth 2.0 in a new or existing Access Manager environment so that OAuth clients can use OAuth 2.0 flows to access resources protected by Access Manager. An OAuth client can be an application or service created and controlled by your organization, or it can be an application or service created and controlled by another organization that requires access to resources protected by Access Manager.

Tip:

For detailed information about OAuth and its related concepts see the "Understanding the OAuth Service" chapter of the Oracle Fusion Middleware Administrator's Guide for Oracle Access Management.

The IDM Mobile SDK provides authorization against the OAM Mobile and Social (M&S) OAuth Server in order to access protected resources.

After the initialization of the IDM Mobile SDK with the correct properties and authentication, the application will be able to get the access tokens in the same method as it did under other authentication modes.

Table 10-7 lists the new configuration properties that have been added to support the OAuth 2.0 service:

Table 10-7 Configuration Properties for OAuth 2.0

Configuration Property Valid Value Mandatory

OM_PROP_AUTHSERVER_TYPE

(AuthServerType)

Enum (oracle.idm.mobile.OMMobileSecurityService.AuthServerType)

AuthServerType.OAuth20 (OAuth20)

Yes

OM_PROP_OAUTH_AUTHORIZATION_GRANT

(OAuthAuthZGrantType)

Enum(oracle.idm.OMMobileSecurityConfiguration.OAuthAuthorizationGrantType), the value can be one of the following:

  • IMPLICIT(OAuthImplicit)

  • AUTHORIZATION_CODE(OAuthAuthorizationCode)

  • RESOURCE_OWNER(OAuthResourceOwner)

  • ASSERTION("OAuthUserAssertion") - (OAM(M&S) oauth)

  • CLIENT_CREDENTIALS("OAuthClientCredentials") - (OAM(M&S) oauth)

  • OAM_CREDENTIAL("OAuthOAMCredential") - (OAM(M&S) oauth)

Yes

OM_PROP_OAUTH_AUTHORIZATION_ENDPOINT

(OAuthAuthZEndpoint)

URL/String

This is mandatory for all client types using AUTHORIZATION_CODE as grant type, except M&S Mobile OAuth Clients.

OM_PROP_OAUTH_TOKEN_ENDPOINT

(OAuthTokenEndpoint)

URL/String

This is mandatory for all client types except M&S Mobile OAuth Clients.

OM_PROP_OAUTH_REDIRECT_ENDPOINT

(OAuthRedirectEndpoint)

String

This is mandatory for all client types except M&S Mobile OAuth Clients.

OM_PROP_OAUTH_CLIENT_ID

(OAuthClientID)

String

Yes

OM_PROP_OAUTH_SCOPE

(OAuthScope(s))

Set<String>

No

OM_PROP_BROWSER_MODE

(BrowserMode)

Enum (oracle.idm.mobile.OMMobileSecurityConfiguration.BrowserMode)

No.

However, the default option will be EXTERNAL if nothing is set during initialization.

OM_PROP_OAUTH_CLIENT_SECRET

(OAuthClientSecret)

String

No

OM_PROP_OAM_OAUTH_SERVICE_ENDPOINT

(OAMOAuthServiceEndpoint)

String/URL

No.

This is only required for OAM OAuth mobile clients.

OM_PROP_OAUTH_ASSERTION_JWT (OAuthUserJWTAssertionValue)

String

No

OM_PROP_OAUTH_ASSERTION_SAML2 (OAuthUserSAML2UserAssertionValue)

String

No

OM_PROP_OAUTH_CLIENT_ASSERTION_SAML2 (OAuthClientSAML2AssertionValue)

String

No

OM_PROP_OAUTH_CLIENT_ASSERTION_JWT (OAuthClientJWTAssertionValue)

String

No


10.10.2 Oracle Access Manager Mobile and Social (M&S) OAuth

The OAM M&S server supports the following types of OAuth clients that can be used with mobile.

  • Web Clients: These clients can use the IDM Mobile SDK with the OAuth Generic flows as discussed below. The web-based clients are considered as trusted clients and possess a client secret. Therefore, the authorization server knows the identity of the client that is making the request. When using this client type, the application should pass the client secret during SDK initialization.

  • Mobile Clients : Mobile clients are not considered to be confidential clients. So, they do not possess a client secret. The OAM OAuth server provides a functionality through which mobile clients can be registered dynamically by sending the device claims along with the username and password of the end user. This flow is proprietary to the OAM OAuth server. After dynamic client registration is performed, the IDM Mobile SDK receives a client assertion and user assertion ( if SERVER SIDE SSO is not enabled). The client assertion token is required to be sent in all the subsequent requests for access token acquisition or other token operations. IDM Mobile SDK manages the life cycle of the client assertion and does not return this to the client application.

New Token Type Significance
Client Assertion This token is generated after the dynamic client registration is performed. This token is must be sent with every request made to the authorization server. The server identifies the request or client from the client assertion and validates the same. Client assertions are usually JWT tokens.
User Assertion Since dynamic client registration involves user authentication, M&S along with client assertion generates a user assertion. This user assertion marks the user session on the server side. The user assertion is returned by the server only when the SERVER SIDE SSO is disabled. The client or SDK can thus use the same assertion to acquire the access token for every resource access till the user session is valid on server side.

Also, when the SERVER SIDE SSO is enabled, the SDK or client can still use the user assertion by adding the following parameter in every request:

use_server_side_device_store = true


After configuring the server for the OAuth mobile client, the application can initialize the SDK using the same details. See the "Configuring OAuth Services" chapter of Fusion Middleware Administrator's Guide for Oracle Access Management for detailed information about configuring the server. See the sample code in Section 10.10.2.1.2, "Working With the Supported Grant Types and Getting Access tokens" for more information about initializing the SDK.

10.10.2.1 Authentication

After the completing the setup, the application can perform authentication which is to get an access token for accessing the OAuth protected resources. The authentication flow is not different from the other flows. The application only needs to invoke the OMMobileSecurityService#authenticate() API to start the authentication process. The SDK will invoke the OMMobileServiceCallback#processAuthenticationResponse after the authentication is done. If the authentication is successful, the context will contain the access token along with the other axillary tokens like user_assertion it if available. If the authentication was not successful, the authentication context will be null.

This flow of authentication involves the following steps:

10.10.2.1.1 Dynamic Client Registration

Mobile clients are usually not considered to be confidential and so the server does not create any secrets for these clients. However, the OAM M&S server provides a functionality through which the client can register itself dynamically to get a client token (client_assertion) which is tied to the user and the device from which the registration is being performed. The device information is useful for the server to track the user and the device so that it can trigger the OAAM plug-in if applicable.

The OAM Mobile and Social server supports two methods to perform client registration. The client registration flow is decided by the SDK based on the grant type provided by the application during initialization. The property used to define the grant type is OM_PROP_OAUTH_AUTHORIZATION_GRANT.

2-Legged Client Registration:

2-legged client registration is performed when the grant type is set as RESOURCE_OWNER, ASSERTION, CLIENT_CREDENTIALS, or OAM_CREDENTIALS. After the end of this flow, SDK receives the client_assertion along with user assertion token.

Note:

The availability of user_assertion on the client side is dependant on the value that is set for the SERVER_SIDE_SSO property in the server.

3-Legged Client Registration:

3-legged client registration is done when the grant type is set as AUTHORIZATION_CODE. This flow will invoke the external or embedded browser based on the initialization property. At the conclusion of this flow, IDM Mobile SDK will receive only the client_assertion token.

10.10.2.1.2 Working With the Supported Grant Types and Getting Access tokens

After the dynamic client registration is performed and the SDK has a valid client_assertion token as mentioned in Section 10.10.2.1.1, "Dynamic Client Registration," it can proceed to perform the access token acquisition flow. The access token can be acquired using the following grant type that is specified using the initialization property OM_PROP_OAUTH_AUTHORIZATION_GRANT. The following is the sample code for initialization:

Map<String, Object> configMap = new HashMap<String, Object>();
        configMap.put(OMMobileSecurityService.OM_PROP_APPNAME,
                "MSOAuthClient1");
        configMap.put(OMMobileSecurityService.OM_PROP_AUTHSERVER_TYPE,
                AuthServerType.OAuth20);
        configMap.put(OMMobileSecurityService.OM_PROP_OAUTH_CLIENT_ID,
                "1234567890987654321");
        
        configMap.put(
                    OMMobileSecurityService.OM_PROP_OAUTH_REDIRECT_ENDPOINT,
                    "idmtester://");
        configMap.put(OMMobileSecurityService.OM_PROP_OAUTH_AUTHORIZATION_GRANT_TYPE,
                                OAuthAuthorizationGrantType.RESOURCE_OWNER);
 
        Set<String> scopeset = new HashSet<String>();
      
        scopeset.add("UserProfile.users");
        scopeset.add("UserProfile.secretkey.management");          
        
        configMap.put(OMMobileSecurityService.OM_PROP_OAUTH_SCOPE, scopeset);
 
        configMap.put(
                    OMMobileSecurityService.OM_PROP_OAM_OAUTH_SERVICE_ENDPOINT,
                    "http://myhost.example.com:18465/ms_oauth/oauth2/endpoints/oauthservice");    
        configMap.put(OMMobileSecurityService.OM_PROP_BROWSER_MODE, BrowserMode.EXTERNAL);

Resource Owner Grant Type

The value of the initialization property should be OAuthAuthorizationGrantType.RESOURCE_OWNER. For this grant type, the 2-legged client registration flow is performed (as mentioned above). The SDK collects the user name and password in order to complete the 2-legged client registration flow. Hence the SDK will reuse these user credentials to get the access token. The SDK does not honor the SERVER_SIDE_SSO property sent by the server in this flow and will always send the user credentials to get an access token.If the client assertion is expired or invalidated, the SDK will again ask for the end user credentials to first renew the client assertion and then get the access token.

Client Credentials Grant Type

The value of the initialization property should be OAuthAuthorizationGrantType.CLIENT_CREDENTIALS. This grant type also involves the 2-legged client registration. In order to complete the authentication flow, the SDK uses the client_assertion obtained after the client registration to get the access token.

Note:

If the client assertion is expired or invalidated, the SDK will ask for the end user credentials to first renew the client assertion and then get the access token.

Assertion Grant Type

The value of the initialization property should be OAuthAuthorizationGrantType.ASSERTION.

This grant type also involves the 2-legged client registration flows, after which the SDK gets a client_assertion token and a user_assertion token. As mentioned earlier, the user_assertion token is made available by server only if the SERVER_SIDE_SSO is false. To complete the authentication flow the SDK uses the user assertion obtained after client registration to get the access token. This grant type honors the SERVER_SIDE_SSO configuration property from the server by appropriately forming the request based on the property value. If the SERVER_SIDE_SSO property is set to true, the SDK adds the oracle_use_server_device_store=true parameter in the access token request. In doing so, it requires the server to reuse the user session that was created at the server side.

Applications can however provide the custom assertion to be used for this flow using the initialization property OM_PROP_OAUTH_ASSERTION_JWT for JWT assertion and OM_PROP_OAUTH_ASSERTION_SAML2 for saml2 assertions. The SDK will use this assertion for access token acquisition to complete the authentication flow.

Authorization Code Grant Type

The value of the initialization property should be OAuthAuthorizationGrantType.AUTHORIZATION_CODE. This grant type involves the 3-legged client registration flow. After this flow, the SDK receives only the client_assertion. During this flow, the SDK invokes either the external or embedded browser based on the initialization property OM_PROP_BROWSER_MODE. The SDK must invoke the browser twice to complete the authentication flow. The first time is for client registration and the second time is for getting the access token.

Note:

If the application provides the value as BrowserMode.EXTERNAL for the OM_PROP_BROWSER_MODE property, the user may not have to enter the credentials twice in the external browser. This is because the server will set the OAM_ID cookie in the external browser during client registration flow itself, and so, during the access token acquisition the browser will not prompt for the login credentials.

OAM Credential Grant Type:

The value of the initialization property should be OAuthAuthorizationGrantType.OAM_CREDENTIAL. This grant also involves the 2-legged client registration flows after which the SDK will obtain a client_assertion and a user_assertion token based on the value set for the SERVER_SIDE_SSO property. To complete the authentication flows, SDK will first exchange the client_assertion to get the access token for OAuth protected resources, and then use the client_assertion and user_assertion (if available) to get the OAM_ID(USERTOKEN_MT) and OBSSOCookie(USERTOKEN) tokens. This grant type is provided by the server for the clients who use the OAM_ID cookie to access the webgate protected resources.

10.10.3 Standard Flows(Generic Implementation)

IDMMobile SDK supports authorization against any OAuth2.0 compliant server .The support is added in order to fit with current authentication architecture followed by the IDMMobile SDK for other types of authentications . The SDK will also work against any OAuth2.0 generic server provided it supports the below mentioned grant types for mobile clients.

The Current implementation supports the following grant types:

  • Implicit grant type.(client id and token endpoint are must)

  • Authorization code grant type .(client_id,authorization end point and token endpoint are must)

  • Resource Owner grant type (client_id and token end point is must)

  • Client Credentials (for this client_id and client_secret is must)

  • Assertion (For this the application should provide an assertion value using any one of the OM_PROP_OAUTH_ASSERTION_JWT or OM_PROP_OAUTH_ASSERTION_SAML2 property based on the type of assertion)

10.10.3.1 Authentication

In order to authenticate the user (or get a valid access token) with the OAuth2.0 server, the SDK accepts a set of scopes.

After user authentication and user consent with the authorization server, the access token returned from the authorization server is retrieved by the IDMMobile SDK and is tied with the scopes provided during initialization.

Hence, before starting any authentication process, the SDK checks for any valid access token for the requested scopes. If there is a valid access token for the requested scopes or there is an access token already present with a wider scope or scopes, the SDK will not perform authentication again. Instead, it will return the same authentication context (access token) .

The IDMMobile SDK supports the refreshing of the access token if it is supported by the authorization server.

The life cycle of an access token is controlled by the SDK. So if any access token is invalid, the SDK will internally try to refresh the access token if the access token had a refresh token value returned from the server initially.

Sample code for initialization :

            configProp.put(OMMobileSecurityService.OM_PROP_AUTHSERVER_TYPE,
                    OMMobileSecurityService.AuthServerType.OAuth20);
            configProp.put(OMMobileSecurityService.OM_PROP_OAUTH_CLIENT_ID,
                    "myhost.example.com");
            configProp
                    .put(OMMobileSecurityService.OM_PROP_OAUTH_AUTHORIZATION_GRANT,
                            OAuthAuthorizationGrantType.AUTHORIZATION_CODE);
            configProp
                    .put(OMMobileSecurityService.OM_PROP_OAUTH_AUTHORIZATION_ENDPOINT,
                            "https://accounts.example.com/o/oauth2/auth");
            configProp.put(
                    OMMobileSecurityService.OM_PROP_OAUTH_TOKEN_ENDPOINT,
                    "https://accounts.example.com/o/oauth2/token");
            configProp.put(OMMobileSecurityService.OM_PROP_BROWSER_MODE,
                    BrowserMode.EMBEDDED);
            configProp.put(OMMobileSecurityService.OM_PROP_OAUTH_REDIRECT_ENDPOINT,
                    "http://localhost");
 
           List<String> scope1 = new ArrayList<String>();
           scope1.add("https://www.example.com/auth/userinfo.email");
           scope1.add("https://www.example.com/auth/userinfo.profile");
 
           configProp.put(OMMobileSecurityService.OM_PROP_OAUTH_SCOPE, scope1);
           configProp.put(OMMobileSecurityService.OM_PROP_APPNAME, appId);

After initializing, you can call the authenticate() api on MSS after performing the setup.

The following is a sample code to authenticate with a custom OMAuthenticationRequest:

 OMAuthenticationRequest authRequest1 = new OMAuthenticationRequest();
           List<String> scope3 = new ArrayList<String>();
           scope3.add("https://www.example.com/auth/calendar");
           authRequest1.setOAuthScopes(scope3));
               try
               {
                   mAuthView = getMobileSecuritySevice().authenticate(
                           authRequest1);
               }
               catch (OMMobileSecurityException e)
               {
                   e.printStackTrace();
               }
           RelativeLayout.LayoutParams params1 = new RelativeLayout.LayoutParams(
           RelativeLayout.LayoutParams.MATCH_PARENT,
           RelativeLayout.LayoutParams.MATCH_PARENT);
           rl.addView(mAuthView, params1);

10.10.4 New APIs

  • OMAuthenticationContext#getTokens(List<String> scopes):

    The API returns a list of tokens that are valid and match the passed list of scopes. The passed scopes should match or be a subset of the scopes associated with the access token held by the SDK. If null is passed, then the SDK returns all the non-expired access tokens at a given time.

  • OMAuthenticationContext#isValid(List<String> scopes boolean refreshExpiredToken):

    This API returns boolean true or false if the access token for the given scope is valid or expired respectively. If the access token is expired, the SDK will try to refresh the same internally based on the value set for the refreshExpiredToken passed in the function call. If this value is set as true the SDK will refresh the access token. The refresh is possible if the following conditions are met:

    • The server supports refreshing for the mobile clients and given authorization grant types.

    • If SDK has a valid refresh token value associated with the access token retrieved earlier. This shows that refreshing the access token is possible only in OAuthAuthorizationGrantType.Authorization_Code.

10.10.5 Getting the Tokens From SDK

The SDK will expose all the tokens obtained during the OAuth2.0 flows both through OMAuthenticationContext#getTokens() which returns the map of tokens and OMAuthenticationContext#getTokens(Set<String>) which returns the list of tokens matching the passed scopes. Refer to the following table to obtain the token from the SDK.

Token Type Constant value used as name
access_token OMSecurityConstants.OAUTH_ACCESS_TOKEN

("oauth_access_token")

user_assertion OMSecurityConstants.OM_OAUTH_USER_ASSERTION_TOKEN

("user_assertion")

usertoken OMSecurityConstants.USER_TOKEN

("USERTOKEN")

oam_id OMSecurityConstants.OAM_ID

("OAM_ID")


10.10.6 Using the External Browser

The initialization and the call to authenticate is for same for both browser modes, embedded or external. However, if the application uses the external browser to complete authentication, there are a few additional steps involved. This is because the response must be retrieved from the authorization server back to the application so that the SDK can complete the authentication flow. The following steps are followed:

  • You must register the application or activity with the data or scheme. This is the same as the redirect url mentioned during initialization.

  • After the activity is registered for the url scheme similar to redirect url, you must invoke processSSORequest(intent) in NewIntent()(single instance activity) or on Resume() of the activity. In doing so, the SDK will internally parse the response from the server and return the result Authcontext or OMMobileSecurityException via the processAuthenticationResponse response.

This model is similar to SSO-based authentication. The sample codes are provided in this section.

Add intent filters in the AndroidManifest.xml to register the app for the redirect URL so that the application catches the response from the authorization server if an external browser is used. You must add the intent filter in the activity on which you want to get the control back and complete the authentication process.

If you want to register for redirect url like : example://

<intent-filter>
                <data android:scheme="geektech" />
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.BROWSABLE" />
                <category android:name ="android.intent.category.DEFAULT"/>
            </intent-filter>

If you want to register for redirect url like :http://localhost

<intent-filter>
<data android:scheme="http" android:host="localhost" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name ="android.intent.category.DEFAULT"/>
</intent-filter>

In order to complete the authentication, you must get the intent used by the external browser to invoke your activity whose url scheme is registered as the redirect url, which was mentioned during the initialization. Then you must call processSSORequest on the OMMobileSecurityService instance.

    @Override
    protected void onNewIntent(Intent intent)
    {
        super.onNewIntent(intent);
        System.out.println("MainActivity--- onNewIntent()");
        if (intent != null && intent.getData() != null)
        {
            try
            {
                getMobileSecuritySevice().processSSORequest(intent);
            }
            catch (OMMobileSecurityException e)
            {
                e.printStackTrace();
            }
        }
    }

10.10.7 Accessing Protected Resources

After successful authentication with the OAuth server, having a valid access token for a particular set of scopes, the application can now access the resources protected by the authorization server. The following new APIs must be used in order to perform this request:

  • OMHTTPRequest#executeHTTPRequest(HttpRequest httpRequest

  • OMHTTPRequestCallback callback, List<String> scopes, boolean isAsync)

This method can be used to access any web resource protected by a OAuth2.0 server. This method will inject the access token based on the scopes passed in the request and successfully retrieve the response from the server. If the access token for the requested scopes is expired, then this method will internally refresh the token. This can be performed in an asynchronous way, providing a {@link OMHTTPRequestCallback} object. The response will be delegated through this call back after the request is executed.

*@param request: an instance of {@link HttpRequest} object
* @param callback
* an instance of {@link OMHTTPRequestCallback} , by on which the
* SDK will delegate the response if the request is asynchronous
* @param isAsync
* boolean if the request is to be performed asynchronously or
* not .
* @return an instance of {@link HttpResponse} If the request is
* asynchronous the result will be sent via
* {@link OMHTTPRequestCallback} instance initially registered.

This method will be called by the SDK once OMHTTPRequest#executeHTTPRequest(org.apache.http.HttpRequest, OMHTTPRequestCallback, boolean), OMHTTPRequest#executeHTTPRequest(org.apache.http.HttpRequest, OMHTTPRequestCallback, java.util.List, boolean) is executed. The SDK will delegate the result of the execution through this callback.

* @param request
* {@link OMHTTPRequest} instance on which the request is
* executed .
* @param response
* {@link HttpResponse} object obtained after execution of the
* request .This will be null when there is failure during
* execution.
* @param exception
* {@link OMMobileSecurityException} This contains the failure
* details if any.
*/

Sample code:

String authReq1 = "https://www.googleapis.com/oauth2/v1/userinfo";
  List<String> scope1 = new ArrayList<String>();
           scope1.add("https://www.googleapis.com/auth/userinfo.email");
           scope1.add("https://www.googleapis.com/auth/userinfo.profile");
OMHTTPRequest omrequest = new OMHTTPRequest(
                        getMobileSecuritySevice());
                HttpRequest httpRequest = new HttpGet(authReq1);
                try
                {
                       omrequest1.executeHTTPRequest(httpRequest1,
                            new OMHTTPRequestCallback()
                            {
                                @Override
                                public void processHTTPResponse(
                                        OMHTTPRequest request,
                                        HttpResponse response,
                                        OMMobileSecurityException exception)
                                {
                                    //Handle Your code for parsing response here .
                                    //not adding the source for parsing the response as its up to the app dev how they want to make use of this.
 
                                }
                            }, scope1, true);
                }
                catch (OMMobileSecurityException e)
                {
                    e.printStackTrace();
                }

10.10.8 Credential Collection

For IMPLICIT, and AUTHORIZATION_CODE grant types, the SDK invokes an external or embedded browser. The authorization server will load the login page in the browser. Hence, the end user submits the login credentials directly to the authorization server.

For RESOURCE_OWNER, CLIENT_CREDENTIALS, ASSERTION and OAM_CREDENTIAL grant types, the SDK will by default throw a native UI to collect the login credentials of the end user. However the application can direct the SDK to throw a custom view or UI for credential collection. See Section 10.13, "Login View and KBA View Customization," for detailed information.

Note:

Only the remember user name flag will be entertained in case of OAuth2.0 (as in resource owner grant type SDK collects the credentials). The Remembering Credentials section provides detailed information.

10.11 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 and in local storage.

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 values configured in the OAM 11g R2
        // WebGate user defined parameters.
        // We need to configure OAM 11g R2 WebGate with these parameters:        //  i) OAMAuthUserAgentPrefix=<Prefix for User-Agent HTTP header> (Example: OIC)        // ii) OAMAuthAuthenticationServiceLocation=<OIC Server URL> (Example:
        //     http://host123.us.example.com:14100/oic_rest/rest/mobileoamauthentication)
        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 and OAMAuthAuthenticationServiceLocation properties. The same property values 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.

In version 11.1.2.2 of the SDK, an option to execute the Web service request asynchronously was added. To execute the request in the background, the SDK accepts a call back OMHTTPRequestCallback object. The SDK notifies the application when the request is executed and the REST request response is propagated to the application using this callback object. The OMHTTPRequest class receives and responds to the request. Following is the method signature.

OMHTTPRequest#executeHTTPRequest(HttpRequest httpRequest , OMHTTPRequestCallback callback , boolean isAsync)

Where:

  • httpRequest is the HttpRequest object

  • OMHTTPRequestCallback is the callback object that the SDK uses to notify the app that the request is completed. The response/error is sent using this callback object by this method:

    OMHTTPRequestCallback#processHTTPResponse(OMHTTPRequest request, HttpResponse response, OMMobileSecurityException exception)
    

    The application needs to implement this interface and handle the response/error handling logic.

  • isAsync is a Boolean that tells if the request need to be executed asynchronously or not. If false then the execution is similar to OMMobileSecurityService#processHttpRequest(HttpRequest).

Following is sample code that demonstrates an asynchronous REST request.

OMHTTPRequest omrequest1 = new OMHTTPRequest(getMobileSecuritySevice());
HttpRequest httpRequest1 = new HttpGet("http://abc.example.com:7777/restService") ;
 
try
{
omrequest1.executeHTTPRequest(httpRequest1,
new OMHTTPRequestCallback()
  {
 
    @Override
    public void processHTTPResponse( OMHTTPRequest request, HttpResponse response, OMMobileSecurityException exception)
    {
     String data1="";
     if (response != null)
      {
       try
       {
        data1 = parseHttpResponse(response);
       }
       catch (IOException e)
       {
        
        // TODO Auto-generated catch block
        e.printStackTrace();
       }
       catch (JSONException e)
       {
        // TODO Auto-generated catch block
        e.printStackTrace();
       }
      }
     else
     {
       if (exception != null)
       {
        data1 = exception.getErrorMessage();
       }
     }
     if(data1 != null)
     {
       Message msg = handler.obtainMessage(MSG_SHOW_DIALOUGE);
       msg.obj = data1;
       handler.sendMessage(msg);
     }
 
   }
  }, true);
}
catch (OMMobileSecurityException e)
{
e.printStackTrace();
}

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

You can extend the Application class to keep a singleton instance for OMMobileSecurityService that accepts either a null intent or one that contains a configuration URL. The following code snippet shows how to initialize an OMMobileSecurityService instance using the configuration URL based mechanism for a new intent and using the config properties stored in SharedPreferences for subsequent cases.

public OMMobileSecurityService getMobileSecurityService(Context context,
            Intent intent, OMMobileServiceCallback callback)
            throws JSONException, OMMobileSecurityException
{
     if (!mssInitialized)
     {
            if (intent == null || intent.getData() == null)
            {
                mss = new OMMobileSecurityService(context, callback);
            }
            else
            {
                Map<String, Object> configMap = OMMobileSecurityService
                        .parseConfigurationURI(context, intent, true, null);
 
                mss = new OMMobileSecurityService(context, configMap, callback);
            }
            if (mss == null)
            {
                throw new OMMobileSecurityException(
                        OMErrorCode.INITIALIZATION_FAILED, null, context);
            }
            else
            {
                mssInitialized = true;
            }
     }
     else
     {
            mss.registerCallback(callback);
     }
     return mss;
} 

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)
            {
                 boolean isConfigurationIntent = false;
                 /* Check if the intent URI contains the configuration parameters 
                    which can be passed to the the SSOApplication class. */ 
                 
                 if (isConfigurationIntent == true)
                 {
                      mMobileSecurityService = (SSOApplication) getApplication.getMobileSecurityService(getApplicationContext(), intent, new SSOAgentCallback();
                 }
                 else
                 {
                      mMobileSecurityService = (SSOApplication) getApplication.getMobileSecurityService(getApplicationContext(), null, new SSOAgentCallback();
                 }
            }
            if ((intent.getData() != null && !isConfigurationIntent) || 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
             */
        }
    }

10.13 Login View and KBA View Customization

The SDK displays a basic login 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 user name 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.14 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 mss as follows:

OMCryptoService cryptoService =  mss.getCryptoService();
 

Note:

In the 11.1.2.2 release, the OMCryptoService added support for passing a custom key for features such as encryption, decryption, and matching, while keeping support for legacy features that work independent of any key. Applications can now manage the life cycle of the crypto key themselves. They do not have to depend on the SDK generated key. It is the application's duty to provide the same key for encryption and decryption of the same data. The custom key that the SDK accepts is a byte[] array. The application must provide a compliant key size based on the encryption algorithm being used.

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 either generated automatically and stored in the credential store (the SDK default key), or a custom key provided by the application.

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);

If using a custom key:

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

The key for decryption is automatically retrieved from the credential store automatically (that is, the SDK default Key), or provided by the application if the encryption was done using a custom key. The decrypted text is given as output by the following method. The SDK default key is generated automatically by the SDK when the encrypt method is called for the first time.

cryptoService.decrypt(encodedText);

If using a custom key:

cryptoService.decrypt(encodedText,customKey);URL

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.

Note:

If the text is encrypted using a custom Key, the application should pass the same key in the match() method.
cryptoService.match(password, passwordStored, mss.getMobileSecurityConfig().getSaltLength());

If using a custom key:

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

10.15 Using the Auto Login and the Remember Credentials Features

The Mobile and Social Android Client SDK provides APIs that can securely store user credentials and play them back to a login server with or without user interaction. Deploy this feature in apps where security is not critically important to make it easier for users to log in. This feature requires at least version 11.1.2.2.0 of the Mobile and Social Client SDK.

To use this feature, the user selects one of up to three option boxes on the login screen. (You can choose to enable one, two, or all three of these options in your app.) If more than one option is selected, the higher priority feature takes precedence. The priority of the options is as follows:


1. Auto Login
2. Remember Credentials
3. Remember User Name Only

So for example, if Auto Login and Remember Credentials are selected, then Auto Login takes priority.

The three options are described as follows:

  • Auto Login - The Mobile and Social Android Client SDK securely caches the user's credentials and automatically supplies them at the login screen. This option does not require any user interaction to log the user in. The user see a progress screen that provides feedback while authentication is underway.

  • Remember Credentials - The Mobile and Social Android Client SDK securely caches the user's credentials and auto-fills the user name and password fields on the login screen. The user has to click the Login button to proceed with the authentication process. The user can enter different credentials and make changes to the option boxes if necessary.

  • Remember User Name Only - The Mobile and Social Android Client SDK securely caches the user name and auto-fills the user name on the login screen. The user has to input the password and click the login button to proceed with the authentication process. The user can enter different user name and make changes to the option boxes if necessary.

Enabling the Feature

This is a client-side only feature that does not require server configuration to deploy. To enable the features described, the following SDK configuration parameters should be added to your code:

Table 10-8 Configuration parameters used to enable auto login and remember credentials features

Parameter Description

OM_PROP_AUTO_LOGIN_ALLOWED

Boolean value that enables/disables the Auto Login feature.

OM_PROP_REMEMBER_CREDENTIALS_ALLOWED

Boolean value that enables/disables the Remember Credentials feature.

OM_PROP_REMEMBER_USERNAME_ALLOWED

Boolean value that enables/disables the Remember User Name Only feature.


Handling User Preferences

Pass the following properties while initializing the mss object to pre-populate the option boxes with a default value. Only one of the following options can be true. If all the option box states are false, all of the option boxes on the login screen will be empty.

Table 10-9 Configuration parameters used to set the option box default values

Parameter Description

OM_AUTO_LOGIN_DEFAULT

Boolean value that specifies the default value of the "Auto Login" option box.

OM_REMEMBER_CREDENTIAL_DEFAULT

Boolean value that specifies the default value of the "Remember Credential" option box.

OM_REMEMBER_USERNAME_DEFAULT

Boolean value that specifies the default value of the "Remember User Name Only" option box.


Persist option box states as key-value pairs in SharedPreferences. Use the combination of the server URL and the application identifier as a key so that the user preferences for each login connection can be uniquely identified.

Clearing Credentials and Preferences From Mobiles Devices

Authentication failure can result if the user credentials were changed since the last login, or if the mobile device is not able to reach the authentication service due to a network or server issue. If authentication fails using the stored credentials, the SDK deletes the stored password (if present) from the shared preferences. The login page will then either revert to the Remember User Name Only feature, or control will revert to the mobile app using OMMobileServiceCallback. This decision is based on an SDK-level parameter named OM_PROP_MAX_LOGIN_ATTEMPTS, which is a numeric value that stores how many incorrect attempts for authentication are allowed before control is given back to the mobile app.

The SDK will clear a stored user password from the mobile device in the following scenarios:

  • The user authentication fails (for example, if the server password is no longer valid, the user is blocked, or if the user authentication fails for another reason).

  • The Mobile and Social Android Client SDK logout method is called

  • A session time-out is detected

The SDK will clear the stored user name, password, and option box states from the mobile device in the following scenario:

  • The Mobile and Social Android Client SDK logout method is called and the forgetDevice parameter is set to true

Creating a Custom Login Screen

The Mobile and Social Android Client SDK sends flags in the input params map in the processViewRequest callback that you use to inflate your custom views. (See Section 10.13, "Login View and KBA View Customization" for more information.) These flags are specific to the Auto Login and Remember Credentials features and indicate if a given feature is enabled or disabled during initialization, and what the UI preference for these features should be set to. The SDK also sends the user name and the password as needed for the Remember User Name and Remember Credentials options.

If you want to create a custom login screen instead of using the basic login view provided by the SDK, do the following:

  • Receive and interpret the Auto Login / Remember Credentials flags correctly

  • Control the visibility of the option boxes for flags that indicate if a feature is enabled

  • For flags that indicated UI preferences, update the state of the option boxes when presenting the view to the user

  • After the submit button is pressed, read the state of the option boxes and send the same

The following table lists the keys that you need to use to access credential properties in the authentication inputParams Map.

Table 10-10 Keys used to access credential properties in the inputParams Map

Key Description

OMMobileSecurityService.OM_PROP_AUTO_LOGIN_ALLOWED

Boolean value that enables/disables the Auto Login feature.

OMMobileSecurityService.OM_PROP_REMEMBER_CREDENTIALS_ALLOWED

Boolean value that enables/disables the Remember Credentials feature

OMMobileSecurityService.OM_PROP_REMEMBER_USERNAME_ALLOWED

Boolean value that enables/disables the Remember User Name Only feature

OMSecurityConstants.OM_AUTO_LOGIN_PREF

Boolean value that specifies the user's preference regarding the Auto Login feature based on the last authentication.

OMSecurityConstants.OM_REMEMBER_CREDENTIALS_PREF

Boolean value that specifies the user's preference regarding the Remember Credentials feature based on the last authentication.

OMSecurityConstants.OM_REMEMBER_USERNAME_PREF

Boolean value that specifies the user's preference regarding the Remember User Name Only feature based on the last authentication.

OMSecurityConstants.USERNAME

String value that specifies the user's user name.

OMSecurityConstants.PASSWORD

String value that specifies the user's password.


The following code sample shows how you can control the visibility and UI state of the option boxes using the remember credentials flags.

// RC
CheckBox autoLogin = (CheckBox) basicAuthView.findViewById(R.id.autoLoginCB);
CheckBox rememberCredentials = (CheckBox) basicAuthView.findViewById(R.id.rememberCredentialsCB);
CheckBox rememberUsername = (CheckBox) basicAuthView.findViewById(R.id.rememberUsernameCB);
// RC
button.setOnClickListener(new AuthenticationLoginListener(callback));
 
Button cancelButton = (Button) basicAuthView.findViewById(R.id.cancel);
cancelButton.setOnClickListener(new AuthenticationCancelListener(asm,callback));
 
EditText username = (EditText) basicAuthView.findViewById(R.id.username);
username.setEnabled(true);
EditText password = (EditText) basicAuthView.findViewById(R.id.password);
password.setEnabled(true);
String usernameFromRCStore = null;
String passwordFromRCStore = null;
String identityFromRCStore = null;
boolean rcUseCase = false;
// Try to get the user name or password stored by the SDK.
// Note: This is possible only if the Remember Credentials feature is
// enabled.
if (inputParams.containsKey(USERNAME))
{
  usernameFromRCStore = (String) inputParams.get(USERNAME);
}
if (inputParams.containsKey(PASSWORD))
{
  passwordFromRCStore = (String) inputParams.get(PASSWORD);
}
 
Object autoLoginAllowedObj = inputParams.get(OMMobileSecurityService.OM_PROP_AUTO_LOGIN_ALLOWED);
if (autoLoginAllowedObj != null)
{
  boolean autoLoginAllowed = ((Boolean) autoLoginAllowedObj);
  // feature enabled now set the visibility to true.
  if (autoLoginAllowed)
  {
    autoLogin.setVisibility(View.VISIBLE);
    Object alChecked = inputParams.get(OMSecurityConstants.OM_AUTO_LOGIN_PREF);
    if (alChecked != null)
    {
      autoLogin.setChecked((Boolean)alChecked);
    }
    rcUseCase = true;
  }
}
 
Object remCredObj = inputParams.get(OMMobileSecurityService.OM_PROP_REMEMBER_CREDENTIALS_ALLOWED);
if (remCredObj != null)
{
  boolean rememberCredentialsAllowed = ((Boolean) remCredObj);
  if (rememberCredentialsAllowed)
  {
    // feature enabled now set the visibility to true.
    rememberCredentials.setVisibility(View.VISIBLE);
    Object rcChecked = inputParams.get(OMSecurityConstants.OM_REMEMBER_CREDENTIALS_PREF);
    if (rcChecked != null)
    {
      rememberCredentials.setChecked((Boolean)rcChecked);
    }
    rcUseCase = true;
  }
}

Object remUserObj = inputParams.get(OMMobileSecurityService.OM_PROP_REMEMBER_CREDENTIALS_ALLOWED);
if (remUserObj != null)
{
  boolean rememberUsernameAllowed = ((Boolean) remUserObj);
  if (rememberUsernameAllowed)
  {
    // feature enabled now set the visibility to true.
    rememberUsername.setVisibility(View.VISIBLE);
    Object ruChecked = inputParams.get(OMSecurityConstants.
OM_REMEMBER_USERNAME_PREF);
    if (ruChecked != null)
    {
      rememberUsername.setChecked((Boolean)ruChecked);
    }
    rcUseCase = true;
  }
}
// pre filling
if (rcUseCase)
{
  if (usernameFromRCStore != null && usernameFromRCStore.length() > 0)
  {
    username.setText(usernameFromRCStore);
  }
  if (passwordFromRCStore != null && passwordFromRCStore.length() > 0)
  {
    password.setText(passwordFromRCStore);
  }
}
// RC
 

This next code sample shows how to control the visibility and UI state of the option boxes when the submit (or log on) button is pressed.

// Do the registration and then perform the authentication
EditText username = (EditText) basicAuthView.findViewById(R.id.username);
username.setEnabled(false);
 
EditText password = (EditText) basicAuthView.findViewById(R.id.password);
password.setEnabled(false);

 
Button button = (Button) basicAuthView.findViewById(R.id.login);
button.setEnabled(false);
 
Button cancelButton = (Button) basicAuthView.findViewById(R.id.cancel);
cancelButton.setEnabled(false);
// RC
CheckBox autoLogin = (CheckBox) basicAuthView.findViewById(R.id.autoLoginCB);
CheckBox rememberCredentials = (CheckBox) basicAuthView.findViewById(R.id.rememberCredentialsCB);
CheckBox rememberUsername = (CheckBox) basicAuthView.findViewById(R.id.rememberUsernameCB);
// RC
InputMethodManager imm = (InputMethodManager) asm.getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(username.getWindowToken(), 0);
 
String uname = username.getText().toString();
String pwd = password.getText().toString();
 
Map<String, Object> outputParams = new HashMap<String, Object>();
//sending the username passord for the authentication purpose.
outputParams.put(USERNAME, uname);
outputParams.put(PASSWORD, pwd);
// RC
//sending UI preferences for the current auth /login screen to the SDK 
outputParams.put(OMSecurityConstants.OM_AUTO_LOGIN_PREF,autoLogin.isChecked());
outputParams.put(OMSecurityConstants.OM_REMEMBER_CREDENTIALS_PREF,rememberCredentials.isChecked());
outputParams.put(OMSecurityConstants.OM_REMEMBER_USERNAME_PREF,rememberUsername.isChecked());
// RC
 
basicAuthView.invalidate();
 
callback.processLoginResponse(outputParams);

10.16 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:

http://developer.android.com/reference/android/content/SharedPreferences.html

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.17 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-11 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 user name 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.