This section covers configuration tasks to ensure that your app works properly.
You must add your app to the Authentication Server.
Most customers choose to embed authenticators rather than use remote authenticators.
You can change many default behaviors of your app using the client configuration file.
Adding your app to the server
Prior to releasing your completed app, you must add it to the Digipass S3 Server. Refer to Configure apps.
Ensure that any legal notices included with your app contain the proper attributions to third-party source licenses. Refer to the <APP_SDK_HOME>/licenses/ folder for the list of third-party source licenses used in the App SDK.
Embedding an authenticator
Use the App SDK to embed one or more FIDO ASMs into your mobile app by adding additional dependencies to the mobile app's project. By default, the App SDK embeds a Touch ID / Face ID ASM and a Presence ASM. However, you can develop and add others to enable unique authentication capabilities and experiences beyond those available with Touch ID.
Embeddable ASM components are delivered by an Authenticator vendor as an iOS framework for Xcode. The instructions below explain how to embed a sample ASM into your mobile application. These instructions are similar for any embeddable ASM created with the Digipass S3 Authenticator SDK.
Adding an authenticator
Open the AppDelegate.swift file and add the following code in application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) method for embedding an authenticator:
SampleASM.addSampleAuthenticator()Include the corresponding SampleASM module as follows:
import SampleASMEmbedding an authenticator using Xcode
The embeddable Authenticator is delivered as an iOS framework. The following instructions describe how to embed the SampleASM module included with the Authenticator SDK.
Open your app properties General tab and add SampleASM.xcframework into the Framework, Libraries and Embedded Content section.
The client configuration file
The client supports a configuration file, called mfac_cfg.json, that enables you to override default values that are hard coded in the App SDK. Place this file inside the main bundle. The configuration information is contained in a JSON object:
{
"Fieldname": Value1,
"Fieldname2": Value2
}The most commonly used fields are listed in the sections below. For details about other fields that can be used in mfac_cfg.json file, see the ClientConfig class (which has a function for each field listed here) in the Client API Docs.
Note that a different client configuration file, the JSON UI Configuration file, contains customizations that affect the user interface.
asmSelectionEnabled
Controls whether the client prompts the user to choose an authenticator to use. This is a boolean.
True (default): The client prompts the user to choose an authenticator to use, if the UAF policy matches multiple authenticators.
False: The client automatically picks the first matching authenticator and never prompts the user. Digipass doesn't recommend this option.
suspendRegistrationEnabled
Controls whether the user is able to suspend a credential's registration without removing it. This is a boolean and the default is False.
customClient
Specifies the client package name to use.
otpConfig
Configures SMS and email OTP by specifying the maximum number of retries, the amount of time the end user has to make those attempts, and the lockout period if the user fails to enter a registered email address or phone number. You can also configure this value from the Server, see Configure non-FIDO authentication methods.
An example JSON object with all available fields:
"otpConfig": {
"maxFalseAttempts": 3,
"probationPeriod": 20,
"lockoutPeriod": 20
}Field | Description |
|---|---|
maxFalseAttempts | Maximum number of failed attempts allowed for an end user. Recommended to be greater than 1. The default value is 3. |
probationPeriod | Time in seconds during which maxFalseAttempts are allowed. The default value is 0, which means that no time limit is enforced. When this expires, maxFalseAttempts and lockoutPeriod are reset. When the user makes maxFalseAttempts, the authentication fails and the user starts over. |
lockoutPeriod | After the user makes maxFalseAttempts, the user is locked out for lockoutPeriod seconds. The user cannot start a new authentication during that period. The default value is 10. |
pinConfig
Configures PIN creation behavior and specifies constraints. Configure anti-hammering behavior by setting maxFalseAttempts, probationPeriod, and lockoutPeriod.
An example JSON object with all available fields:
"pinConfig": {
"minLength": 5,
"maxLength": 6,
"maxRepeatDigits": 3,
"maxSequentialDigits": 4,
"confirmationButton": true,
"maxFalseAttempts": 3,
"probationPeriod": 20,
"lockoutPeriod": 20,
"nonReusableOldPINs": 0
}Field | Description |
|---|---|
minLength | Minimum PIN length. The default value is 4 and the value can’t be less than 4. |
maxLength | Maximum PIN length, cannot be less than minLength. The default value is 4. |
maxRepeatDigits | Maximum number of repeated digits in the PIN. The default value is 0, which means all digits can be repeated. |
maxSequentialDigits | Maximum number of sequential digits in the PIN. The default value is 0, which means all digits can be sequential, in either increasing or decreasing order. |
confirmationButton | Boolean field that controls whether or not the PIN confirmation button is displayed on the PIN ASM UI. The default value is true which means the button is displayed. The system automatically assigns true to this field if minLength and maxLength are different. |
maxFalseAttempts | Maximum number of incorrect PIN attempts, should be greater than 1. The default value is 10. |
probationPeriod | Time in seconds during which maxFalseAttempts are allowed. The default value is 0, which means then no time limit is enforced. |
lockoutPeriod | Time in seconds when the user is locked out after maxFalseAttempts is reached. The default value is 0, which means the PIN is deleted after maxFalseAttempts is reached. |
nonReusableOldPINs | Integer. The system prevents the user from using the previous nonReusableOldPINs PINs as a valid current PIN. The default value is 0, which means the system allows any previous PIN to be reused. |
sendCredentialProviderInfo
Boolean. Controls whether the App SDK sends information on available credential providers in its request to the Server. This information is used by the Server to suggest that the user authenticate with a passkey when a passkey is available on their device.
true (default): Send the additional information on available credential providers.
false: Do not send additional information on credential providers.
The App SDK uses the CloudKit framework to get the iCloud account ID. Note that you must add the CloudKit.framework to your Xcode project even if you set sendCredentialProviderInfo to false. See Importing the App SDK into Your Mobile App for instructions on how to enable CloudKit.
Configuring signal generation
The App SDK can generate and send signals to the Server when registering or authenticating. The Server can use these signals to decide which adaptive rules to apply to authentication or which FIDO policies to apply to registration or authentication. Since these signals take resources and time to process, you can configure in mfac_cfg.json whether or not they are generated as well as when they are generated.
You can specify signals for device jailbreak status, user location, metrics, App Attest, WiFi network and user on phone call. All signals allow the same configuration fields and values as described below.
Each signal’s configuration uses the following structure to control when it is generated. The field name specifies where the App SDK can place the generated signal in REST API client-server requests. The value controls whether the App SDK generates and sends the signals.
An example JSON object with all available fields for a sendLocationSignal signal that the App SDK should never send:
"sendLocationSignal": {
"init": "never",
"finish": "never",
"protocol": "never"
}Field | Description |
|---|---|
init | When to place the signal in the INIT request payload. Use this field for signals used by adaptive rules. Values: "always" | "never" | "silently" |
finish | Only use this if your Server version is 6.0.2 or newer. When to place the signal in the FINISH request payload. Use this field for signals used by FIDO policy risk rules. |
protocol | Only use this if your Server version is 6.0.1 or older. When to place the signal in the FINISH request inside the protocol message. Use this field for signals used by FIDO policy risk rules. Values: "always" | "never" | "requested" | "silently" |
The values mean:
always: Always generate the signal.
never: Never generate the signal.
requested: Generate the signal only if it is requested by the Server.
silently: If the user has already granted your client app permission to access the signal, then generate it. The advantage of this option is that it doesn't prompt the user if they haven't yet granted permission. This only applies to sendLocationSignal and sendWifiNameSignal since they require user permission.
To send a signal when implementing Quick Authentication, the setting for the signal must be always.
Device jailBreak status signal
sendJailBreakRiskSignal controls whether the App SDK automatically generates and sends the jailbreak signal.
Configure this signal as shown below if
You defined an adaptive rule or a FIDO policy that uses device health (device health uses the jailbreak signal).
Your Server is version 6.0.3 or later.
"sendJailBreakRiskSignal":{
"init": "always",
"finish": "requested",
"protocol": "never"
}This is the default configuration, which means that the App SDK never sends the jailbreak signal in the INIT request nor in the protocol message, and sends it in the finish response payload only if the Server requests it:
"sendJailBreakRiskSignal":{
"init": "never",
"finish": "requested",
"protocol": "never"
}See table above for field descriptions.
User location signal
sendLocation controls whether the App SDK automatically generates and sends the location signal. Configure this signal (use the default configuration) if you create adaptive rules that look at a user's location.
To enable your app to transmit location information to the Server, you must add the following key to the Info.plist file:
NSLocationWhenInUseUsageDescription
For example, the Info.plist file could contain the following:
<key>NSLocationWhenInUseUsageDescription</key>
<string>Location is required to find out where you are</string>Below is the default configuration, which means that the App SDK generates and sends the location signal in the INIT request only if the end user already granted permission to the App SDK, sends it in the finish response payload only if the Server requests it, and never sends it in a protocol message. Location needs to be sent during INIT so it can be used by an adaptive rule.
"sendLocationSignal":{
"init": "silently",
"finish": "requested",
"protocol": "never"
}See table above for field descriptions.
Metrics
sendMetrics controls when the App SDK sends metrics to the Server. Configure this signal if you would like to disable sending metrics to the Server.
"sendMetrics":{
"init": "never",
"finish": "never",
"protocol": "never"
}App Attest
sendAppAttest controls when the App SDK sends App Attest information to the Server. Configure this signal to disable sending App Attest information to the Server.
"sendAppAttest": {
"protocol": "never"
}By default, the App SDK sends the App Attest information only when the Server requests it:
"sendAppAttest":{
"protocol": "requested"
}See table above for field descriptions.
WiFi network signal
sendWifiNameSignal controls whether the App SDK automatically generates and sends the WiFi network name. Configure this signal (use the default configuration) if you define adaptive rules that look at a user's WiFi network. The end user must consent to allow the App SDK to access their WiFi SSID.
To enable your app to transmit WiFi name to the Server, add "Access WiFi information" capability to your app. Select TutorialAppPlus from the Targets. Navigate to Signing & Capabilities > + Capabilities > Access WiFi Information.
.png?sv=2026-02-06&spr=https&st=2026-09-30T00%3A38%3A44Z&se=2026-09-30T01%3A00%3A44Z&sr=c&sp=r&sig=BLwnttnNAoF2zpeR3fnwV80%2B7pcwrEt304pJ%2FIlYyUA%3D)
Also starting from iOS 13 you must enable location access from your app. See User Location Signal.
Below is the default configuration, which means that the App SDK generates and sends the WiFi SSID signal in the INIT request only if the end user already granted permission to the App SDK, it generates and sends the signal in the FINISH response payload only if the Server requests it, and it never sends it in the protocol message. The WiFi network needs to be sent during INIT so it can be used by an adaptive rule.
"sendWifiNameSignal":{
"init": "silently",
"finish": "requested",
"protocol": "never"
}See table above for field descriptions.
User on phone call
sendInCallState controls the generation of the in-call extension, a boolean that tells if the user is on a phone call or not.
"sendInCallState": {
"init": "never",
"finish": "requested",
"protocol": "never"
}See table above for field descriptions.
Localizing
If you are changing the style of the user interface, including colors and images, we recommend that you create cross-platform JSON UI configuration files which also localize strings. See Customizing Strings, Styles, Images and more.
Otherwise, if you are using the default App SDK UI, you can add a new localization to the custom or main bundle. If you are only localizing the strings in your application, we recommend this alternative, which is described in this section.
The App SDK looks for localization strings and resources in the custom or main bundle when it needs to display a UI to the user. If the strings are not found in the custom or main bundle, the framework gets the corresponding default English strings.
Customizing an existing localization
Duplicate the bundle module which needs to be customized.
Rename the duplicated bundle to custom.nnl.<ModuleName>.bundle. For example, to customize the PresenseASM bundle, you should rename it custom.nnl.PresenceASM.bundle.
Choose the language you want to customize from the custom.nnl.<ModuleName>.bundle, then navigate to that folder from the iOS terminal.
Use the plutil tool to convert binary to JSON format using the following command: /usr/bin/plutil -convert json NNLLocalizable.strings.
Open the NNLLocalizable.strings file in an editor. It has now been converted to JSON format and contains key and values. Modify the values with your customized translations and save the file.
From the terminal, run the following command:
/usr/bin/plutil -convert binary1 NNLLocalizable.strings.Add the custom.nnl.<ModuleName>.bundle to your application project SwiftPackages folder. Alternatively, add the custom bundle in the Copy Bundle Resources section in your Xcode project settings.
If you need to store bundles in a custom place that is not in the application main path, you need to call the NNLSetBundlesPath(NSString *strBundlesPath) function from your application to set the custom bundle path.
Adding a new localization to the local FIDO client
Open the package content of the module to add a new localization. For example, custom.nnl.PresenceASM.bundle.
Duplicate the en.lproj folder. Rename the folder to <locale>.lproj, where <locale> is the locale identifier string (LCID). For example, zh-Hans.lproj for Chinese-simplified language.
Navigate to the newly renamed folder from the terminal.
Repeat steps 4-6 from section Customizing an Existing Localization.
Do not modify the file name and tag names in the NNLLocalization.string file. Any modification might interfere with the correct display of localized strings.
Displaying localized strings for one language only
To only display the localized strings for a particular language (for example, Japanese) regardless of the language settings used on the iOS device, do the following:
Delete all other language folders in the nnl.TouchIDASM.bundle, leaving only the ja.lproj folder.
Make a copy of the ja.lproj folder and rename the copy to en.lproj.
The title of the Touch ID UI remains under the control of iOS and cannot be changed. This string is still displayed in English.
Localized strings loading order from the bundles
Check for a custom prefixed bundle string match in the mainBundle path.
Check for a custom prefixed bundle string match in the NNLSetBundlesPath path.
Check for NNL bundle string match in the NNLSetBundlesPath path.
Check for NNL bundle string match in the mainBundle path.
Return the string key if nothing else works.