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. This chapter provides the following sections:
Section 9.2, "Invoking Authentication Services With the iOS Client SDK"
Section 9.3, "Invoking HTTP Basic Authentication With the iOS Client SDK"
Section 9.4, "Invoking User Profile Services With the iOS Client SDK"
Section 9.5, "Using the Credential Store Service (KeyChain)"
Section 9.8, "Using the iOS SDK to Create a Custom Mobile Single Sign-on Agent App"
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 three 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.
Secure Storage Module - Provides APIs to store and retrieve sensitive data using the iOS Keychain feature.
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:
Follow these steps to set up your XCode environment.
Add libIDMMobileSDK.a
to XCode by following these steps:
Download libIDMMobileSDK.a
to your development environment and add it to a project folder.
Launch XCode and open your project.
Click your project to select it, then click your target and click the Build Phases tab.
Expand Link Binary With Libraries and click the + button.
Select Other and choose libIDMMobileSDK.a
.
Download and unzip the PublicHeaders.zip
and PublicResources.zip
files.
The PublicHeaders.zip
archive contains the IDM Mobile SDK header files
The PublicResources.zip
archive contains the IDM Mobile SDK resource bundle.
Choose Add Files to Your-Project-Name to add the contents of PublicHeaders.zip
and PublicResources.zip to your project.
You can now start coding using the IDM Mobile iOS Client SDK.
Important:
Before linking your project, add as a single line both the -ObjC
and -all_load
linker flags to your project. Without these flags your application will crash with a "selector not recognized" runtime exception.
Because libIDMMobileSDK
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:
This section provides sample code that demonstrates how to authenticate with the Mobile and Social server.
The sample code in this section supports the "JWTAuthentication" (JSON Web Token Authentication) service type. 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 and Declare the Endpoints
Create the OMMobileSecurityService
class as follows and initialize it by providing the required Mobile and Social server details:
OMMobileSecurityService *mss = [[OMMoblieSecurityService alloc] initWithURL: mobileSocialServerURL] appName: applicationName domain: domainName delegate: self];
The initWithURL
argument is the URL (including protocol, host name, and port number) required to reach the Mobile and Social server. Only the HTTP and HTTPS protocols are supported.
The appName
argument is a unique identifier that identifies the application. This String value must match the application "Name" value located in the Application Profile section of the Mobile and Social server administration console. For more information, see "Editing or Creating Application Profiles" in Oracle Fusion Middleware Administrator's Guide for Oracle Access Management.
The domain
argument is the name of the Internet domain within which the Mobile and Social server is located.
The delegate
argument should be set to self
.
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 the iOS Client SDK calls the following method for the specified delegate:
didReceiveApplicationProfile: (NSDictionary *)applicationProfile error: (NSError *)error
This method returns an OMRegistrationService
object that handles the client registration.
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:
Step 2: Complete the Authentication Process
The OracleMobileSecurityService
object maintains all of the details regarding your current session. Upon receiving the application profile and the URLs needed to connect to the services, start the authentication process. Call the following methods.
NSError *error = nil; //startAuthenticationProcess API triggers the authentication process. error = [self.mss startAuthenticationProcess:nil presenterViewController:loginController]; if (error) { UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:@"Authentication process failed" message:[error localizedDescription] delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alertView show]; [alertView release]; return; }
The last line 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.
This section provides sample code that show to implement HTTP Basic Authentication. This authentication model does not require the Mobile and Social server.
The HTTP Basic authentication scheme supports the following functionality:
Online and offline authentication
Credential storage for offline authentication and retrieval
Idle time-out and session time-out
Maximum number of allowed failure attempts for offline authentication after which online authentication is enforced
Retrieval of HTTPCookie
after authentication (for example, OAM_ID
and ObSSSOCookie
)
Logout clears the cookie and any cached information in the IDM Mobile iOS Client SDK
Sample code for HTTP Basic authentication is provided here:
OMMobileSecurityConfiguration *conf = [[OMMobileSecurityConfiguration alloc] initWithApplicationID:@"TestApp" maxFailureAttempts:3 authenticationScheme:OM_HTTP_BASIC_AUTH_SCHEME]; /* Initialize OMMobileSecurityService by passing in ADFMobileSecurityConfiguration */ OMMobileSecurityService *service = [[OMMobileSecurityService alloc]initWithAppProfileConfiguration:conf delegate:self]; /* Create an authentication request object that will hold all the inputs for one particular session*/ OMAuthenticationRequest *request = [[[OMAuthenticationRequest alloc]init]]; [request setLogoutURL:@"http://hostName.example.com:14100/oam/server/logout"]; [request setSessionExpiryInSecs:30]; [request setIdleTimeInSecs:12]; [request setIsOnlineMode:true]; NSMutableArray *array = [[[NSMutableArray alloc]init]; [array addObject:@"OAM_ID"]; [request setRequiredTokens:array]; [request setAuthenticationURL:@"http://hostName.example.com:7777/index.html"]; [request setAuthenticationScheme:OM_HTTP_BASIC_AUTH_SCHEME]; NSError *error = nil; UINavigationController *viewController = [service getAuthenticationViewController:request error:nil]; if (viewController != nil) [self presentModalViewController:viewController animated:true]; else if (error != nil) { UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"Could not authenticate" message:[error localizedDescription] delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alertView show]; [alertView release]; }
After the authentication process completes, the code calls the delegate's didFinishAuthentication: error:
method.
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:
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.
- (NSArray *)searchUsersWithFilter: (NSDictionary *)filter isSimpleSearch: (BOOL)simpleSearch attributesToBeFetched: (NSArray *)attributesToFetch pageSize: (NSInteger)pageSize pagePosition: (NSInteger)pagePosition error: (NSError **)error;
- (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;
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;
Use the following APIs to request information about managers and their reports.
The following APIs are available in OMUser
.
- (OMUser *)getManager: (NSError **)error; - (OMAsyncOpHandle *)getManagerAsynchronously;
The following APIs are available in OMUser
.
- (NSArray *)getReporteesWithAttributes: (NSArray *)attributes returningError: (NSError **)error; - (OMAsyncOpHandle *)getReporteesAsynchronouslyWithAttributes:(NSArray *)attributes;
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
.
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;
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;
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;
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.
Web apps can also use the single sign-on authentication features provided by the mobile SSO agent. This functionality requires Access Manager.
Log on to the Oracle Access Management Administration Console and click the Policy Configuration tab.
Under Shared Components click Authentication Schemes, then click the Create button.
The "Create Authentication Scheme" tab opens.
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
In the Oracle Access Management Administration Console, do the following:
Create a new Authentication Scheme in an Application Domain:
Authentication Scheme: MobileSSOScheme
(MobileSSOScheme is the scheme that was created in step one.)
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.
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.
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.
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). 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:
See "Editing or Creating Application Profiles" for information about specific iOS application settings.
See "Editing or Creating the Service Domain" for information about configuring an SSO-enabled application as either a mobile SSO agent or a mobile SSO client.