Setting up the project

This section describes the first steps to integrate the Onegini iOS SDK with an existing iOS project.

Adding the SDK to your project

There are two ways to add the iOS SDK to your project. Manually or through CocoaPods as a Pod.

Cocoapods

CocoaPods is the preferred way to add the Onegini SDK to your project. It provides the most convenience and ease of use. You don't have to manually change your Xcode project file.

Install the CocoaPods Artifactory plugin

The Onegini SDK is uploaded to the Onegini Artifactory repository. In order to let CocoaPods use an Artifactory repository you need to install a specific plugin.

gem install cocoapods-art

Note: It is strongly recommended that you install CocoaPods as a Rubygem and not through Homebrew. Installing with Homebrew may cause issues with the CocoaPods hooks mechanism that the plugin relies on.

Setup authentication

The Onegini SDK repository is not a public repository. You must provide credentials in order to access the repo.

Create a file named .netrc in your Home folder (~/) and add the following contents to it:

machine repo.onegini.com
login <username>
password <password>

Replace the <username> and <password> with the credentials that you use to login to support.onegini.com.

Add the OneginiSDK to your Podfile

Adding the OneginiSDK to your Podfile is done in two steps. First you need to add the cocoapods-art plugin as a plugin in your Podfile.

plugin 'cocoapods-art', :sources => [
 'onegini'
]

Second you need to add the Onegini SDK as a Pod in one of your project targets.

target 'OneginiExampleApp' do
    pod 'OneginiSDKiOS', '10.0.0'
end

This way after running pod install command, OneginiSDKiOS.framework and OneginiCrypto.framework will be added to the project.

Adding and updating the onegini CocoaPods repository

The Onegini CocoaPods repository must be added to your local machine using the following command.

pod repo-art add onegini https://repo.onegini.com/artifactory/api/pods/cocoapods-public

In order to update the Repository you must manually perform an update

pod repo-art update onegini

Note: It is a good habbit to perform pod repo-art update onegini every once in a while just as you are doing it with the CocoaPods master repository.

Manually

Copy the Onegini SDK framework into the Frameworks group of the project workspace. Add the OneginiSDKiOS.framework and the OneginiCrypto.framework to the "Link Binary With Libraries" section of the Build Phases and add it as an "Embedded binary" to the app target within "General" tab.

The result should look similar to the following example:

Add SDK

Build Settings

Currently its only required to disable the bitcode for the application using the Onegini SDK. It is done by setting the Enable bitcode to No value within the Build Settings.

Archiving

Onegini SDK is distributed as a fat framework, which means that it cotains symbols for both iOS devices and Simulators. This way juggling between two builds of the framework is not necessary. However Apple does not allow distribution of apps containing simulator symbols. Unfortunetaly Xcode will not do it for you (like Cocoapods does), it needs to be done as an additional step before distribution. The issue can be solved by adding the following script as a Run Script in Build Phases:

APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"

# This script loops through the frameworks embedded in the application and
# removes unused architectures.
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"

EXTRACTED_ARCHS=()

for ARCH in $ARCHS
do
echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
done

echo "Merging extracted architectures: ${ARCHS}"
lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
rm "${EXTRACTED_ARCHS[@]}"

echo "Replacing original executable with thinned version"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"

done

SDK configuration

Before the SDK can be used in an application it needs to be configured. E.g. you need to tell it the location (URL) of the Token Server instance, but also some of the security features need to be configured. There are two ways of the providing configuration:

The latter is the preferred way of working since it does not require the manual steps described in the paragraph below. The SDK configurator can be found on GitHub.

Manual configuration

The paragraphs below explain how to manually configure the SDK.

Configuration model

The SDK relies on a set of configuration parameters which must be provided to the SDK by means of an instance of ONGConfigModel. The backing data model of the ONGConfigModel is a property list. The App is responsible for creating an instance of the ONGConfigModel with a backing property list and the app also needs to provide it to the ONGClientBuilder. Initialization of ONGConfigModel is described here.

Certificate pinning

Certificates used by the SDK are secured from tampering. In order for the SDK to detect certificate tampering it is required to perform Certificate Pinning.

Instantiating the SDK

The whole functionality of the SDK is accessed by means of a single shared client which is named ONGClient. The client must be instantiated once early in the App lifecycle and thereafter only referred to by it's shared instance. This is usually done in the root view controller but can also be done in a specific non UI class. In order to instantiate SDK ONGConfigModel containing the configuration parameters and an array of PEM Base64 encoded X509 certificates has to be provided to the ONGClientBuilder. This class is the only way to instruct SDK about configuration, X509-encoded certificates and other settings.

After instantiating the shared instance of ONGClient it is required to call its start: method. In this method the client verifies integrity and performs validation and registration calls, the result is returned in callback. You need to wait until the start method completes before proceeding with using the Onegini SDK. Accessing ONGDeviceClient and ONGUserClient (both as shared instances or ONGClient properties) before calling start: method will raise NSInternalInconsistencyException.

Example of the ONGClient initialization:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    ...
    NSString *const certificate = @"AaXeRCk/luuGtm87fM04wO+mPZn+C+mv626PAcwDj1hKvTfIPWhRRH224hoFiB85ccsJP81cqcdnUl4XmGFO3";
    NSString *configPath = [[NSBundle mainBundle] pathForResource:@"config" ofType:@"plist"];
    ONGConfigModel *configModel = [[ONGConfigModel alloc] initWithContentsOfFile:configPath];

    [[[[ONGClientBuilder new] setConfigModel:configModel] setX509PEMCertificates:@[certificate]] build];
    [[ONGClient sharedInstance] start:^(BOOL result, NSError *error) {
        if (error != nil) {
            if (ONGGenericErrorOutdatedApplication == error.code) {
                [self showAlertWithTitle:@"Application disabled" message:@"The application version is no longer valid, please visit the app store to update your application"];
            }

            if (ONGGenericErrorOutdatedOS == error.code) {
                [self showAlertWithTitle:@"OS outdated" message:@"The operating system that you use is no longer valid, please update your OS."];
            }
        }
    }];
    ...
}

Configuration via SDK configurator

Once configurator has generated and added the OneginiConfigModel class to your App, you can instantiate SDK by calling the -[ONGClientBuilder build] method. It automatically finds the OneginiConfigModel in order to configure SDK correctly.

Example of the ONGClient initialization:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    ...
    [[ONGClientBuilder new] build];
    [[ONGClient sharedInstance] start:^(BOOL result, NSError *error) {
        if (error != nil) {
            if (ONGGenericErrorOutdatedApplication == error.code) {
                [self showAlertWithTitle:@"Application disabled" message:@"The application version is no longer valid, please visit the app store to update your application"];
            }

            if (ONGGenericErrorOutdatedOS == error.code) {
                [self showAlertWithTitle:@"OS outdated" message:@"The operating system that you use is no longer valid, please update your OS."];
            }
        }
    }];
    ...
}

Important additional information

Using the security controls during development

Please note that the iOS SDK has the ability to detect if the app works in debug mode or with a debugger attached. This feature is enabled by default. When debug mode detection is enabled and a debugger is detected (which is most likely the case if you run your app in an simulator), the SDK will not allow to execute any of the user related flows and return an error. To disable this feature during development please follow the security controls guide.

Configuring the Application Signature

Depending on the Application Integrity level you use you might need to obtain the App ID and store it in the Token Server. The App ID should not change for the app very often however if for any reason Application Signature verification is hampring the development its recommended to create new application version with Integrity level set to None for the duration of development.

Resetting the SDK

After starting the SDK there is a possibility to reset the SDK to state after completing the start method. Reset will clear all of the access tokens stored in memory and all of the challenges waiting for responses from the application. Client credentials will be revalidated and the client configuration will be refreshed. You can do that by calling reset method from ONGClient.

    [[ONGClient sharedInstance] reset:^(BOOL result, NSError *error) {
        if (error != nil) {
            // Errors will be from the ONGGenericErrorDomain
        }
    }];
    ...

results matching ""

    No results matching ""