Setting up the project
This section describes the first steps to integrate the iOS SDK with an existing project. In this sample you integrate the iOS SDK into the iOS Example Application.
There are two methods to add the iOS SDK to your project, through CocoaPods as a Pod or manually. We recommend using CocoaPods to integrate the iOS SDK with your project. Using CocoaPods does not require manually changing your Xcode project.
Integrate the iOS SDK using CocoaPods
To integrate the iOS SDK with your project using CocoaPods, you must install the CocoaPods Artifactory plugin, set up authentication, add the iOS SDK to the pod file, and update the pod repository.
Install the CocoaPods Artifactory plugin
The iOS SDK is uploaded to the OneWelcome Identity Platform Artifactory repository. To let CocoaPods use an Artifactory repository, you need to install the cocoapods-art
plugin.
Tip
We 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.
gem install cocoapods-art
Set up authentication
The OneWelcome Identity Platform repository is not a public repository. You must provide credentials to access the repo.
To obtain credentials visit https://onewelcome.atlassian.net/servicedesk/customer/portals and submit a request for access.
Create a file named .netrc in your Home folder (~/) and add the following:
machine repo.onewelcome.com
login <username>
password <password>
Add the iOS SDK to Podfile
- Add the cocoapods-art plugin as a plugin in your Podfile.
plugin 'cocoapods-art', :sources => [
'onegini'
]
- Add the SDK as a Pod to one of your target projects.
target 'OneginiExampleApp' do
use_frameworks!
pod 'OneginiSDKiOS', '12.0.0'
end
Run the pod
Execute the pod install
command. On install, the OneginiSDKiOS.framework
is added to the project.
Add and update the local CocoaPods repository
The OneWelcome Idenntity Platform CocoaPods repository must be added to your local machine using the following command:
pod repo-art add onegini https://repo.onewelcome.com/artifactory/api/pods/cocoapods-public
To update the repository, you must manually perform an update:
pod repo-art update onegini
Integrate the iOS SDK manually
To integrate the iOS SDK with your project manually you must update the framework, modify the build settings to use the framework, and archive the unused iOS SDK components.
Update the framework
-
Copy the SDK framework into the Frameworks group of the project workspace.
-
Add the
OneginiSDKiOS.framework
to the Link Binary With Libraries section of the Build Phases. -
Add the
OneginiSDKiOS.framework
to the app target within the General tab.
Configure build settings
- Disable the bitcode for the application using the iOS SDK. Open the Build Settings and set Enable bitcode to No.
Archive unused iOS SDK components
The iOS SDK is distributed as a fat framework. It contains symbols for both iOS devices and simulators. This way juggling between two builds of the framework is not necessary. However Apple does not allow the distribution of apps containing simulator symbols. Unfortunately, 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
Configure the iOS SDK
Before you can use the iOS SDK in your application, the iOS SDK must be configured. There are two ways to provide the configuration:
-
manually
Manual configuration
Create the configuration model
The iOS SDK relies on a set of configuration parameters that must be provided to the iOS SDK by means of an instance of ConfigModel
. The backing data model of the ConfigModel
is a property list. The app is responsible for creating an instance of the ConfigModel
with a backing property list, and the app also needs to provide it to the ClientBuilder
. For more information about setting up and initializing, see the Configuration Model documentation.
Pin SDK certificates
Certificates used by the iOS SDK are secured from tampering. For the iOS SDK to detect certificate tampering, it is required to perform certificate pinning. For more information see certificate pinning.
Instantiate the iOS SDK
The whole functionality of the iOS SDK is accessed by means of a single shared client that is named Client
. The client must be instantiated once, early in the app lifecycle, and thereafter only referred to by its shared instance. This is usually done in the root view controller but can also be done in a specific non-UI class. To instantiate the iOS SDK, a ConfigModel
containing the configuration parameters and an array of PEM Base64-encoded X509 certificates has to be provided to the ClientBuilder
. This class is the only way to instruct the iOS SDK about configuration, X509-encoded certificates, and other settings.
After instantiating the shared instance of Client
, you must call its start:
method. In this method, the client verifies integrity and performs validation and registration calls, and the result is returned in a callback. You must wait until the start
method completes before proceeding with using the iOS SDK. Accessing DeviceClient
and UserClient
(both as shared instances or Client
properties) before calling the start:
method will raise an NSInternalInconsistencyException
.
Example of the client initialization
let model = ConfigModel(dictionary: ["ONGAppIdentifier": "AppId",
"ONGAppPlatform": "ios",
"ONGAppVersion": "1.3.0",
"ONGAppBaseURL": "https://baseurl.com",
"ONGResourceBaseURL": "https://rbaseurl.com/",
"ONGRedirectURL" : "app://loginsuccess"])!
let publicKey = "101133300A0CA2108222D02B8455766F7DC28E28A8A0ED025876BFB21FE3DDA0"
let certs = ["MIIDzTC...TSrLE="]; //Base64Certificates
ClientBuilder()
.setConfigModel(model)
.setX509PEMCertificates(certs)
.setServerPublicKey(publicKey)
.build()
SharedClient.instance.start { (succeeded, error) in
}
- (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 with the Mobile SDK Configurator
When the configurator has generated and added the ConfigModel
class to your app, you can instantiate the SDK by calling the -ClientBuilder().build()
method. It automatically finds the ConfigModel
to configure the SDK correctly.
Example of Client
initialization:
ClientBuilder().build().start { error in
completion(error.flatMap { ErrorMapper().mapError($0) })
}
- (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."];
}
}
}];
...
}
Call resources outside the main domain
When you call for a resource whose domain is not set as the main domain in the ConfigModel
, the certificate pinning mechanism will not allow you to do that. As the ConfigModel
can be set only for one domain, there is an optional method to fetch resources for different domains covered by the certificates set with the ConfigModel
.
The method called setAdditionalResourceUrls
has to be called before the build()
command, and uses an array of URL strings. An example of usage:
ClientBuilder()
.setAdditionalResourceUrls(["https://www.domain1.com", "https://domain2.com"])
.build()
.start { ... }
Using security controls during development
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 iOS SDK will not allow you to execute any of the user-related flows and returns an error. To disable this feature during development, follow the security controls.
Configure the application signature
Depending on the application integrity level you use, you might need to obtain the App ID and store it in the IDAAS-core. The App ID should not change for the app very often. However, if application signature verification is hampering development, it's recommended to create a new application version with the Integrity level set to None for the duration of development.
Reset the iOS SDK
After starting the iOS SDK, there is a possibility to reset the iOS 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 the reset
method from Client
.
[[ONGClient sharedInstance] reset:^(BOOL result, NSError *error) {
if (error != nil) {
// Errors will be from the ONGGenericErrorDomain
}
}];
...
SharedClient.instance.reset { error in
if error != nil {
// Errors will be from the ONGGenericErrorDomain
}
}