Best practices for using the AppConnect for iOS SDK

The following are best practices for developing secure enterprise apps:

Display authorization status in the home screen

When an app becomes unauthorized or retires, the authState property on the AppConnect object changes to ACAUTHSTATE_UNAUTHORIZED or ACAUTHSTATE_RETIRED. Additionally, the authMessage property changes to a string that explains to the device user why the app is unauthorized or retired. The string sometimes also explains what the device user can do to make the app authorized again.

The app should display the authMessage string. However, consider that since the app is now unauthorized or retired, the app must exit its secure functionality. Therefore, the best user experience is to display the string in a home view that never contains secure information.

The following alternatives for displaying the authMessage string are not recommended:

  • Do not display the string using UIAlertView on top of the current view. Beneath the message, the current view can still have secure information visible.
  • Do not use the -displayMessage: method. This method does not match the look of your app.
  • Do not exit the app without displaying the string.

Allow the user to enter credentials manually

Always provide a way for a user to enter login credentials manually in your app. Provide this user interface even if you are receiving login credentials in app-specific configuration information from the AppConnect library.

As described in Configuration specific to the app, an Ivanti server administrator can set up configuration information for your app on the server. Your app receives the information using the AppConnect for iOS SDK. This information can include authentication credentials, such as username, password and certificates, for a corporate service. Because the app receives the information, the device user does not have to enter the information.

However, if the credentials change, the amount of time for the change to reach your application can vary. Some variables that impact this notification include:

  • the app checkin interval that the administrator configured on the Ivanti server. This value is the maximum number of minutes until devices running AppConnect apps receive updates of their AppConnect policies and app-specific configurations.
  • whether the device has network coverage.

Therefore, providing changes to devices is not a real-time process and can take up to several hours. Therefore, if the corporate service rejects the credentials, provide a way for the user to enter the credentials manually.

Use the AppConnectDelegate protocol for notifications

Use methods of the AppConnectDelegate protocol to receive notifications of changes to:

  • the authorization status and associated message.
  • the permission status for copying content to the iOS pasteboard, using document interaction (Open In and Open From), and print.
  • app-specific configuration.

Do not use the iOS SDK’s key-value observing capabilities instead of AppConnectDelegate protocol notifications.

Consider the following scenario in which the AppConnect library receives a new authorization status:

  1. The authState property on the AppConnect object changes from ACAUTHSTATE_AUTHORIZED to ACAUTHSTATE_UNAUTHORIZED.
  2. The authMessage property on the AppConnect object changes from “The app is authorized.” to “The app is not authorized because your device OS is compromised.”
  3. The AppConnect library calls the -appConnect:authStateChangedTo:withMessage method on the AppConnectDelegate.

Now consider what can happen if you use key-value observing on the authState property. When authState changes, an application typically displays to the user the string in authMessage. Because the authMessage string has not yet changed, the user sees the original message that “The app is authorized.” However, the app is no longer authorized.

Using only the AppConnectDelegate’s callback methods avoids such inconsistencies.

Limit the size of configuration data from the Ivanti server

Do not design your app to use large amounts of configuration data from the Ivanti server.

As described in Configuration specific to the app, an Ivanti server administrator can set up configuration information for your app on the server. Your app receives the information using the AppConnect for iOS SDK. Use this capability only for short strings and options, such as server addresses, authentication credentials, and certificates.

Do not use it for larger data items, such as documents, large blocks of HTML, or images. For large data items, use a web service to deliver the items. Use AppConnect configuration only to provide the URL for the web service.

Although no precise upper limit is defined for an item configured on the Ivanti server, a large item can impact server performance. It can also slow connectivity between the server and the Ivanti client app. A very large item can possibly cause the communication protocol between the Ivanti server and the Ivanti client app to fail entirely.

Use the UIApplication’s delegate as you normally would

The AppConnect library depends on knowing about application life cycle events, such as when the application becomes active. Requiring the app to pass every life cycle event to the AppConnect library would be too much of a burden on the app. Therefore, the AppConnect library installs a UIApplicationDelegate proxy. This proxy sits between the UIApplication and your application’s UIApplicationDelegate.

Your application does not do anything to support the proxy. Use your UIApplicationDelegate as you normally would:

  • The AppConnect library does not filter or modify any messages sent by iOS to the UIApplicationDelegate.

  • You can still add custom methods to your UIApplicationDelegate. Call the custom method as you normally would, such as in the following statement:

    [[UIApplication sharedApplication] delegate] customMethod];

    The proxy passes the method invocation to your UIApplicationDelegate.

  • You can set a new UIApplicationDelegate as you normally would:

    [[UIApplication sharedApplication] setDelegate:myOtherAppDelegate];

Until AppConnect 4.0 for iOS, the UIApplicationDelegate proxy caused side effects. Now these side effects do not occur, The side effects of the proxy were:

  • The following expression did not return your UIApplicationDelegate’s class:

    [[[UIApplication sharedApplication] delegate] class]

    Instead, it returned the proxy class.

    Therefore, prior to AppConnect 4.0, using isKindofClass: was necessary. For example, the following returned YES:

    [[UIApplication sharedApplication] isKindOfClass:[MyAppDelegate class]]

  • The following expression did not return your UIApplicationDelegate object:

    [[UIApplication sharedApplication] delegate]

    If you required access to your UIApplicationDelegate object, the AppConnectUIApplication class provided a property called originalDelegate. Because this property is no longer necessary, it is deprecated.

    See AppConnectUIApplication class.

Consider limitations when using the iOS simulator

To fully test an AppConnect app, debug on a tethered device using Xcode, as you would for any other app. On a device, your testing includes the Ivanti client app, which is necessary for the complete flow of data from the Ivanti server to your app.

You can do initial functionality testing in the iOS simulator in Xcode. You can link against the AppConnect library when building for the iOS simulator as you normally would.

However, when using the AppConnect library in the iOS simulator, the AppConnect library always sets the properties on the AppConnect singleton as follows:

  • the authState property is set to ACAUTHSTATE_AUTHORIZED
  • the config property has no entries
  • the pasteboard property is set to ACPASTEBOARDPOLICY_AUTHORIZED
  • the openInPolicy property is set to ACOPENINPOLICY_AUTHORIZED
  • the openFromPolicy property is set to ACOPENFROMPOLICY_AUTHORIZED
  • the printPolicy property is set to ACPRINTPOLICY_AUTHORIZED

This behavior is necessary because no simulator version of the Ivanti client app is available, and the Ivanti client app is necessary for your app to receive notifications. Without notifications, the authState property cannot change to ACAUTHSTATE_AUTHORIZED, and your app cannot execute its logic that accesses its secure data and functionality. The AppConnect library’s special simulator behavior solves this problem, allowing you to use the iOS simulator to test your app’s functionality. You cannot, however, use the simulator to test handling notifications from the AppConnect library.

Enable the AppConnect library to blur screens when the app becomes inactive

AppConnect 4.0 for iOS added support for blurring screens when the app becomes inactive. Use this capability of the AppConnect library, as described in Enable screen blurring. If your app provided its own screen blurring, remove that code. By using the AppConnect library’s screen blurring capability, all AppConnect apps behave consistently.

Do not put secure data in the app bundle

Files that you package in your app bundle are not AppConnect-encrypted files. Also, files packaged with an app cannot be modified at runtime. Therefore, these files are not secure. Therefore, include only non-sensitive data in the app bundle.

Indicate to the user that the app is initializing

Indicate in the user interface that the app is initializing if the app requires the AppConnect singleton’s instance properties to determine what to do. For example, use an activity indicator (spinner). Remove the indication after the app is notified that the AppConnect singleton is ready.

One reason this indication is important involves when to display sensitive data. Do not show any sensitive data until the AppConnect singleton is ready, because until that time, the app cannot determine whether it is authorized. Only an authorized app should show sensitive data.

Reject custom keyboard control

Custom keyboard extensions sometimes send data to servers when a device user enters data into an app. They send this data for assistance with word-prediction, for example. This behavior has potential for harmful data loss. Ivanti server administrators can control whether your app can use a custom keyboard by specifying a key-value pair (MI_AC_IOS_ALLOW_CUSTOM_KEYBOARDS) on your app’s configuration. Your app can control whether custom keyboards are allowed if the server administrator has enabled the key-value pair.

To reject custom keyboards when the server administrator has enabled the key-value pair, implement the -shouldAllowExtensionPointIdentifier: method on your AppDelegate as follows:

// Reject all non-native keyboards.
- (BOOL) application:(UIApplication *) application
 	shouldAllowExtensionPointIdentifier:(NSString *)extensionPointIdentifier 
{
 
    	if ([extensionPointIdentifier 
		isEqualToString:UIApplicationKeyboardExtensionPointIdentifier]) 
	{
		return NO;
	}
	return YES;
}

Custom keyboard control

Do not use UIWebView to upload sensitive data

When an app uploads data, such as a file or image, using UIWebView, the UIWebView object saves the data in a folder on the device. The folder is Apps/<app name>/tmp. The data is then available using, for example, iExplorer.

Therefore, apps should not use UIWebView to upload sensitive data. If you cannot change the app’s use of UIWebView, be sure to delete any sensitive data from the folder after each upload attempt, whether successful, unsuccessful, or canceled.

Provide documentation about your app to the Ivanti server administrator

Whether your app is an in-house app or is available from the Apple App Store, an Ivanti server administrator configures the server with information about your app. Provide the server administrator documentation that specifies:

  • whether you app enforces the print policy.

The server administrator needs to know whether allowing or not allowing your app to use print capabilities has impact on your app’s behavior.

Because the AppConnect library enforces the pasteboard and Open In policies, the server administrator needs no documentation from your app about how it handles it, even if you disable or enable special related user interfaces.

  • whether your app handles the pasteboard policy.

    Although the AppConnect library enforces the pasteboard policy, inform the server administrator if your app enables or disables any special user interfaces depending on the policy status. This documentation allows the administrator to better understand your app’s expected behavior.

  • whether you app handles the Open In policy.

    Although the AppConnect library enforces the Open In policy, provide information so that the server administrator understands your app’s expected behavior and recommendations. Specifically, document the following:

    • Whether your app enables or disables any special user interfaces depending on the policy status.
    • Whether your app informs end users when they tap to open a document in an app for which Open In is not allowed. That is, document whether you have implemented the
      -appConnect:openInAttemptedWhenACOpenInPolicyBlocked: callback method.
    • Whether you have a recommended list of whitelisted apps. If you do, document their bundle IDs.
  • whether you app handles the Open From policy.

    Although the AppConnect library enforces the Open From policy, provide information so that the server administrator understands your app’s expected behavior and recommendations. Specifically, document the following:

    • Whether your app has any special user interfaces depending on the policy status.
    • Whether your app informs end users when they have tapped another app to open a document in your app, but your app is not allowed to receive documents from the other app. That is, document whether you have implemented the
      -appConnect:openFromAttemptedWhenACOpenFromPolicyBlocked: callback method.
    • Whether you have a recommended list of whitelisted apps. If you do, document their bundle IDs.
  • whether you app enforces the secure file I/O policy.

    The server administrator needs to know whether your app uses secure file I/O for its sensitive data.

  • the app-specific configuration key-value pairs.

    Provide a list of the key-value pairs that your app expects to receive through the AppConnect API. Provide each key’s default value if it has one. Specify if the value should default to the device’s user’s LDAP user ID, password, or email address.

  • the encryption group Id app-specific configuration key name for shared secure files.

    If your app uses the Secure file I/O API details to share encrypted files with other AppConnect apps, provide the key name of the encryption group Id that your app expects to receive through the AppConnect API. Also, list the AppConnect apps that your app expects to share files with, so the server administrator can provide the same value to the encryption group Id key for each of those apps.

  • the values for the app-specific configuration keys MI_AC_SHARED_GROUP_ID and MI_AC_ACCESS_CONTROL_ID

    If your app provides an extension to share secure files with other AppConnect apps, provide the value of these keys. Your app receives these key-value pairs through the AppConnect API. Also, list the AppConnect apps that your extension expects to share files with, so the server administrator can provide the same key-value pairs for each of those apps.

  • AppTunnel information

    If your app expects to interact with internal servers using AppTunnel, specify whether your app expects to work with AppConnect with HTTP/S tunneling, or whether it requires AppConnect with TCP tunneling.

    Also, provide information about the internal servers.

    For example:

    • Explain the type of servers your app interacts with, such as, for example, SharePoint servers.
    • Specify if your app expects to receive internal servers’ host names using the app-specific configuration API.
    • Specify if your app expects to be able to interact with all internal servers.
    • If you are an in-house app developer, provide the host names of the internal servers that your app interacts with. Also, provide the port number on each internal server that the app connects to.
  • HTTPS connections that your app makes that use certificate authentication to an enterprise service.

    For in-house app developers, provide the URLs of the enterprise services that use certificate authentication.

    If your app receives these URLs through app-specific configuration, make sure you listed the URLs in the app-specific configuration key-value pair documentation.

  • Dual-mode app behavior.
    • Provide expected behavior and features in AppConnect mode versus non-AppConnect mode.
    • If your app allows the device user to switch between AppConnect mode and non-AppConnect mode, document what the device user must do.
  • Whether your app uses the AppConnect-provided screen blurring capability

    Server administrators need to know whether your app will be impacted if they disable screen blurring for your app.

  • Whether your app does not allow some or all custom keyboards.
  • Whether your app includes the MI_AC_DISABLE_SCHEME_BLOCKING key set to YES in its Info.plist.