9 Developing Mobile Services Applications with the iOS Client SDK

This chapter describes how to develop Mobile Services applications with the iOS Client SDK. This SDK serves as a Security Layer for developing secure mobile applications on iOS. Every native iOS app must implement this SDK to use Mobile and Social. The iOS SDK supports devices running iOS 4.3 and above. This chapter provides the following sections:

9.1 Getting Started With the iOS Client SDK

This SDK (oamms_sdk_for_ios.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 IDM Mobile iOS Client SDK is provided as a static library. It contains the following modules:

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

  • Secure Storage Module - Provides APIs to store and retrieve sensitive data using the iOS Keychain feature.

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

  • Cryptography Module - Provides intuitive Objective C APIs for common cryptography tasks.

  • REST Web Service Handler Module - Provides access to REST Web services protected by Access Manager.

Note:

You must have the Xcode IDE (integrated development environment) installed on an Intel-based Mac running Mac OS X Snow Leopard or later to develop applications for iOS mobile devices.

For more information, see the iOS Dev Center website:

https://developer.apple.com/devcenter/ios/index.action

9.1.1 Getting Started Using the iOS Client SDK With XCode

Follow these steps to set up your XCode environment.

  1. Add libIDMMobileSDK.a to XCode by following these steps:

    1. Download libIDMMobileSDK.a to your development environment and add it to a project folder.

    2. Launch XCode and open your project.

    3. Click your project to select it, then click your target and click the Build Phases tab.

    4. Expand Link Binary With Libraries and click the + button.

    5. Select Other and choose libIDMMobileSDK.a.

  2. Download the PublicHeaders and PublicResources folders located in oamms_sdk_for_ios.zip.

    The PublicHeaders directory contains the IDM Mobile SDK header files.

    The PublicResources directory contains the IDM Mobile SDK resources.

  3. Choose Add Files to Your-Project-Name to add the contents of PublicHeaders and PublicResources to your project.

  4. Add frameworks by opening Build Phases in your project and expand Link Binary with Libraries. Click the + button to add the following frameworks one after the other:

    • SystemConfiguration.framework

    • Security.framework

    • CoreLocation.framework

    Important:

    Before linking your project, in Build Settings add as a single line both the -ObjC and -all_load flags to "Other linker flags." Without these flags your application will crash with a "selector not recognized" runtime exception.

    Because libIDMMobileSDK.a extends pre-existing classes with categories, the linker does not know how to associate the object code of the core class implementation with the category implementation. This prevents objects created in the resulting application from responding to a selector that is defined in the category.

    For background information and steps that describe how to add flags to your project, see the following page:

    http://developer.apple.com/library/mac/#qa/qa1490/

    You can now start coding using the IDM Mobile iOS Client SDK.

    Important:

    The iOS SDK supports devices running iOS 4.3 and above.

9.2 Invoking Authentication Services With the iOS Client SDK

This section provides sample code that demonstrates how to authenticate with the Mobile and Social server.

Refer to "Configuring Mobile Services" in Oracle Fusion Middleware Administrator's Guide for Oracle Access Management for information about configuring a service provider.

Step 1: Initialize Required Objects

Create an NSMutableDictionary object and populate parameters:

NSMutableDictionary *sdkProps = [[NSMutableDictionary alloc] init]; 

[sdkProps setObject:OM_PROP_AUTHSERVER_OAMMS forKey:OM_PROP_AUTHSERVER_TYPE];
[sdkProps setObject:@"http://oammsurl" forKey:OM_PROP_OAMMS_URL];
[sdkProps setObject:@"myApp" forKey:OM_PROP_APPNAME];
[sdkProps setObject:@"MobileServiceDomain" forKey:OM_PROP_OAMMS_SERVICE_DOMAIN];

Next, create the OMMobileSecurityService object and pass the Dictionary object as properties.

OMMobileSecurityService *mss = [[OMMobileSecurityService alloc]                
                                           initWithProperties:sdkProps 
                                                     delegate:self]; 
 

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

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

The OM_PROP_OAMMS_SERVICE_DOMAIN property key is the name of the Service Domain in Mobile and Social server that contains the Application Profile for this application.

Next, call the OMMobileSecurityService setup method.

[mss setup];

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

The setup call is an asynchronous call and on completion the iOS client SDK calls the following delegate method:

didReceiveApplicationProfile: (NSDictionary *)applicationProfile error:  
 (NSError *)error

Note:

The name of the delegate to be implemented by the application developer is OMMobileServiceDelegate.

This method returns an NSDictionary object that contains the application profile details.

Note:

The thread that calls [mss setup] must have a run loop running. If you invoke [mss setup] from a thread other than the main thread, ensure that a run loop is running in default mode.

For more information, see the iOS Developer Library Threading Programming Guide:

http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html

Step 2: Complete the Authentication Process

Upon receiving the application profile, start the authentication process. Supply your own customized login and KBA (knowledge-based authentication) views in the authentication request as in the following sample. If a customized view is not required, pass nil for authnReq in startAuthenticationProcess. If a customized login views are not passed, the SDK will throw a default login and KBA view.

OMAuthenticationRequest *authnReq = [OMAuthenticationRequest alloc] init];
authnReq.kbaView = myKBAView;
authnReq.authView = myLoginView;
[[mss startAuthenticationProcess:authnReq presenterViewController:myViewController];
 

This starts the authentication process and the iOS Client SDK interacts with the Mobile and Social server to complete the authentication process. If the user is already authenticated and the authentication token is still valid, the Mobile and Social server simply returns the cached token. Otherwise, the server prompts the user to provide login credentials. If the Mobile and Social server is configured to use Knowledge Based Authentication, the iOS Client SDK automatically handles the details.

Next, the iOS Client SDK calls your delegate's didFinishAuthentication:error: method. The method returns OMAuthenticationContext, which has your token details.

Use the OMMobileSecurityService object's [mobileSecurityService authenticationContext] method to retrieve OMAuthenticatonContext at any time. For details about OMAuthenticationContext, see the API documentation.

- (void)didFinishAuthentication:(OMAuthenticationContext *)context error:(NSError *)error
{
  if (context == nil || error != nil)
  {
     NSString *msg = [[NSString alloc] initWithFormat:@"%@-%d: %@",
     [error domain],
     [error code], [error localizedDescription]];
     UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:@"Err" message:msg delegate:self
                               cancelButtonTitle:@"OK" otherButtonTitles:nil];
     [alertView show];
     [msg release];
     [alertView release];
     return;
  }
 // If successful, proceed with your remaining actions. 
 // This example gets the authenticated user's attributes 
 // and presents it using User Profile Viewer.

 OMUserRoleProfileService* ups = [mss userRoleProfileService];
 OMUserManager *um = [ups getuserManager];
 OMUser *user = [um searchUser:context.userName attributes:nil shouldPreFetch:NO error:&error];
 self.user = user;
 [detailPaneController showProfileButton];
}

At this point your application can use the token obtained from the Mobile and Social server to make additional web service calls.

Note:

The iOS Client SDK does not consume a significant amount of memory. The SDK stores registration handles, authentication handles, application profiles, and security profiles. If iOS sends a low memory warning notification, the SDK persists its cache and releases its memory. When required, the SDK can read persisted data either from a file or from KeyChainItem (covered later), as appropriate.

9.3 Initialization Properties

You can set the following properties when you initialize the SDK.

Table 9-1 iOS Client SDK Initialization Properties

Property Name Property Value(s) Type

OM_PROP_AUTHSERVER_TYPE

  • OM_PROP_AUTHSERVER_OAMMS

NSString

OM_PROP_OAMMS_HOST

A valid host name passed as an NSString object. Alternatively, you can pass host, port, and port type details using the OM_PROP_OAMMS_URL object.

NSString

OM_PROP_OAMMS_PORT

A valid port number passed as an NSString object. Alternatively, you can pass host, port, and port type details using the OM_PROP_OAMMS_URL object.

NSString

OM_PROP_OAMMS_PORT_IS_SSL

Either true or false. Alternatively, you can pass host, port, and port type details using the OM_PROP_OAMMS_URL object.

NSString

OM_PROP_OAMMS_URL

An NSURL Object or a valid NSString object that can be used to create NSURL.

If you do not use this property, specify the following properties:

  • OM_PROP_OAMMS_HOST

  • OM_PROP_OAMMS_PORT

  • OM_PROP_OAMMS_PORT_IS_SSL

NSString or NSURL

OM_PROP_OAMMS_SERVICE_DOMAIN

Required property. Any valid Service Domain name passed as an NSString object.

NSString

OM_PROP_APPNAME

Required property. A valid application name passed as an NSString object.

NSString

OM_PROP_OFFLINE_AUTH_ALLOWED

Either true or false.

This is an optional property, however, if it is not specified, offline authentication is not allowed.

The Mobile and Social server can also specify this property in the application profile. The server setting overrides the application setting.

NSString

OM_PROP_SESSION_TIMEOUT_VALUE

A login session time-out value passed as an NSNumber object. The SDK only takes the integer value of the number.

This is an optional property. If this property is not specified or if the value is zero, the login session is valid until the server invalidates the session.

The Mobile and Social server can also specify this property in the application profile. The server setting overrides the application setting.

NSNumber

OM_PROP_IDLE_TIMEOUT_VALUE

An idle connection time-out value passed as an NSNumber object. The SDK only takes the integer value of the number.

This is an optional property. If this property is not specified or if the value is zero, the login session is valid until the server invalidates the session.

The Mobile and Social server can also specify this property in the application profile. The server setting overrides the application setting.

NSNumber

OM_PROP_MAX_LOGIN_ATTEMPTS

The maximum number of login attempts allowed by the user.

This is an optional property. If this property is not specified, only one login attempt is allowed.

The Mobile and Social server can also specify this property in the application profile. The server setting overrides the application setting.

NSNumber

OM_PROP_KEYCHAIN_DATA_PROTECTION

Use this property to specify the KeyChain Item protection level.

Must be one of the following values:

  • OM_KEYCHAIN_DATA_ACCESSIBLE_WHEN_UNLOCKED

  • OM_KEYCHAIN_DATA_ACCESSIBLE_AFTER_FIRST_UNLOCK

  • OM_KEYCHAIN_DATA_ACCESSIBLE_ALWAYS

  • OM_KEYCHAIN_DATA_ACCESSIBLE_WHEN_UNLOCKED_THIS_DEVICE_ONLY

  • OM_KEYCHAIN_DATA_ACCESSIBLE_AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY

  • OM_KEYCHAIN_DATA_ACCESSIBLE_ALWAYS_THIS_DEVICE_ONLY

This is an optional property. If it is not specified, the property defaults to the highest level: OM_KEYCHAIN_DATA_ACCESSIBLE_WHEN_UNLOCKED_THIS_DEVICE_ONLY

NSString

OM_PROP_LOCATION_UPDATE_ENABLED

Either true or false.

This is an optional property and the default value is false. Location update consumes battery on the device and should be enabled only when required.

NSString

OM_PROP_LOCATION_UPDATE_DISTANCE_FILTER

Location update (when enabled) is sent only when the device moves beyond the specified distance in meters.

Use this property to control the frequency of updates generated.

The Mobile and Social server can also specify this property in the Mobile Custom Attributes section with the key LocationUpdateEnabled and a numeric value. The server setting overrides the application setting. When location update is enabled and the distance filter is not set or is invalid, the default distance filter is taken as 1000m.

NSNumber


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

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. The server setting overrides the application setting.

For information about the cryptography module included in the Mobile and Social iOS Client SDK, see Section 9.10, "Using the Cryptography Module."

Table 9-2 Cryptography Scheme Property Attributes for the iOS Client SDK

Property Value Attribute Name Attribute Value

OM_PROP_CRYPTO_SCHEME

OM_PROP_CRYPTO_PLAINTEXT

CryptoScheme

PlainText

OM_PROP_CRYPTO_AES

AES

OM_PROP_CRYPTO_SHA1

SHA-1

OM_PROP_CRYPTO_SHA224

SHA-224

OM_PROP_CRYPTO_SHA256

SHA-256

OM_PROP_CRYPTO_SHA384

SHA-384

OM_PROP_CRYPTO_SHA512

SHA-512

OM_PROP_CRYPTO_SSHA1

SaltedSHA-1

OM_PROP_CRYPTO_SSHA224

SaltedSHA-224

OM_PROP_CRYPTO_SSHA256

SaltedSHA-256

OM_PROP_CRYPTO_SSHA384

SaltedSHA-384

OM_PROP_CRYPTO_SSHA512

SaltedSHA-512


9.4 About Offline Authentication

Offline authentication is supported for the Mobile and Social authentication flow.

The OMAuthenticationRequest object that is passed to the startAuthenticationProcess:presenterViewController: method has a property called connectivityMode. This property accepts values from the enum OMConnectivityMode that is defined in the OMAuthenticationRequest.h file.

The values are described as follows.

  • OMConnectivityOnline - Always authenticates with the server. Fails if the device cannot reach the Internet.

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

  • OMConnectivityAuto - Authentication happens with the server if the server is reachable. Otherwise, authentication happens offline if the device is not connected to the Internet.

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 setting (discussed in the "Initialization Properties" section), the locally stored credentials are wiped off 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.

9.5 Invoking Relying Party Authentication

Relying Party authentication is a feature of the Oracle Mobile and Social server that enables authentication against third party OpenId and OAuth providers like Google, Twitter, Facebook, and so on. Refer to the "Configuring Internet Identity Services" chapter in the Administrator's Guide for Oracle Access Management for more information.

For Relying Party authentication, the SDK can be invoked using the same APIs that you use to authenticate against the Mobile and Social server. When you configure the Service Domain for authentication against the Internet Identity Service, the SDK automatically follows the Relying Party authentication flow. After successful authentication, control is returned back to the app using the URL scheme configured in the Mobile and Social server.

Add this code snippet to your application in the application:openURL:sourceapplication:annotation method of the UIApplicationDelegate object to complete the flow. This helps pass the information received from the server to the SDK to signify that authentication has completed.

// Called when application in invoked via some URL
- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation
{
 
    ...
    ...
 
    NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] 
                                     initWithCapacity:1];
    [userInfo setObject:url forKey:OM_RESPONSE_URL];
 
    //Post the notification to IDM Mobile SDK
    [[NSNotificationCenter defaultCenter] 
     postNotificationName:OM_PROCESS_URL_RESPONSE
                   object:self
                 userInfo:userInfo];
 
    ...
    ...
 
    return TRUE;
}

After authentication succeeds, you can access the token from the provider (if any) with the key OM_ACCESS_TOKEN from the dictionary OMAuthenticationContext.accessTokens. If emailid is configured, it is available as OMauthenticationContext.userName.

9.6 Invoking User Profile Services With the iOS Client SDK

Before working with the code samples in this section, see "Building Applications With User Profile Services" for notes and information that are not specific to this SDK.

The code samples in this section are organized into the following three categories:

9.6.1 Working With People

To search and retrieve user details, get the handle of OMUserManager from the OMMobileSecurityService object. See "Invoking Authentication Services With the iOS Client SDK" for information about the OMMobileSecurityService object.

OMUserManager provides synchronous and asynchronous APIs to search and get user details.

All asynchronous operations return an OMAsyncOpHandle object. You can use this object to cancel the operation before it completes. Cancelling an operation after it completes has no effect on it.

- (id)getAttribute: (NSString *)attrName returningError: (NSError **)error;
- (NSArray *)searchUsersWithFilter: (NSDictionary *)filter
                                          isSimpleSearch: (BOOL)simpleSearch
                                   attributesToBeFetched: (NSArray *)attributesToFetch
                                                pageSize: (NSInteger)pageSize
                                            pagePosition: (NSInteger)pagePosition
                                                   error: (NSError **)error;
- (OMAsyncOpHandle *)getAttributeAsynchronously: (NSString *)attrName;
- (OMAsyncOpHandle *)searchUsersAsynchronouslyWithFilter:(NSDictionary *)filter
                                          isSimpleSearch:(BOOL)simpleSearch
                                   attributesToBeFetched:(NSArray *)attributesToFetch
                                                pageSize:(NSInteger)pageSize
                                            pagePosition:(NSInteger)pagePosition;

- (OMUser *)searchUser: (NSString *)user attributes: (NSArray *)attributes
                                     shouldPreFetch: (BOOL)preFetch
                                              error: (NSError **)error;
- (OMAsyncOpHandle *)searchUserAsynchronously: (NSString *)user 
                                   attributes: (NSArray *)attributes
                               shouldPreFetch: (BOOL)preFetch
                                        error: (NSError **)error;
 
- (OMAsyncOpHandle *)searchAsynchronouslyUser: (NSString*)user
                                   attributes: (NSArray *)attributes
                               shouldPreFetch: (BOOL)preFetch;
- (NSError *)deleteUser: (NSString *)userName;
- (OMAsyncOpHandle *)deleteAsynchronouslyUser:(NSString*)userName;
- (NSError *)createUserWithAttributes: (NSDictionary *)attributes;
- (OMAsyncOpHandle *)createUserAsynchronouslyWithAttributes:(NSDictionary *)attributes;
- (OMAsyncOpHandle *)modifyAsynchronouslyUser: (NSString*)user
                                   attributes: (NSDictionary *)attributes;

9.6.2 Working With Groups

To search and retrieve group details, get the handle of OMRoleManager from OMMobileSecurityService. See "Invoking Authentication Services With the iOS Client SDK" for information about the OMMobileSecurityService object.

OMRoleManager provides synchronous and asynchronous APIs to search for groups, add members to groups, and delete members from groups.

All asynchronous operations return an OMAsyncOpHandle object. You can use this object to cancel the operation anytime before it completes. Cancelling an operation after it completes has no effect on it.

- (OMRole *)getRoleByName: (NSString *)roleName
                    error: (NSError **)error;
- (OMAsyncOpHandle *)getAsynchronouslyRoleByName: (NSString *)roleName;
- (NSError *)deleteRoleByName: (NSString *)roleName;
- (OMAsyncOpHandle *)deleteAsynchronouslyRoleByName:(NSString*)name;
- (OMUser *)getUserInfo: (NSString *)userName fromRole: (NSString *)roleName
               error: (NSError **)error;
- (OMAsyncOpHandle *)getAsynchronouslyUserInfo:(NSString *)user
                                      fromRole:(NSString *)roleName;
- (NSError *)deleteMember: (NSString *)memberName
                 fromRole: (NSString *)roleName;
- (OMAsyncOpHandle *)deleteAsynchronouslyMember:(NSString *)memberName
                                       fromRole:(NSString*)roleName;

- (OMAsyncOpHandle *)createAsynchronouslyRoleWithAttributes:(NSArray*)attributes
                                                 withValues:(NSArray*)values;
- (OMAsyncOpHandle *)modifyAsynchronouslyRole:(NSString*)role
                                   attributes:(NSArray*)attributes
                                       values:(NSArray*)values;
- (OMAsyncOpHandle *)addUserAsynchronouslyToRole:(NSString *)roleName
                                  withAttributes:(NSArray*)attributes
                                      withValues:(NSArray*)values;

9.6.3 Working With Organizations

Use the following APIs to request information about managers and their reports.

Get a User's Manager

The following APIs are available in OMUser.

- (OMUser *)getManager: (NSError **)error;
- (OMAsyncOpHandle *)getManagerAsynchronously;

Get a Given User's Reports

The following APIs are available in OMUser.

- (NSArray *)getReporteesWithAttributes: (NSArray *)attributes returningError: (NSError **)error;
- (OMAsyncOpHandle *)getReporteesAsynchronouslyWithAttributes:(NSArray *)attributes;

9.7 Invoking the Mobile Single Sign-on Agent App

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

9.7.1 Invoking the Mobile Single Sign-on Agent App From a Web Browser

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

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

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

    The "Create Authentication Scheme" tab opens.

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

    • Name: MobileSSOScheme

    • Authentication Level: 2

    • Challenge Method: FORM

    • Challenge Redirect URL: /oam/server/

    • Authentication Module: LDAP

    • Challenge URL: /mobilesso?serviceDomain=MobileServiceDomain

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

    • Context Type: customWar

    • Context Value: /oic_rest

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

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

      Authentication Scheme: MobileSSOScheme

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

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

9.8 Invoking REST Web Services

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

The Mobile and Social SDK provides the OMRESTRequest class to access REST web services protected by Access Manager. First, use the SDK to authenticate against the OAM server using Mobile and Social services.

Next, initialize the OMRESTRequest object by passing a OMMobileSecurityService object and a delegate object. You can use either of the following methods:

executeRESTRequest: convertDataToJSON: isJsonRepresentation returningResponse: error:  

- or -

executeRESTRequestAsynchronously: convertDataToJSON:

The former is a synchronous call and the latter is an asynchronous call. The asynchronous call returns the result through the following OMRESTRequestDelegate method:

didFinishExecutingRESTRequest: data: urlResponse: error: asyncHandle:

The following example demonstrates the asynchronous API of the OMRESTRequest object.

- (void)someMethod
{
    OMMobileSecurityService *mss = ...;
    ...
    //Initialize OMRESTRequest object. In this example, instead of using
    //"initWithMobileSecurityService: delegate:" method, we use init method
    //and set the properties
    OMRESTRequest *restReq = [[OMRESTRequest alloc] init];
    restReq.delegate = self;
    restReq.mobileService = mss;

    NSURL *url = [[NSURL alloc] initWithString:@"http://myresturl.example.com/resturl"];
    NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithCapacity:1];

    //It is important to set the User-Agent to the value configured in OAM 11g R2
    //Webgate user defined parameters.
    [dictionary setObject:@"OAMMS-Agent" forKey:@"User-Agent"];
    NSMutableURLRequest *urlRequest = [[NSMutableURLRequest alloc] initWithURL:url];
    [urlRequest setAllHTTPHeaderFields:dictionary];
    [url release];
    [dictionary release];
    [urlRequest setHTTPMethod:@"GET"];
    OMAsyncOpHandle *opHandle = [restReq executeRESTRequestAsynchronously:urlRequest
                                                        convertDataToJSON:FALSE];
    [urlRequest release];
    OMLog(@"%@", opHandle);
}

-(void) didFinishExecutingRESTRequest:(OMRESTRequest *)RESTRequest
                                 data:(id)data
                          urlResponse:(NSURLResponse *)urlResponse
                                error:(NSError *)error
                          asyncHandle:(OMAsyncOpHandle *)handle
{
    if (error)
    {
        //In case of error, show the error message
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"REST Request Error"
                                                            message:[error localizedDescription]
                                                           delegate:self
                                                  cancelButtonTitle:@"OK"
                                                  otherButtonTitles:nil];
        [alertView show];
        [alertView release];
    }
    else
    {
        //Show the result in the UIAlertView
        NSString *disp = nil;
        if ([data isKindOfClass:[NSDictionary class]])
        {
            NSDictionary *dict = (NSDictionary *)data;
            disp = [[dict OMJSONRepresentation] retain];
        }
        else
        {
            disp = [[NSString alloc] initWithData:data
                                         encoding:NSASCIIStringEncoding];
        }
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Received"
                                                            message:disp
                                                           delegate:self
                                                  cancelButtonTitle:@"OK"
                                                  otherButtonTitles:nil];
        [disp release];
        [alertView show];
        [alertView release];
    }
}

Note:

OMRESTRequest 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 User-Agent property. The same User-Agent property value must be specified by the mobile application in its header.

OMRESTRequest can be initialized without OMMobileSecurityService, as well. In such cases, the OMRESTRequest APIs will just return the URL values.

9.8.1 Understanding the OMRESTRequest API Flow

The following steps describe the internal flow of the OMRESTRequest API:

1. The OMRESTRequest API 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.

9.9 Using the iOS SDK to Create a Custom Mobile Single Sign-on Agent App

This section contains information to get you started creating a mobile single sign-on app.

To serve as a mobile single sign-on agent, the app must include logic to handle authentication requests coming from other apps (the mobile SSO clients). After initializing the IDM Mobile SDK and creating an authentication request, add the following code in the ApplicationDelegate.m class.

- (BOOL) application:(UIApplication *)application
     openURL:(NSURL *)url
     sourceApplication:(NSString *)sourceApplication
                annotation:(id)annotation
 
{
      NSString *queryString = [url query];
 
      if ([queryString hasPrefix:@"oamconfig=true&"])
      {
         //If it is server settings, store it in NSUserDefaults
 
         [OMMobileSecurityService storeOAMServerSettingsInNSUserDefaults:url];  
         //IDMMobileSDK.h needs to be imported
      }
      else
      {   
       /* This section is application specific. In this else section we need to call handleRequestWithURL:url bundleID:sourceApplication that is the entry point to process SSO requests. */
 
          if(splitViewController != nil)
 
          [self.documentViewController handleRequestWithURL:url 
           bundleID:sourceApplication];
 
          else
          {
 
           UINavigationController *nav = [[tabBarController customizableViewControllers] objectAtIndex:0];
 
           DocumentViewController * doc = [[nav childViewControllers] objectAtIndex:0];
 
           [doc handleRequestWithURL:url bundleID:sourceApplication];
           [nav release];
          }
      } 
      return YES;
}

Note that handleRequestWithURL:url bundleID:sourceApplication is the function that is the entry. It should be implemented in the class that has access to the OMMobileSecurityService object that has been setup.

Next, introduce the following instance variable in the class that implements the handleRequestWithURL:url bundleID:sourceApplication:

NSDictionary *_queryParams; 

Following is the implementation of the handleRequestWithURL:url bundleID:sourceApplication function:

- (void)handleRequestWithURL:(NSURL *)url bundleID:(NSString *)appBundleID
 
{
        NSDictionary *params = [_mobileServices parseURL:url fromApp:appBundleID]; //_mobileServices is the object of OMMobileSecurityService
 
        /* If this is a SSO request coming from a native app or browser
        * then do the SSO flow. Else do application specific logic */
 
     if ([_mobileServices isSSORequest:params])
     {
        self.queryParams = params;
 
       [_mobileServices processSSORequest:self.queryParams presenter:self];
       // presenter should be of type UIViewController
 
     }
     else
        {
        // Write Application specific logic
        NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] initWithCapacity:1];
 
        [userInfo setObject:url forKey:OM_RESPONSE_URL];
 
        //Post the notification to IDM Mobile SDK
        [[NSNotificationCenter defaultCenter] postNotificationName:OM_PROCESS_URL_RESPONSE
 
                         object:self
                                 userInfo:userInfo];
 
        [userInfo release];
 
        }
}

Finally, add the following code to the didFinishAuthentication method:

if(self.queryParams != Nil)
 
      _mobileServices sendSSOResponseWithHandles:nil error:error params:self.queryParams];

The Sample Mobile SSO Agent App

Mobile and Social provides a sample SSO agent app that illustrates the required logic. You can adapt this logic to any business app and enable the app to function as a mobile SSO agent. To get started, open OICSSOAPP.zip.

Note that the app delegate of the iOS mobile SSO app should implement the openURL method to handle SSO requests coming from other apps. The URL scheme should also be defined in the iOS app and on the Mobile and Social server. Finally, when adding the Application Profile to a Service Domain on the Mobile and Social server, configure the Mobile Single Sign-on (SSO) Configuration attributes (Participate in Single Sign-on and Agent Priority).

Note:

For information about configuring iOS specific settings on the Mobile and Social server, see the following topics in Oracle Fusion Middleware Administrator's Guide for Oracle Access Management:

9.10 Using the Cryptography Module

The cryptography APIs provided by iOS are C APIs that are cumbersome to use. The Mobile and Social iOS Client SDK provides intuitive Objective C APIs for common cryptography tasks that are simple to use. The SDK uses the APIs listed here 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.

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

Hashing

Use the hashing capability to get the hash value of a string (typically a password) with an auto-generated random salt. The following API also adds the salt to the output and prefixes the algorithm name to the output. This is suitable for storage and transfer over the network. The generated salt, if requested, can be extracted using the outSalt parameter.

NSString *secret = "mypassword";
NSString *outSalt;
NSError *error;

NSString *hashValue = [OMCryptoService SHA256HashAndBase64EncodeData:[secret
                                                           dataUsingEncoding:
                                                           NSUTF8StringEncoding]
                                                 withSaltOfBitLength:24
                                                           outSalt:&outSalt
                                                           outError:&error];

The hashing capability provides the following functionality:

  • Convenience APIs are provided to perform hashing using the following algorithms SHA1, SHA224, SHA256, SHA384, SHA512

  • A similar set of APIs that operate without a salt are also provided

  • A random salt generation method is available if the salt needs to be stored separately

  • The resulting hash value can be optionally Base64 encoded

  • The algorithm name can be optionally prefixed to the output

  • In addition to the convenience API, a more sophisticated method that can customize all values is also provided:

hashData:withSalt:algorithm:appendSaltToOutput:base64Encode:prefixOutputWithAlgorithmName:outError:

Symmetric key encryption/decryption

This API helps perform symmetric key encryption and decryption of data. The following example helps encrypt a given data using AES algorithm, PKCS7 padding using an auto-generated random symmetric key.

  NSData *plainText = ...
  NSString *outKey;
  NSError *error;
 
  NSString *cipherText = [OMCryptoService encryptData:plainText
                             withSymmetricKeyOfLength:24
                                      outSymmetricKey:&outKey
                                             outError:&error];
 

To decrypt the above cipher text, the following API can be used.

  NSString *plainText = [OMCryptoService decryptData:cipherText
                                    withSymmetricKey:outKey
                                            outError:&error];
 
  • The supported algorithms are AES128 (key sizes 16,24,32), DES (key size 8), 3DES (key size 24).

  • A secure symmetric key generation API is available

  • The resultant cipher text can be optionally Base64 encoded

  • The algorithm name can be optionally prefixed to the output.

  • A more sophisticated method that makes it possible to specify the algorithm, initialization vector, padding, and so on is available:

encryptData:withSymmetricKey:initializationVector:algorithm:padding:mode:base64EncodeOutput:prefixOutputWithAlgorithmName:outError:
 decryptData:withSymmetricKey:initializationVector:algorithm:padding:mode:isInputPrefixedWithAlgorithmName:isInputBase64Encoded:outError:

Asymmetric Key Cryptography

The asymmetric key cryptography APIs that are part of OMCryptoService help with the following operations:

  • Key pair generation and storage in a key chain

  • Sign and verify operations with keys in a key chain

  • Wrap and unwrap operations with keys in a key chain

  • Extraction of the public key from a key chain

  • Deletion of a key pair in a key chain

9.11 Using the Credential Store Service (KeyChain)

The Credential Store service provides APIs to store and retrieve sensitive data using iOS Keychain Services.

Start with the OMMobileSecurityService object and get an OMCredentialStore handle. Use OMCredentialStore to write to and retrieve sensitive data from KeyChainItem.

The following code snippets illustrate how to use OMCredentialStore.

Add a User Name and Password

This example adds a user name and password to a given key in KeyChainItem.

- (void)addCredential:(NSString *)userName pwd:(NSString *)password url:(NSString *)key;

Add a User Name, Password, and Tenant Name

This is a variation of the previous addCredential function.

- (void)addCredential:(NSString *)userName 
                  pwd:(NSString *)password 
           tenantName:(NSString *)tenantName 
                  url:(NSString *)key;

Delete a Credential

This example deletes the credential from KeyChainItem. Because there is not a true delete operation, the user name and password are instead set to null.

- (void)deleteCredential:(NSString*)key;

Update a User Name and Password

This example updates the user name and password given the user and key values. Because there is not a true update operation, updateCredential calls addCredential.

- (void)updateCredential:(NSString*)userName pwd:(NSString*)password  url:(NSString*)key; 

Update a User Name, Password, and Tenant Name

This is a variation of the previous updateCredential function.

- (void)updateCredential:(NSString *)userName 
                     pwd:(NSString *)password 
              tenantName:(NSString *)tenantName 
                     url:(NSString *)key;

Get a User Name and Password

This example retrieves the user name, password, and tenant name for a given key.

- (OMCredential *)getCredential:(NSString*)key;

Store a Property in KeyChainItem

This example stores a property in KeyChainItem.

- (void)storeProperty: (NSString *)property withKey: (NSString *)key;

Store Multiple Properties in KeyChainItem

This is a variation of the previous storeProperty function.

- (void)storeProperty: (NSString *)property 
              withKey: (NSString *)key
            withLabel: (NSString *)label
      withDescription: (NSString *)description;