Custom API Identity Provider

When a user tries to register with an Identity Provider (IdP) that has a custom 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.

Registration types

One step registration

One step registration process can be described as follows:

1. App -> SDK: start user registration with selected custom IDP
2. SDK -> App: ask for registration data
3. App -> SDK: provide registration data
4. SDK -> TS: send registration data
5. TS -> XE: register user
6. XE -> TS: send registration result
7. TS -> SDK: send registration result
8. SDK -> App: send registration result

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

Two step registration

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

Two step registration process can be described as follows:

1. App -> SDK: start user registration with selected custom IDP
2. SDK -> App: ask for initialization data
3. App -> SDK: provide initialization data
4. SDK -> TS: send initialization data
5. TS -> XE: initialize registration
6. XE -> TS: provide initialization result
7. TS -> SDK: provide initialization result
8. SDK -> App: ask for registration data
9. App -> SDK: provide registration data
10. SDK -> TS: send registration data
11. TS -> XE: register user
12. XE -> TS: send registration result
13. TS -> SDK: send registration result
14. SDK -> App: send registration result

Handling Custom Registration Challenge

When registering a user the application will receive a custom registration challenge containing a used identity provider, which must be handled. The challenge will be passed as an argument to userClient:didReceiveCustomRegistrationInitChallenge: and userClient:didReceiveCustomRegistrationFinishChallenge: methods of your ONGRegistrationDelegate.

Depending on the registration type used for an identity provider the handling is performed slightly differently:

  • One step - the SDK will call only the userClient:didReceiveCustomRegistrationFinishChallenge: method on your delegate.
  • Two step - first the SDK will call userClient:didReceiveCustomRegistrationInitChallenge: in order to handle the first step. The second step will start automatically after the first step is handled. Then the SDK will call userClient:didReceiveCustomRegistrationFinishChallenge: in order to handle the second step.

Both userClient:didReceiveCustomRegistrationInitChallenge: and userClient:didReceiveCustomRegistrationFinishChallenge: methods have two parameters:

  • userClient (ONGUserClient) user client performing registration.
  • challenge (ONGCustomRegistrationChallenge) challenge containing selected identity provider used to perform a registration.

Challenge object represents a custom registration challenge. It provides all information about the challenge and the sender awaiting for the response:

  • userProfile (ONGUserProfile) user profile for which custom registration challenge was sent.
  • identityProvider (ONGIdentityProvider) identity provider used for registration.
  • info (ONGCustomInfo) optional data used to perform a registration.
  • error (NSError) error describing cause of failure of previous challenge response. Possible error domains: ONGGenericErrorDomain.
  • sender (id<ONGCustomRegistrationChallengeSender>) sender awaiting for response to the custom registration challenge.

You can respond to the challenge using sender object by calling one of the following methods:

  • respondWithData:challenge: - used to deliver the optional data to the SDK
  • cancelChallenge - used for registration cancelation

The data used to respond to the challenge is sent to the Token Server and interpreted by the Extension Engine. When there are no issues detected the SDK will proceed by sending next challenge. In case of error Extension Engine specifies two groups of error codes that are returned within the ONGCustomInfo object:

  • Recoverable errors (4000 - 4999) - the registration flow can be recovered, the SDK will call either the userClient:didReceiveCustomRegistrationInitChallenge: or userClient:didReceiveCustomRegistrationFinishChallenge: method again, depending on the step that has caused the error. It allows to retry the step by the user.
  • Unrecoverable errors (5000 - 5999) - the registrations flow cannot be recovered and it has to be started from the beginning.

Example implementation for handling init step:

- (void)userClient:(ONGUserClient *)userClient didReceiveCustomRegistrationInitChallenge:(ONGCustomRegistrationChallenge *)challenge
{
    // Continue user registration with optional data
    [challenge.sender respondWithData:@"optional data" challenge:challenge];

    // Or cancel challenge
    [challenge.sender cancelChallenge:challenge];
}

Example implementation for handling finish step:

- (void)userClient:(ONGUserClient *)userClient didReceiveCustomRegistrationFinishChallenge:(ONGCustomRegistrationChallenge *)challenge
{
    // Continue user registration with optional data
    [challenge.sender respondWithData:@"optional data" challenge:challenge];

    // Or cancel challenge
    [challenge.sender cancelChallenge:challenge];
}