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:
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:
Follow these steps to set up your Xcode environment.
Download libIDMMobileSDK.a
to your development environment and add it to Xcode.
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.
Add the contents of PublicHeaders
and PublicResources
to your project.
Add the following frameworks to your project:
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:
You can now start coding using the IDM Mobile iOS Client SDK.
Important:
The iOS SDK supports devices running iOS 4.3 and above.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:
mobileSecurityService: (OMMobileSecurityService *)mobileSecurityService 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:
Step 3: 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 a value of zero 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. This method takes a Boolean: true
means check with the server to see if the authentication context is still valid; false
means try to get the authentication context locally without checking whether it is still valid. For details about OMAuthenticationContext
, see the API documentation.
- (void)mobileSecurityService: (OMMobileSecurityService *)mobileSecurityService 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; }
At this point your application can use the token obtained from the Mobile and Social server to make additional web service calls.
Note:
TheOMMobileServiceDelegate
now contains selectors that include mobileSecurityService
. The old selectors without mobileSecurityService
are also available. When both are implemented, the new selector alone is called.Call the following method to log out the user:
[mss logout:false];
The Mobile and Social logout operation involves invoking a REST Web service to delete tokens maintained in the server. When the Boolean parameter clearRegistrationHandle
is true, the service clears device registration handles stored in the keychain. If false, only the session tokens are deleted.
Because a web service call is involved, the following delegate is called in OMMobileServiceDelegate
when the operation completes:
- (void)mobileSecurityService:(OMMobileSecurityService *)mobileSecurityService didFinishLogout:(NSError *)error;
sample implementation of the delegate is as follows:
- (void) mobileSecurityService:(OMMobileSecurityService *)mobileSecurityService didFinishLogout:(NSError *)error { NSString *msg = nil; if (error) msg = [NSString stringWithFormat:@"%@-%05ld: %@", [error domain], (long)[error code], [error localizedDescription]]; else msg = [NSString stringWithFormat:@"You are logged out successfully"]; UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Logout" message:msg delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alertView show]; [alertView release]; }
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 fromKeyChainItem
(covered later), as appropriate.URL-based configuration can easily configure an app utilizing the SDK. It works like this: Create an URL containing SDK configuration properties. When a user opens this URL using a mobile browser, the mobile app receives the URL in the application:openURL:sourceApplication:annotation
delegate method. The mobile app needs to pass this URL to the IDM Mobile SDK. The SDK extracts and persists the configuration parameters and, once persisted, the app can reuse the configuration for subsequent authentication. This provides a user friendly way to configure the app.
The configuration URL should adhere to the following pattern:
<urlscheme>://[host]?<parameter1>::=<value1>&<parameter2>::=<value2>&...&<parameterN>::=<valueN>
For example:
wp://settings?AuthServerType::=OAMMSAuthentication&OAMMSURL::=http://host123.us.example.com:14100 &OAMMSServiceDomain::=MobileServiceDomain&ApplicationName::=WhitePages
The urlscheme identifies the app to be opened. This can be added to an iOS project in Xcode by setting "URL Schemes" in the project Info section. Note that the URL scheme needs to match the setting in the OAM console. An URL scheme defined as wp
in the console needs to be defined as wp:// in Xcode
. URL schemes must be unique.
In the app, the application delegate is the right place to handle the URL and complete the configuration steps. A code sample is given below.
- (BOOL) application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { /* This snippet assumes "settings" is passed as host in the config URL. Replace it with the actual host passed in the config URL*/ if([host url] isEqualToString:@"settings"]) { NSSet *sdkPropsFilter = [NSSet setWithObjects:OM_PROP_AUTHSERVER_TYPE, OM_PROP_OAMMS_URL, OM_PROP_OAMMS_SERVICE_DOMAIN, OM_PROP_APPNAME,nil]; [OMMobileSecurityService parseConfigurationURL:url persistInUserDefaults:true withKey:nil andFilters:sdkPropsFilter]; } return YES; }
The mobile app can also apply some filters on the configuration received from the URL. Refer to the andFilters
parameter in the code above. Using this parameter the app can specify a list of SDK parameters that should be allowed. The remaining parameters in the URL extracted from the configuration URL are ignored by the IDM Mobile SDK. After you have received and persisted the configuration, the OMMobileSecurityService
object can be initialized. The withKey
parameter can be used to identify a set of configuration parameters. When this is set to zero, the SDK treats it as the default configuration.
OMMobileSecurityService *mss = [[OMMobileSecurityService alloc] initWithDelegate:self];
This will create an OMMobileSecurityService
object with the configuration parameters stored in NSUserDefaults
. Use the following selector to pick the configuration associated with key
:
- (id)initWithPropertiesAvailableInNSUserDefaultsWithKey:(NSString *)key
This helps maintain multiple configuration parameter sets in a mobile app.
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 |
---|---|---|
|
|
NSString |
|
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:
|
NSString or NSURL |
|
Required property. Any valid Service Domain name passed as an NSString object. |
NSString |
|
Required property. A valid application name passed as an NSString object. |
NSString |
|
Either 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 |
|
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 |
|
Use this property to specify the KeyChain Item protection level. Must be one of the following values:
This is an optional property. If it is not specified, the property defaults to the highest level: |
NSString |
|
Either This is an optional property and the default value is |
NSString |
|
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 |
NSNumber |
|
Either This is an optional property, however, if it is not specified, the Auto Login feature is disabled. |
NSString |
|
Either This is an optional property, however, if it is not specified, the Remember Credentials feature is disabled. |
NSString |
|
Either This is an optional property, however, if it is not specified, the Remember User Name feature is disabled. |
NSString |
|
Either This is an optional property, however, if it is not specified, the default value for the Auto Login user preference is false. |
NSString |
|
Either This is an optional property, however, if it is not specified, the default value for the Remember Credentials user preference is false. |
NSString |
|
Either This is an optional property, however, if it is not specified, the default value for the Remember User Name user preference is false. |
NSString |
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.12, "Using the Cryptography Module."
Table 9-2 Cryptography Scheme Property Attributes for the iOS Client SDK
Property | Value | Attribute Name | Attribute Value |
---|---|---|---|
|
|
|
|
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
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.Social Identity 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 Social Identity" chapter in the Administrator's Guide for Oracle Access Management for more information.
For Social Identity authentication (also known as 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 Social 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
.
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.
- (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;
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
.
Note:
You need to implement a delegate to get results from the asynchronous call. For details see Chapter 9, "Using the Asynchronous API."- (NSArray *)getReporteesWithAttributes: (NSArray *)attributes returningError: (NSError **)error; - (OMAsyncOpHandle *)getReporteesAsynchronouslyWithAttributes:(NSArray *)attributes;
Follow these steps to use the User Profile Service's asynchronous API:
The calling class has to implement OMEntityDelegate
.
Implement the delegate method -didReceiveEntities:from:withAsynchronousHandle:
The following code snippet demonstrates the user search operation:
OMUserManager *userManager = [[mss userRoleProfileService] getUserManager]; userManager.delegate = self; //class that implements OMEntityDelegate [userManager searchUsersAsynchronouslyWithFilter:filter isSimpleSearch:YES attributesToBeFetched:attributes pageSize:pageSize pagePosition:pagePosition]; // This method receives the asynchronous operation result -(void)didReceiveEntities:(id)entities error:(NSError *)error from:(id)omObject withAsynchronousHandle:(OMAsyncOpHandle *)asyncHandle
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.
The Launch Pad opens.
Under Access Manager click Authentication Schemes, then click the Create Authentication Scheme 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 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) [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 OAMAuthUserAgentPrefix
and OAMAuthAuthenticationServiceLocation
properties. The same property values 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 or converting an application to 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). Follow the steps to initialize and configure the SDK.
Introduce the following instance variable to the class implementing OMMobileServiceDelegate
:
BOOL _setupDone; //Indicates if the application profile was downloaded successfully NSString *_ssoAppBundleID; //Store the bundle ID of the SSO client app NSURL *_ssoRequestURL; // Stores the request URL sent by the client app BOOL _profileError; //Indicates if an error occurred in the profile download NSDictionary *_queryParams; // Stores query parameters from the SSO request URL
Add the following methods to the same class:
/* This method is the entry point to handle SSO requests. If the app Profile is not downloaded, it starts the download or it starts by processing the request. The App profile download can be triggered from this function if it is not being checked every time the app becomes active. */ - (void) handleRequestWithURL:(NSURL *)url bundleID:(NSString *)appBundleID { if (!_setupDone) { self.ssoRequestURL = url; self.ssoAppBundleID = appBundleID; return; } [self ssoRequestWithURL:url fromApp:appBundleID]; } /* This function invokes the SDK to process the SSO request. */ - (void)ssoRequestWithURL:(NSURL *)url fromApp:(NSString *)appBundleID { if(_profileError) { _profileError = FALSE; self.ssoAppBundleID = nil; self.ssoRequestURL = nil; return; } NSDictionary *params = [self.mobileServices parseURL:url fromApp:appBundleID]; self.ssoRequestURL = nil; self.ssoAppBundleID = nil; self.queryParams = params; /* If this is an SSO request coming from either a native app or a browser * then do the SSO flow. Else do application specific logic. */ if ([self.mobileServices isSSORequest:self.queryParams]) { [self.mobileServices processSSORequest:self.queryParams presenter:self]; //It is assumed that the class also extends UIViewController. } }
Add the following code to the didReceiveApplicationProfile:error
method:
if (error) { _profileError = TRUE; } else { _setupDone = TRUE; } if(self.ssoRequestURL != nil && self.ssoAppBundleID != nil) { [self ssoRequestWithURL:self.ssoRequestURL fromApp:self.ssoAppBundleID]; return; }
Add the following code to the didFinishAuthentication:error
method:
if([self.mobileServices isSSORequest:self.queryParams]) { [self dismissModalViewControllerAnimated:NO]; [error retain]; [self performSelector:@selector(completeSSOAuthentication:) withObject:(id)error afterDelay:0]; /* This is required because the SSO Agent app starts the client app registration after authentication. The registration should occur in the next run loop cycle.*/ return; } - (void)completeSSOAuthentication:(id)object { NSError *error = (NSError *)object; [self.mobileServices completeSSORequest:self.queryParams presenter:self error:error]; }
Add the following code to the didFinishRegistration:error
method:
[registrationHandle retain]; [self dismissModalViewControllerAnimated:true]; [self.mobileServices sendSSOResponseWithHandles:registrationHandle error:loginError params:self.queryParams]; [registrationHandle release];
Add the following to the application:openURL:sourceApplication:annotation
method of UIApplicationDelegate
:
/* This starts the SSO request handle process. You can check the request URL to make sure it is an SSO request. */ [<object of class implementing handleRequestWithURL:bundleID method> handleRequestWithURL:url bundleID:sourceApplication];
The following is a sample implementation of application:openURL:sourceApplication:annotation
:
- (BOOL) application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { self.viewController.isConfigUpdate = false; NSString *queryString = [url query]; NSString *host = [url host]; if ([queryString hasPrefix:@"oamconfig=true&"]) { //do something } else if([host isEqualToString:@"settings"]) { //do Something } else { [self.viewController handleRequestWithURL:url bundleID:sourceApplication]; } return YES; }
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: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.
You can create custom views to get login and knowledge-based authentication (KBA) information from the user. The SDK will present these views to the user as needed. Otherwise, the SDK presents the default native view.
Custom native views should subclass OMAuthView
and override some methods described later in this section.
When creating custom native views:
Subclass OMAuthView
.
Override the viewLoaded
method. If any part of the Remember Credentials feature is enabled then the authData
dictionary will contain credentials and user preferences for the feature.
Override the retrieveAuthData
method. This method should populate the authdata
dictionary with user input.
MyLoginView.h file @interface MyLoginView : OMAuthView //Declare properties required for getting user input @end MyLoginView.m file @implementation MyLoginView -(void) viewLoaded { // Get credentials and user preferences from self.authData } -(NSDictionary *) retrieveAuthData { // Populate self.authData with user input } @end
When passing the custom native views to the SDK:
Create an OMAuthenticationRequest
object.
Set the authView
and kbaView
properties to custom native view objects.
Pass the OMAuthenticationRequest
object to the mss.startAuthenticationProcess:presentViewController
method.
// Initialize mss object OMMobileSecurityService *mss = [[OMMobileSecurityService alloc] initWithProperties:sdkProps delegate:self]; [mss setup]; //Wait for setup to complete //Create authentication request OMAuthenticationRequest *authnReq = [OMAuthenticationRequest alloc] init]; MyLoginView *loginView = [[MyLoginView alloc] init]; MyKBAView *kbaView = [[MyKBAView alloc] init]; authReq.authView = loginView; authReq.kbaView = kbaView; [mss startAuthenticationProcess:authnReq presenterViewController:myPresenter];
The progress view shown after the login screen can be customized. The pattern is similar to the Login view customization. The app needs to extend the OMAuthProgressView
class and register the instance of the app's implementation in OMAuthenticationRequest
. A code snippet is given below:
OMAuthenticationRequest *authReq = [[OMAuthenticationRequest alloc] init]; MyProgressView *myProgressView = [[MyProgressView alloc] initWithFrame:self.view.frame]; authReq.authProgressView = myProgressView; [myProgressView release];
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.
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:
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
The Mobile and Social iOS 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:
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 iOS 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 iOS 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 iOS 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
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 9-3 Configuration parameters used to enable auto login and remember credentials features
Parameter | Description |
---|---|
|
Boolean value that enables/disables the Auto Login feature. |
|
Boolean value that enables/disables the Remember Credentials feature. |
|
Boolean value that enables/disables the Remember User Name Only feature. |
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 9-4 Configuration parameters used to set the option box default values
Parameter | Description |
---|---|
|
Boolean value that specifies the default value of the "Auto Login" option box. |
|
Boolean value that specifies the default value of the "Remember Credential" option box. |
|
Boolean value that specifies the default value of the "Remember User name Only" option box. |
Persist option box states as key-value pairs in NSUserDefaults
. 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 keychain. The login page will then either revert to the Remember User Name Only feature, or control will revert to the mobile app using OMMobileService
delegate. 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 iOS 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 iOS Client SDK logout method is called and the clearRegistrationHandles
parameter is set to TRUE
Creating a Custom Login Screen
If you want to create a custom login screen instead of using the basic login view provided by the SDK, you need to subclass OMAuthView
and add its object to the current authentication request object so that your custom view will be used for authentication instead of the default view. The Mobile and Social iOS Client SDK uses an authentication data dictionary to set user credentials and option box states. This authentication data dictionary is available as a property to every subclass of OMAuthView
. Be sure to read these values and display them properly in the UI elements. Similarly, when submitting user credentials, be sure to read values from the UI elements and set them properly in the authentication data dictionary.
The following table lists the keys that you need to use to access credential properties in the authentication data dictionary.
Table 9-5 Keys used to access credential properties in the data dictionary
Key | Description |
---|---|
|
Boolean value that enables/disables the Auto Login feature. |
|
Boolean value that enables/disables the Remember Credentials feature |
|
Boolean value that enables/disables the Remember User Name Only feature |
|
Boolean value that specifies the user's preference regarding the Auto Login feature. |
|
Boolean value that specifies the user's preference regarding the Remember Credentials feature. |
|
Boolean value that specifies the user's preference regarding the Remember User Name Only feature. |
|
String value that specifies the user's user name. |
|
String value that specifies the user's password. |
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;
Delete Property in KeyChainItem
Deletes a given property store in KeyChainItem
. All details stored with the property are deleted.
- (NSError *)deletePropertyWithKey:(NSString *)key
Returns a property from KeyChainItem
.
- (id)getPropertyForKey:(NSString *)key