Custom API Identity Provider

In case when user tries to register with an Indentity Provider (IdP) that has a custom API type, the SDK will use the custom registration functionality delivered by the app. In order to use the custom IdP, it has to be enabled and configured on the Token Server side, and implemented in the app itself. Usually when the custom IdP is created on the server side, you will also provide the server side script for handling the registration process on both client and server side.

One and two step registration

The MSP platform expects that the registration process can have either one or two steps.

One step registration

In case of one step registration the SDK asks the app for optional registration data. The data is send to the Token Server where the custom registration script is executed. The result of the custom script (status code and optional data) is send back to the SDK and the registration result is propagated to the app.

Two step registration

In case of two step registration the SDK asks the app for optional initial registration data. The data is send to the Token Server where the custom registration is initialized. The optional initialization result is send back to the SDK. Then the SDK asks the app for a registration data, providing the optional initialization data provided by the Token Server. The registration data is send to the Token Server where the custom registration script is executed. The result of the custom script (status code and optional data) is send back to the SDK and the registration result is propagated to the app.

Custom registration

OneginiCustomIdentityProvider

In order to use a custom IdP, you should provide an implementation of the OneginiCustomIdentityProvider interface to the SDK. The implementation provides the unique ID of the IdP along with methods that should be called during registration.

Example code for OneginiCustomIdentityProvider implementation

public class TwoWayOtpIdentityProvider implements OneginiCustomIdentityProvider {

  private final OneginiCustomRegistrationAction registrationAction;

  public TwoWayOtpIdentityProvider(final Context context) {
    this.registrationAction = new TwoWayOtpRegistrationAction(context);
  }

  @Override
  public OneginiCustomRegistrationAction getRegistrationAction() {
    return registrationAction;
  }

  @Override
  public String getId() {
    return "2-way-otp-api";
  }
}

OneginiCustomRegistrationAction

The OneginiCustomRegistrationAction interface is used to request a registration from the app and deliver the registration result back to the SDK. In case of a one-step registration the OneginiCustomIdentityProvider should provide an implementation of OneginiCustomRegistrationAction which has a finishRegistration method:

/**
 * The interface used to define custom registration action
 */
public interface OneginiCustomRegistrationAction {

  /**
   * The method called by the SDK when registration with custom IdentityProvider is required.
   *                                    
   * @param oneginiCustomRegistrationCallback the {@link OneginiCustomRegistrationCallback} object to return the registration result to
   * @param customInfo                        optional {@link CustomInfo} data for registration, provided by the Extension Engine
   */
  void finishRegistration(OneginiCustomRegistrationCallback oneginiCustomRegistrationCallback, CustomInfo customInfo);
}

In case of a two step registration the OneginiCustomIdentityProvider should provide an implementation of OneginiCustomTwoStepRegistrationAction which extends the OneginiCustomRegistrationAction to provide additional initRegistration method:

/**
 * The interface used to define the two-step custom registration action.
 */
public interface OneginiCustomTwoStepRegistrationAction extends OneginiCustomRegistrationAction {

  /**
   * The method called by the SDK when registration with custom IdentityProvider is required. This method is called for the first registration step,
   * for the second step the finishRegistration() method is used.
   *                       
   * @param registrationCallback the {@link OneginiCustomRegistrationCallback} object to return the registration result to
   * @param customInfo           optional {@link CustomInfo} data for registration, provided by the Extension Engine
   */
  void initRegistration(OneginiCustomRegistrationCallback registrationCallback, CustomInfo customInfo);
}

The OneginiCustomRegistrationCallback is a handler where you can provide either the optional data that should be send to the backend (Extension Engine script) or an Exception that occurred during the registration. In case of an exception the SDK will end the registration with a GENERAL_ERROR and original exception included as a cause.

The CustomInfo object contains a status code and an optional data provided by the backend script. The first step of registration flow will always return null CustomInfo. This means that the object will be null in the finishRegistration method of the one-step registration flow and in the initRegistration method of the two-step registration. The only exception to this rule is a retry of the registration step: in case of a recoverable error returned by the SDK the CustomInfo object in the retried step will contain the error info. There are three groups of status codes that can be returned in the CustomInfo object:

  • success status (2XXX) - when the status code is in the rage of 2000 - 2999 the registration step has been finished successfully.
  • recoverable errors (4XXX) - when the status code is in the range 4000 - 4999 the flow can be recovered and the SDK will call either the OneginiCustomTwoStepRegistrationAction#initRegistration or the OneginiCustomTwoStepRegistrationAction#finishRegistration method again, depending on the step that has caused the error.
  • unrecoverable errors (5XXX) - when the status code is in the range 5000 - 5999 the flow cannot be recovered and the SDK will return an error instead of retrying the step.

Example code for custom registration action implementation

public class TwoWayOtpRegistrationAction implements OneginiCustomTwoStepRegistrationAction {

  public static OneginiCustomRegistrationCallback CALLBACK;

  private final Context context;

  public TwoWayOtpRegistrationAction(final Context context) {
    this.context = context;
  }

  @Override
  public void initRegistration(final OneginiCustomRegistrationCallback callback, final CustomInfo customInfo) {
    // for a TwoWayOTP the initialization request doesn't contain data
    callback.returnSuccess(null);
  }

  @Override
  public void finishRegistration(final OneginiCustomRegistrationCallback callback, final CustomInfo customInfo) {
    // for a TwoWayOTP the initialization result contains the challenge code
    CALLBACK = callback;
    final Intent intent = new Intent(context, TwoWayOtpRegistrationActivity.class);
    intent.putExtra(OTP_CHALLENGE_EXTRA, customInfo.getData());
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(intent);
  }
}

Initialising the OneginiClient

To provide implementations of the OneginiCustomIdentityProvider to the SDK you can use OneginiClientBuilder#addCustomIdentityProvider or OneginiClientBuilder#setCustomIdentityProviders to either add one implementation to the SDK or give a Set of supported custom IdPs.

Example code for initializing the SDK with custom IDP

  return new OneginiClientBuilder(applicationContext, createPinRequestHandler, pinAuthenticationRequestHandler)
    // add a browser registration handler
    .setBrowserRegistrationRequestHandler(registrationRequestHandler)
    .setMobileAuthWithPushRequestHandler(new MobileAuthenticationRequestHandler(applicationContext))
    .setMobileAuthWithPushPinRequestHandler(new MobileAuthenticationPinRequestHandler(applicationContext))
    // add a custom identity provider
    .addCustomIdentityProvider(new TwoWayOtpIdentityProvider(applicationContext))
    .build();