The App SDK provides a default UI for registering OTP and Photo ID authentication methods implemented as a View.
.png?sv=2026-02-06&spr=https&st=2026-09-30T03%3A55%3A03Z&se=2026-09-30T04%3A07%3A03Z&sr=c&sp=r&sig=jtcRt5CEVdwyse3okpg6ggcS7lrhSrjq7WODyH9IT3U%3D)
Default OTP View
This registration uses the Model-View-Controller (MVC) architecture which makes it easy to replace the UI without having to reimplement the core logic. To use your own UI, you need to provide your own implementation of this view. Your view (View or Fragment in the sequence diagram below) responds to user input by calling the NNLRegistrationController (Controller) functions to trigger the required functionality such as registering a non-FIDO authenticator (Model). The NNLRegistrationController uses Live Data to call back to your view so it can show the updates.
To provide your own UI:
Implement your own custom Fragment class that extends the BaseAdaptiveRegFragment class.
Important: For your Fragment to receive notifications from the Registration Controller, the App SDK provides class RegistrationViewModel. This class is called Registration Live Data in the diagram below following code in your Fragment so that the Controller notifies your Fragment when it needs to update its list of authentication methods:
Implement your own ViewController class, extending the NNLBaseAdaptiveRegViewController class and adopting the NNLIRegistrationLiveData protocol.
Implement your own ViewController factory, adopting the NNLIAdaptiveRegUIFactory protocol. For example, call it SampleAdaptiveRegUIFactory.
Initialize the SDK to use your custom UI factory by making the following call: NNLAdaptiveRegUIFactory.setInstance(SampleAdaptiveRegUIFactory())
The following diagram illustrates the MVC flow when the user adds an authentication method. The yellow boxes represent your code.
.png?sv=2026-02-06&spr=https&st=2026-09-30T03%3A55%3A03Z&se=2026-09-30T04%3A07%3A03Z&sr=c&sp=r&sig=jtcRt5CEVdwyse3okpg6ggcS7lrhSrjq7WODyH9IT3U%3D)
The steps in this diagram are described below:
Your application calls NNLAdaptiveUI.getRegistrationView().
NNLAdaptiveUI calls the createViewController() method of your custom NNLIAdaptiveRegUIFactory implementation to obtain the instance of your custom NNLBaseAdaptiveRegViewController class.
Your application shows the instance of NNLBaseAdaptiveRegViewController it just obtained.
Once your View is initialized, it calls onRefresh() from class NNLRegistrationController.
The Registration Controller calls the Server to get the list of authenticators for the user.
The Registration Controller calls the Live Data's setMethods() with the list of authenticators.
The Live Data object calls your View's setMethods() with the list.
Your View displays the list of authenticators.
The user selects an authenticator to add.
Your View calls the Registration Controller's onAdd() with the selected authenticator.
The Registration Controller performs the registration on the selected authenticator.
The Registration Controller calls the Live Data's onOperationCompleted().
The Live Data object calls your View's onOperationCompleted().
Refer to the Client API Docs for the NNLIRegistrationLiveData and NNLIAdaptiveRegUIFactory protocols and the NNLRegistrationController and NNLBaseAdaptiveRegViewController classes for more details.
Working Examples in Tutorial App
Refer to files SampleAdaptiveRegViewController.swift and SampleAdaptiveRegCell.swift for implementation.
Refer to RegisterViewController.swift file for usage.