Integration

CocoaPods

The biidCoreSDK can be installed into an Xcode project using CocoaPods.

Cocoapods can be installed on your machine via the terminal:

$ gem install cocoapods

CocoaPods 1.6.2+ is required to build the biidCoreSDK.

Full details on how to install cocoapods can be found here.

To integrate biidCoreSDK into your Xcode project using CocoaPods, specify it in your Podfile as follows:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '10.3'
use_frameworks!

target '<Your Target Name>' do
    pod 'biidCoreSDK', '3.2.260'
end

Then, run the following command to install the SDK and any other dependencies:

$ pod install

Manifest File

A manifest file is required to successfully initialize the biidCoreSDK. The manifest file contains metadata data such as an app key and URL endpoints, public key information and details of backoffice modifiable settings.

the Manifest file for an app can be generated and downloaded directly from the Back Office environment.

The manifest file should added to a build target so that it is available from within the bundle of the built app.

On initialization the SDK will check for the presence of a valid manifest file and load the settings accordingly.

Example of a manifest file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>AppName</key>
    <string>Company App Name</string>
    <key>AppKey</key>
    <string>8Ps5DOtLZTtb0DP0WE2Udu1nCk0jtLDcLlHgHrCYmju55TPL14bVaMjgDcLM</string>
    <key>BundleID</key>
    <string>com.company.app</string>
    <key>EndPoint</key>
    <string>api.companyApp.com</string>
    <key>PublicKey</key>
    <string>-----BEGIN PUBLIC KEY-----
MIIBIjCOMgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzejUt4hyiJ/Y72QZsaiy
jA1Ky+fLO9i56U95Of/U5YQIW8JKdFaB/J09cLY9H0Wa5ugAjOLZP4z7HcTA0GWG
pyFOgaxJedLp5S4BcryLhhl9HcNo/9vThZ7dx+zwjihQ6Bct0PEFiJXVKrRy3YEA
WOEGBhaGv9d18w3j5P0NpBpnCxZjAHOvOGa1xFhWVsT1gztCLI6iidq6m9bPDM4e
KN3w6A47057LyaamtZwJugiO1Ts1HIfAoVzVfHktcVS3XSu0M0G3PXxt9xswf3bc
Buo8m4WhxVZihYKuTplb2Ctu03uG15MlAMlyuDjhRJziN1Djzrmd16iJHD1bvdmO
fQIDAQCD
-----END PUBLIC KEY-----</string>
    <key>AllowMultipleEntities</key>
    <true/>
    <key>RequiresSecureEnclave</key>
    <true/>
    <key>NativeBiometricsRequiredForKeyAccess</key>
    <true/>
    <key>Checksum</key>
    <string>446BEB8E9EC8F2A6B71C5BE627CF22BC582880808BB3CF6229DCB52984FF3DB4A575F27872C4AD08A496AFDCF979146751DE8E4CF14182E2CCEFE656577B968A</string>
</dict>
</plist>

Modifiable Keys

The following manifest keys are modifiable in the Back Office:

  • AppName - The name of the app.

  • BundleID - The bundleID of the app.

    On initialising the SDK, the bundleID specified in the manifest and the bundleID of the app are checked. If they do not match a ClientException.appAndManifestBundleIDsDoNotMatch error is thrown.

  • AllowMultipleEntities - if true the SDK will allow certain entity specific APIs such as requestEntity(), CheckEntityExists() etc. to be called. Attempting to call these APIs when this setting is set to false will result in a Client Exception.

For further information see the Multiple Entities documentation.

  • RequiresSecureEnclave - if set to true, the SDK can only be initialised on a device that includes a Secure Enclave. On such devices the creation and storage of the private key (see certification process), and subsequent operations with it, all take place within the secureEnclave. If set to true and the device does not have a secureEnclave, a Client Exception is returned when initializing the SDK.

    Notes:

    Keys generated and stored in the secureEnclave are ECC (Elliptic Curve Cryptography) keys of 256 bits (equivalent to an RSA key of 3072 bits). Keys generated outside the secureEnclave are RSA keys of 2048 bits

    Use of ECC keys require a CA provider that is able to handle ECC signed Certificate Signing Requests.

    Although iOS 9 allows keys to be stored in the secure enclave, the SDK, for security reasons, relies on some specific iOS 10.3+ only functionality. For this reason use of the RequiresSecureEnclave flag requires a device running iOS 10.3 and above.

    Further information about the Secure Enclave can be found in Apple’s Security Guide.

  • NativeBiometricsRequiredForKeyAccess - if true, then any API that needs to access the generated private key (generated and stored on the device as part of the certification process) such as transaction confirmation or document signing will result in a native biometric authentication request such as TouchID or FaceID (second factor authentication) being presented to the user. For further information and details on how to manage the authentication process see the Native Biometric Authentication section.

Non Modifiable Keys

The following appear in the manifest but are populated in the manifest automatically and therefore are can not be modified.

  • EndPoint - The end point of the API. This is used by the SDK for all Client requests.

  • PublicKey - The public key associated with this app & entity. Used in the SDK for encrypting certain request parameters.

Manifest Error handling

The following manifest related errors can be returned when loading the manifest whilst Initializing the SDK.

  • BiidManifestException.manifestNotFoundInBundle - Manifest file not found in app bundle

  • BiidManifestException.failedToLoadManifest - Manifest file could not be loaded

  • BiidManifestException.invalidChecksum - Manifest checksum failed

  • BiidManifestException.manifestKeyMissing - A required manifest key is missing from the manifest

NB The above errors are returned wrapped in a ClientException.manifestException

In addition the following client exception can be returned during initialization:

Certificate Pinning

The biid SDK implements an additional level of security through the use of Certificate Pinning (SSL Pinning). Certificate pinning ensures that the SSL certificate returned from an SSL connection exactly matches a copy of the certificate stored locally within the app.

To implement certificate pinning, a copy of the SSL certificate, for the endpoint defined in the manifest file, needs be placed in the bundle of the app.

NB The certificate can be downloaded directly from the Back Office environment.

During initialization, the SDK will look through the app bundle and load any certificates it finds. All subsequent network requests then check for the matching certificate and if one isn’t found, a onNoConnection error is returned (see Error Handling for further details).

Notes:

It is highly recommended that certificate used for pinning is a non wild card leaf certificate for the endpoint

It is possible to include multiple certificates for the same endpoint.

Certificates should be in DER format, can have any name, but should have one of the following file extensions : .cer, .CER, .crt, .CRT, .der, .DER.

Thread safety

The biid Core SDK is completely thread safe. All SDK API calls should be executed on the main thread, leaving the SDK to manage any required asynchronous requests, threading as necessary.

All API responses are guaranteed to be returned on the main thread.

Referencing the biid Client

The biid client, and it’s APIs and properties, is accessible through the SDK’s getClient() function.

Assigning the biid client to a var can be done as follows:

Swift3

    var biidClient = SDK.getClient

ObjC

    id<Client>biidClient = [biidCoreSDK getClient];

    id<Client>biidClient = biidCoreSDK.getClient;

Alternatively the getClient function can be called inline if preferred:

Swift3

    SDK.getClient.xxxxxx

ObjC

    [biidCoreSDK.getClient xxxxxx];

NB Calling the getClient method more than once will always return the same instance.

Documentation

Initializing the SDK

The SDK can be initialized as follows:

Swift3

    do {
        try SDK.getClient.initialize()
    }
    catch (let exception) {
        // Handle exception
    }

ObjC

    NSError *error;
    [biidCoreSDK.getClient initialize:&error];
    if (error) {
        // Handle error
    }

Documentation

Roles

Once a user is authenticated, a role or roles is assigned to that user. Roles are used to control access to APIs. If the user is not assigned a role required for a particular API, in general a ClientException with be returned with an error message of Access is denied.

The roles assigned to a user are determined by a number of factors including the user’s status, their currently selected entity etc.

The available roles are:

  • guest - the role assigned to a user who is authenticated but not associated with an entity. A user with this role is limited to calling the requestEntitiesForUser API

  • user - the default role assigned once a user has authenticated against an entity but is not yet certified

  • userCertified - the role assigned to a user authenticated against an entity and who is also certified on the device

  • userExtended - an extended user role available to certified users on a secondary device. This role allows a certified user to see their transactions on a secondary device without having to certify on that device itself (see requestExtendPermissions for details)

  • userLocked - role assigned to an authenticated user who is has a user status of locked

To get the roles for the currently authenticated user, the getRoles() API can be used:

Swift3

      do {
          let roles = try SDK.getClient.getRoles()
      }
      catch (let exception) {
          // Handle exception
      }   

ObjC

    NSError *error;
    NSArray *roles = [biidCoreSDK.getClient getRoles:&error];

    if (error) {
        // handle error
    }

Documentation

Device InstallationID

A unique installationID for a device installation is required for successful user authentication.

The current installationID can be returned as follows:

Swift3

    do {
        let language = try SDK.getClient.getInstallationID()
    }
    catch (let exception) {
        // handle exception
    }

ObjC

    NSError *error;
    NSString *installationID = [biidCoreSDK.getClient getInstallationID:&error];

    if (error) {
        // handle error
    }

Documentation

By default an installationID is automatically generated for each new app installation.

However it is possible to set the installationID to a specific value. For example if it needs to match an ID used in another service in the solution.

In this case the installationID can be set using the setInstallationID API (see below).

Regardless of how the installationID is populated (manually set or automatically generated), the ID is persisted by the SDK and only needs to be set once per app installation (if the app is deleted and re-installed from a backup the installationID will be lost).

NB The installationID must be unique per installation. If this is not the case, attempting to authenticate the user will result in a ClientException error of OAuth request failed.

The installationID can be set as follows:

Swift3

    do {
        try SDK.getClient.setInstallationID (installationID: installationID)
    }
    catch (let exception) {
        // handle exception
    }

ObjC

    NSError *error;
    [biidCoreSDK.getClient setInstallationID:installationID error:&error];

    if (error) {
        // handle error
    }

Summary points for the installationID:

  • Only set the ID if the installation ID needs to match that of an existing ID.
  • Set the ID before authentication, set it the first time the application is launched.
  • Do not set it more than once (unless you use the same value).
  • Not setting it will result in installationID being to set by the SDK to a generated GUID.
  • The installationID can be accessed by getInstallationID().
  • The installationID is persisted by the SDK.
  • The InstallationID will not be backed up, either locally or to iCloud, and therefore will not be restored from backup.

Documentation

Native Biometric Authentication

If the NativeBiometricsRequiredForKeyAccess setting is set to true in the manifest file then calling any API that accesses a private key (i.e. user certification, document signing, authentication confirmation) will result in a native biometric authentication request (TouchID or FaceID) being presented to the user before the API request can continue. If authentication is not obtained then the API request will fail.

Internally biometric authentication is managed by way of a class named LAContext. A LAContext instance has a number of inherent properties, the two most important being those used for Authentication reuse and Authentication reason.

NB On devices that do not support biometrics, a Device Password dialog will be displayed instead.

Authentication Reuse

In order to provide a more user friendly user experience and to reduce the number of times a user is asked to authenticate, the SDK sets a reuse period during which authentication automatically succeeds, without prompting the user to authenticate again.

If there is a requirement to override this behaviour, that is to force the display of an authentication dialog when the private key is next accessed, this can be achieved by calling forceAuthenticationOnNextKeyAccess(:) sometime prior to the any call that may require authentication such as document signing, authentication confirmation or user certification.

Swift3

    SDK.getClient.forceAuthenticationOnNextKeyAccess(withReason:"Authentication required")

    SDK.getClient.forceAuthenticationOnNextKeyAccess() // use default reason

ObjC

    [biidCoreSDK.getClient forceAuthenticationOnNextKeyAccessWithReason:"Authentication required"];

    [biidCoreSDK.getClient forceAuthenticationOnNextKeyAccessWithReason:@""]; // use default reason

Documentation

Authentication Reason

An authentication dialog includes text detailing the reason why authentication is required. The SDK considers this text to be a localizable string and so it is possible to localize it by creating a Localizable.strings file for each language that needs to be supported and setting the authentication-required key value accordingly:

For en localized.strings file:

"authentication-required" = "Please authenticate";

For es localized.strings file:

"authentication-required" = "Por favor autentíquese";

In addition, in iOS 11 and above, it is also possible to set the reason as an argument to the forceAuthenticationOnNextKeyAccess(:) method or directly as follows:

Swift3

    let reason = NSLocalizedString("signing-authentication-reason", comment: "")
    SDK.getClient.setAuthenticationReason(to: reason)

ObjC

    NSString *reason = NSLocalizedString(@"signing-authentication-reason", comment: "");
    [biidCoreSDK.getClient setAuthenticationReason:reason];

Notes:

The reason set will remain until either the app is terminated or forceAuthenticationOnNextKeyAccess(:) is called resulting in the reason being reset to it’s default value.

If the authentication reuse period is still valid, no dialog will be presented regardless of setting the reason

Documentation

When setting a reason, considering the following advice from Apple:

The string you present to the user should provide a clear reason for why you are requesting they authenticate themselves, and what action you will be taking based on that authentication. This string should be provided in the user’s current language and should be short and clear. It should not contain the app name, because that appears elsewhere in the authentication dialog

Language Settings

See localization for details on how to return and set the language code used for localised content.