7 iOS Applications

If you are an iOS app developer, you can use the client SDK that Oracle Mobile Cloud Service (MCS) provides for iOS. This SDK simplifies authentication with MCS and provides Objective-C wrapper classes for MCS platform APIs.

Getting the SDK for iOS

To get the MCS client SDK for iOS, go to the Oracle Technology Network’s MCS download page.

Contents of the iOS SDK

The iOS SDK contains the following items:

  • Documentation - Contains web-browser based documentation (html.zip) and a docset for browsing and accessing context-sensitive help from Xcode (oracle.mobile.cloud.Mobile_Client_SDK.docset.zip). To use html.zip, unzip the file and browse the main page from index.html. To use the docset, unzip the file into the usual location for Xcode docsets, typically something like ~/Library/Developer/Shared/Documentation/DocSets, where ~ is your home directory.

    This folder also contains a sample copy of the OMC.plist file that you will need to add to your app and populate with the configuration details for your mobile backend.

  • release-iphoneos - Release versions of the static libraries and header files. Also contains SyncStore initialization data. The static libraries are Universal (fat) binaries that contain armv7* code and support both the iPhone Simulator and real devices. The following static libraries are included:

    • libOMCCore.a - The Core static library file shared by all iOS applications. Contains the common libraries required by all other libraries.

    • libOMCAnalytics.a - The Analytics static library file, which allows you to insert events in your code that can then be collected and analyzed from the Analytics console.

    • libOMCLocation.a - The Location library, which lets you access details about location devices that have been registered in MCS and the places and assets they are associated with.

    • libOMCNotifications.a - The Notifications static library file, which allows you to set up your application to receive notifications sent from your mobile backend.

    • libOMCStorage.a - The Storage static library file, which allows you to write code to access storage collections that are set up with your mobile backend.

    • libOMCSynchronization.a - The Data Offline static library file, which allows you to cache application data when the device running your app is disconnected from the network, then synchronize the data when the network connection is reestablished.

  • thirdParty - The static library (libIDMMobileSDK.a), headers, and resource strings for the identity management (IDM) library.

  • mcs-tools.zip - The MCS Custom Code Test Tools, a set of command line tools for debugging custom APIs that you have associated with your app's mobile backend. Detailed instructions are located in the README file included in the zip.

Prerequisites for Developing iOS Apps

Before you start developing your app, you need to do some basic setup, such as adding iOS SDK frameworks, modifying configuration settings, and other steps.

Here’s what we assume:

  • You’re familiar with Xcode as your development environment. If you’re just starting, see https://developer.apple.com/xcode/.

  • You’ve already obtained the following things from Apple:

    • An Apple Developer account.

    • A unique secure certificate installed on your Mac or iPad (that is, on the machine where you’ll be developing your app).

    • An Application ID, which is used as the bundle identifier for your application in Xcode.

    • A Provisioning Profile. If you intend to install the Notifications static library from the client SDK and receive notifications in your iOS app, your Provisioning Profile must be enabled for notifications.

      If you haven’t done these things yet, see the iOS developer documentation at http://developer.apple.com.

Note:

You can also use the client SDK with Swift apps. See Writing Swift Applications Using the iOS SDK.

Adding the SDK to an iOS App

  1. Unzip the download file, oracle_mobile_ios_sdk-{n}.zip (where {n} is the version number of the SDK) into some directory on your machine.

  2. Drag and drop the contents of the zip to the Xcode project navigator.

    • Select Copy items if needed.

    • Select Create Groups.

    • Click Finish.

    Once the .a file for a specific library has been copied into your application’s development tree in Xcode, the corresponding platform API is available to your app through SDK calls. At this point, all of the SDK’s static libraries are available to your app. However, you need to complete the next steps so that the Identity Management library works properly.

  3. Select the target for your project, select the Build Phases tab, expand Link Binary with Libraries, click the + button, and add the following frameworks:

    • SystemConfiguration.framework

    • Security.framework

    • CoreLocation.framework

  4. Add the -ObjC flag to the Other Linker Flags settings.

  5. Expand the Documentation folder of the unpacked zip, copy the OMC.plist file, and place it in the root of your app’s main application bundle.

  6. Fill in your mobile backend environment details. See Configuring SDK Properties for iOS.

  7. If you are using Xcode 7 or higher, you need to account for the Application Transport Security (ATS) policy, which enforces remote communications to be over HTTPS.

    For development purposes only, add the following key in app’s Info.plist file to turn off the ATS policy for the app.

    <key>NSAppTransportSecurity</key> 
    <dict>
     <key>NSAllowsArbitraryLoads</key>
     <true/> 
    </dict>

    Note:

    You shouldn't use this setting in production. To make sure you provide optimal security for your app, study Apple's documentation for NSAppTransportSecurity and follow Apple's recommendations for disabling ATS for specific domains and applying proper security reductions for those domains.

iOS SDK Interdependencies

The client SDK is modular, so you can package just the libraries that your app needs. Just be aware of the following dependencies:

  • Every app must have the libOMCCore.a static library file.

  • If your app uses libOMCStorage.a, you must also include lilbOMCSynchronization.a.

  • If your app uses lilbOMCSynchronization.a, you must also include the SyncStore.momd folder, which contains initialization data.

  • If your app uses libOMCCxAEngagement.a, you must also include libOMCCxAAnalytics.a.

Configuring SDK Properties for iOS

To use the SDK in an iOS app, you need to add the OMC.plist configuration file to the app and fill it in with environment details for your mobile backend. In turn, the SDK classes use this information to access the mobile backend and construct HTTP headers for REST calls made to APIs.

You package the configuration file in the root of your app’s main bundle.

Here’s an example of the contents of the OMC.plist file. Pay careful attention to the hierarchy of elements.

Here’s the source code for the same example:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"
<plist version="1.0">
<dict>
  <key>mobileBackends</key>
  <dict>
    <key>FixItFast_Customer</key>
    <dict>
      <key>default</key>
      <true/>
      <key>baseURL</key>
      <string>https://fif.cloud.oracle.com</string>
      <key>appKey</key>
      <string>ebfbc8ea-9173-442b-8a5e-2fae63c64422</string>
      <key>authorization</key>
      <dict>
        <key>authenticationType</key>
        <string>OAuth</string>
        <key>OAuth</key>
        <dict>
          <key>tokenEndpoint</key>
          <string>https://oam.oracle.com/oam/oauth2/tokens</string>
          <key>clientID</key>
          <string>ddb7ff5a-0d86-4b4a-8164-ddad03734249</string>
          <key>clientSecret</key>
          <string>pFmzazXzNTBNVDyraQs7</string>
        </dict>
      </dict>
    </dict>
  </dict>
  <key>logLevel</key>
  <string>debug</string>
</dict>
</plist>

Here are the key entries in the OMC.plist file. You can obtain the necessary environment details from the Settings and Clients pages of the mobile backend.

  • mobileBackends — a dictionary entry containing a nested dictionary for your mobile backend such as FixItFast_Customer. (When you call OMCMobileBackend in an app, you need to supply the value of that entry as a parameter to OMCMobileBackendManager.) That entry, in turn, contains entries for appKey, baseURL, authenticationType, mobileBackendID, anonymousKey, and, optionally, networkConnectionTimeout. See the example below.

  • baseURL — The URL your application uses to connect to its mobile backend.

  • appKey — The application key, which is a unique string assigned to your app when you register it as a client in MCS. See Registering an App as a Client in MCS. If you have not registered the app as a client in MCS, assign a placeholder value for this entry.

  • networkConnectionTimeout — (Optional) The network timeout for API calls, in seconds. Should you need to do any network performance tuning, you can add this property, though you should use it with care. Keep in mind that app responsiveness issues might be better addressed in the app design itself. The default timeout is 60 seconds.
  • logLevel — Determines how much SDK logging is displayed in the app’s console. The default value is error. Other possible values (in increasing level of detail) are warning, info, and debug. It is also possible to set the value to none.

  • logHTTPRequestBody — When set to true, the SDK will also log the HTTP and HTTPS headers and body in the requests to MCS.

  • logHTTPResponseBody — When set to true, the SDK will also log the HTTP and HTTPS headers and body in responses from MCS.

  • authorization — Use this key to define the type of authentication the app will be using and specify the required credentials. The contents and sub-elements of the authorization key depend on the type of authentication.

    • authenticationType — Defines the type of authentication mechanism being used in your mobile application. Possible values are OAuth (for OAuth Consumer), basic (for HTTP Basic), SSO, SSOTokenExchange and Facebook. Include a dictionary for each supported authentication type with the required credentials as explained in the sections that follow.

    • offlineAuthenticationEnabled — If set to true, offline login will be allowed. Offline login is not supported for OAuth so this key will be ignored.

OAuth Consumer

For OAuth, set the value of the authenticationType property to OAuth and fill in the OAuth credentials provided by the mobile backend.
  • tokenEndpoint — The URL of the OAuth server your application goes to, to get its authentication token.

  • clientID — The unique client identifier assigned to all applications when they’re first created in your mobile backend.

  • clientSecret — The unique secret string assigned to all applications when they’re first created in your mobile backend.

The resulting authorization property might look something like this:

<key>authorization</key>
<dict>
    <key>authenticationType</key>
    <string>oauth</string>
      <key>OAuth</key>
      <dict>
        <key>tokenEndpoint</key>
        <string>https://oam.oracle.com/oam/oauth2/tokens</string>
        <key>clientID</key>
        <string>ddb7ff5a-0d86-4b4a-8164-ddad03734249</string>
        <key>clientSecret</key>
        <string>pFmzazXzNTBNVDyraQs7</string>
      </dict>
 </dict>

SSO

For SSO, set the value of the authenticationType property to SSO and fill in the OAuth credentials provided by the mobile backend. (For tokenEndpoint, you use the mobile backend’s OAuth token endpoint.)

The resulting authorization property might look something like this:

<key>authorization</key>
<dict>
    <key>authenticationType</key>
    <string>SSO</string>
		<key>SSO</key>
		<dict>
      <key>tokenEndpoint</key>
      <string>https://oam-server.oracle.com/oam/oauth2/tokens</string>
      <key>clientID</key>
      <string>ddb7ff5a-0d86-4b4a-8164-ddad03734249</string>
      <key>clientSecret</key>
      <string>pFmzazXzNTBNVDyraQs7</string>
    </dict>
</dict>

SSO with a Third-Party Token

For SSO with a third-party token, set authenticationType to SSOTokenExchange and fill in the appropriate credentials. You also need to fill in auth credentials provided by the mobile backend, depending on how you have integrated the token issuer.

If you are using JWT tokens and have integrated the token issuer by registering a configuration via a policy in MCS, you need to nest the mobile backend’s HTTP Basic credentials and then include the mobile backend’s OAuth credentials as a separate key. The resulting authorization property might look something like this:

<key>authorization</key>
<dict>
  <key>authenticationType</key>
  <string>SSOTokenExchange</string>
  <key>SSOTokenExchange</key>
  <dict>
    <key>mobileBackendID</key>
    <string>ddb7ff5a-0d86-4b4a-8164-ddad03734249</string>
    <key>anonymousKey</key>
    <string>UFJJTUVfREVDRVBUSUNPTl9NT0JJTEVfQU5PTllNT1VTX0FQUElEOnZrZWJxUmwuamEwbTdu</string>
  </dict>
  <key>OAuth</key>
  <dict>
    <key>tokenEndpoint</key>
    <string>https://p2mob1813rc1f.identity.dc1.c9dev2.oraclecorp.com/oam/oauth2/tokens</string>
    <key>clientID</key>
    <string>c437c1ed-fef0-4e88-802c-b85525fa0d6d</string>
    <key>clientSecret</key>
    <string>MtHoeHcRrWlDLiKcHJC8</string>
	</dict>
</dict>

If you have integrated the IdP token issuer by uploading certificates into MCS, you need to nest the mobile backend’s HTTP Basic credentials. The resulting authorization property might look something like this:

<key>authorization</key>
<dict>
    <key>authenticationType</key>
    <string>SSOTokenExchange</string>
    <key>SSOTokenExchange</key>
    <dict>
      <key>mobileBackendID</key>
      <string>ddb7ff5a-0d86-4b4a-8164-ddad03734249</string>
      <key>anonymousKey</key>
      <string>UFJJTUVfREVDRVBUSUNPTl9NT0JJTEVfQU5PTllNT1VTX0FQUElEOnZrZWJxUmwuamEwbTdu</string>
    </dict>
</dict>

HTTP Basic

For HTTP Basic authentication, set the value of the authenticationType property to basic and fill in the HTTP Basic credentials provided by the mobile backend.
  • mobileBackendID — The unique identifier assigned to a specific mobile backend. It gets passed in an HTTP header in every REST call made from your application to MCS, to connect it to the correct mobile backend. When calling platform APIs, the SDK handles the construction of the mobileBackendID header for you.

  • anonymousKey — When using HTTP Basic authentication, a unique string that allows your app to access APIs that don’t require login. In this scenario, the anonymous key is passed to MCS instead of an encoded user name and password combination.

You can also enable offline login for Basic authentication by setting the offlineAuthenticationEnabled property to true.

The resulting authorization property might look something like this:

<key>authorization</key>
<dict>
    <key>authenticationType</key>
    <string>Basic</string>
    <key>offlineAuthenticationEnabled</key>
    <true/>
    <key>Basic</key>
    <dict>
      <key>anonymousKey</key>
      <string>UFJJTUVfREVDRVBUSUNPTl9NT0JJTEVfQU5PTllNT1VTX0FQUElEOml6LmQxdTlCaWFrd2Nz</string>
      <key>mobileBackendID</key>
      <string>4fb9cabd-d0e2-40f8-87b5-d2d44cdd7c68</string>
    </dict>
</dict>

Loading a Mobile Backend's Configuration into an iOS App

For any calls to MCS APIs using the iOS SDK to successfully complete, you need to have the mobile backend’s configuration loaded from the app’s OMC.plist file. You do this using the OMCMobileBackend class:

/**
 * Returns the mobile backend named "FixItFast_Customer" that is configured in the OMC.plist file
 */
- (OMCMobileBackend *) myMobileBackend{
    
    return [[OMCMobileBackendManager sharedManager] mobileBackendForName:@"FixItFast_Customer"];
    
}

Authenticating and Logging In Using the SDK for iOS

Here is are some methods you can use for authentication through MCS in your iOS apps. All of code given uses the OMCAuthorization.h class and relies on the following imports:

#import "OMCCore/OMCAuthorization.h"
#import "OMCCore/OMCMobileBackend.h"
#import "OMCCore/OMCMobileBackendManager.h"

OAuth Consumer and HTTP Basic

You can use the following method to handle a user logging in with a user name and password.

- (void) authenticate:(NSString *)userName
             password:(NSString *)password
      completionBlock: (OMCAuthorizationAuthCompletionBlock) completionBlock;

This method terminates the connection to MCS and clears the user name and password from the iOS keychain:

-(void) logout: (OMCAuthorizationLogoutCompletionBlock) completionBlock;

SSO

For apps that allow login through enterprise SSO, use:

-(void) authenticateSSO: (UIViewController*) presentingViewController
           clearCookies: (BOOL) clearCookies
        completionBlock:(OMCAuthorizationAuthCompletionBlock) completionBlock;

SSO with a Third-Party Token

First, your app needs to get a token from the third-party token issuer. The way you can obtain the token varies by issuer. For detailed information on obtaining third-party tokens and configuring identity providers in MCS, see Third-Party SAML and JWT Tokens.

Once you have the token, initialize the authorization agent and use the token in your authorization call.

-(void) authenticateSSOTokenExchange:(NSString*) token
                    storeAccessToken:(BOOL) storeToken
                     completionBlock:(OMCAuthorizationAuthCompletionBlock) completionBlock;

-(NSError*) authenticateSSOTokenExchange:(NSString*) token
                        storeAccessToken:(BOOL) storeToken;

SSO with a Third-Party Token — Staying Logged In

You can also code the app to keep the user logged in, even when closing and restarting the app.

In the authenticateSSOTokenExchange method, if storeAccessToken is set to YES, the token is stored in secure store and the user remains logged in until the token expires.

You can use the loadSSOTokenExchange() method in the app launch sequence to load the token from the keychain. (If a token can’t be retrieved, the method returns NO).

Here’s some code that tries to load a saved token and, if it fails, restarts the authentication process:

OMCAuthorization* auth;
if ( [auth loadSSOTokenExchange] ){
	NSLog(@"## Token already found, login skipped.");
    ...
}
else{
	[auth authenticateSSOTokenExchange:thirdPartyToken
				  storeAccessToken:YES
				   completionBlock:^(NSError * _Nullable error) {
					   
					   if( error ){
						   //Show error popup
					   }
					   else{
							// Login success.
							...
					   }
				   }];
}

When you have the token stored in the secure store, it remains associated with the mobile backend that the app originally used. Therefore, if the app is updated to use a different mobile backend (or mobile backend version), you need to clear the saved token (using clearSSOTokenExchange) and re-authenticate.

Note:

The default expiration time for a stored token that was obtained through token exchange is 6 hours. You can adjust this time by changing the Security_TokenExchangeTimeoutSecs policy.

Calling Platform APIs Using the SDK for iOS

Once the mobile backend’s configuration info is loaded into the app, you can make calls to SDK classes based on the iOS Core library classes.

The iOS Core library (libOMCCore.a) provides three public interfaces that are common across all other iOS libraries:

  • OMCMobileBackendManager

  • OMCMobileBackend

  • OMCServiceProxy

The root class in the SDK is the OMCMobileBackendManager. An instance of OMCMobileBackendManager manages one or more OMCMobileBackend objects. An OMCMobileBackend object is used to manage connectivity, authentication, and other transactions between your application and its associated mobile backend, including calls to platform APIs and any custom APIs you have defined. In turn, an OMCMobileBackend instance manages instances of OMCServiceProxy. These instances correspond to platform services in MCS (for example, Analytics, Notifications, and so on).

It retrieves the information it needs about each mobile backend (the mobile backend name and ID, as well as authentication information) from the app’s OMC.plist file.

Here’s an example of using these classes to call APIs.

//Get mobile backend, here "FixItFast_Customer" is your backend name from the OMC.plist configuration.
OMCMobileBackend* mbe = [[OMCMobileBackendManager sharedManager] mobileBackendForName:@"FixItFast_Customer"];

//Authenticate with your credentials; if returns nil, then authenticated successfully.
NSError* error = [mbe.authorization authenticate:@"username" 
                                        password:@"password"];
//Get analytics client
OMCAnalytics* analytics = [mbe analytics];

//Get storage client
OMCStorage* storage = [mbe storage];

//Get notifications client
OMCNotifications* notifications = [mbe notifications];

To access the required headers to compile the preceding code, you need to import the following headers into your code:

#import "OMCMobileBackend.h"
#import "OMCMobileBackendManager.h"
#import "OMCAuthorization.h"
#import "OMCAnalytics.h"
#import "OMCMobileBackend+OMC_Analytics.h"
#import "OMCStorage.h"
#import "OMCMobileBackend+OMC_Storage.h"
#import "OMCNotifications.h"
#import "OMCMobileBackend+OMC_Notifications"

Note:

Methods written in Objective-C that are used in the MCS SDK for iOS can also be mapped to Swift. For more information, see Writing Swift Applications Using Mobile Client SDK.

Calling Custom APIs Using the SDK for iOS

The SDK provides the OMCCustomCodeClient class to simplify the calling of custom APIs in MCS. You can call a REST method (GET, PUT, POST, or DELETE) on an endpoint where the request payload is JSON or empty and the response payload is JSON or empty.

Using this class, you invoke a REST method (GET, PUT, POST, or DELETE) on an endpoint where the request payload is JSON or empty and the response payload is JSON or empty.

In addition you can provide a completion handler to be called when the method invocation is complete (meaning that the handler runs asynchronously).

If the completion handler is set, it will be invoked in the UI (main) thread upon completion of the method invocation, allowing update of UI items. The completion block will contain the format-specific data for a JSON object, namely an NSDictionary or NSArray. Use the completion block for any returned data or errors, HTTP or system.

All of the required MCS headers, such as Authorization (assuming the user has authenticated), will automatically be inserted into the request.

Use of OMCCustomCodeClient might look something like this:

#import "OMCCore/OMCMobileBackend.h"
#import "OMCCore/OMCCustomCodeClient.h"
...
 
// A GET, PUT, POST, or DELETE method may be specified here - sent or returned JSON data object may be nil as appropriate.
OMCMobileBackend *backend = ...
OMCCustomCodeClient *ccClient = backend.customCodeClient;
NSDictionary *jsonPayload = @{@"myKey", @"myValue"};
[ccClient invokeCustomRequest: @"API2/endpoint2" 
                       method: "@PUT" 
                         data: jsonPayload, 
                   completion: ^(NSError* error,
                                NSHTTPURLResponse *response,
                                id responseData) {
        // error will be nil if no problems occurred, otherwise it will contain the error object
        // response will be complete HTTP response
        // response data will be Map or Array for JSON object if success or nil if error
    }];

Video: Configuring an Existing iOS App to Work with Mobile Cloud

For a demonstration on how to configure an iOS app to use mobile backends and call MCS platform APIs, see this video on YouTube channel for the Oracle Mobile Platform: