User registration

This topic guide explains all the steps required to add user registration to your app. In case you didn't add the SDK to your application project yet, please follow the steps in the setting up the project topic guide.

The SDK is accompanied by a separate Example App which provides a basic implementation and shows how to interact with the SDK. The SDK relies on the app to perform certain tasks which can not be performed by the SDK itself.

The Example App demonstrates the essential steps which must be performed by the App developer.

User registration is performed using the ONGUserClient. The instance can be obtained by using @property (nonatomic, readonly) ONGUserClient *userClient; of the ONGClient object or by calling[ONGUserClient sharedInstance] method. Attempt to obtain ONGUserClient without configuring the SDK first, will result in throwing NSInternalInconsistencyException exception.

The SDK does not provide any UI components but leaves this up to the app. The result of every operation on the ONGUserClient is reported back to the App via a delegate. Hence, the SDK does provides delegate interfaces that must be implemented by the app. All callbacks are performed on the main queue so the app developer can invoke methods on UIKit components directly without having to deal with queue management. These delegates are called once a specific action is required to be taken by the app or to give the result of a requested action back to the app.

Introduction

The SDK uses the OAuth 2.0 protocol to authenticate the device to access protected resources. To support this protocol the SDK acts as an OAuth 2.0 client.

Register user

User registration is one of the first things that you need to take care of. User registration essentially means connecting a user account to a mobile application installed on a device. It is possible to register multiple user accounts with the same application. If multiple users need to be registered the registration flow that is described below needs to be triggered once for every user. There is one restriction: you cannot register the same user multiple times. If you try to register the same user account twice you will essentially override the first registration for that user. Hence, it will not fail but it will reuse the profile that was already created for that user on the device.

The ONGUserClient offers a method to register a new user profile. The new user profile value object will be generated during the authentication process and will be returned in the success callback.

This methods is called registerUserWithIdentityProvider:scopes:delegate: and requires three arguments:

  • identityProvider (nullable ONGIdentityProvider *) a specific identity provider used for registration, if nil is provided the token server will pick a default identity provider
  • scopes (nullable NSArray<NSString *> *) the scopes authentication is requested for, when no scopes are requested the default scopes of the application will be used,
  • delegate (ONGRegistrationDelegate) the delegate delegates control back to the app in case it needs to do something or in case of a successful or failed registration attempt. The delegate must implement the methods specified in the ONGRegistrationDelegate class.

The example below shows you how to call the registerUserWithIdentityProvider:scopes:delegate: method and let the calling class also implement the required delegate:

[[ONGUserClient sharedInstance] registerUserWithIdentityProvider:nil scopes:@[@"read"] delegate:self];

// Handle specific registration challenge 

- (void)userClient:(ONGUserClient *)userClient didRegisterUser:(ONGUserProfile *)userProfile identityProvider:(ONGIdentityProvider *)identityProvider info:(ONGCustomInfo *_Nullable)info
{
    // The user is successfully registered
}

The platform supports two main types of Identity Providers: browser and custom API. Both types of Identity Providers can be defined and configured in the Token Server configuration. All Identity Providers that are configured in the app are returned by the SDK as ONGIdentityProvider. If you would like to read more about it please refer to Identity Provider guide.

Depending on the identity provider type SDK starts the registration process accordingly. Please see Browser Identity Provider and Custom API Identity Provider there is described how handles specific registration challenge type.

Note: If you are using default identity provider you must know its type to handle appropriate methods from ONGRegistrationDelegate

The object passed as the delegate must conform to the ONGRegistrationDelegate protocol. The Onegini SDK will call the following methods on it:

  • userClientDidStartRegistration: - method called when user registration is started.
  • userClient:didReceiveBrowserRegistrationChallenge - method called when the registration action requires you to open a browser with the given URL.
  • userClient:didReceiveCustomRegistrationInitChallenge: - method called when the initialization of two step custom registration requires a optional data to continue.
  • userClient:didReceiveCustomRegistrationFinishChallenge: - method called when the second step of two step custom registration or one step custom registration requires a optional data to continue.
  • userClient:didRegisterUser:identityProvider:info: - method called when registration action is completed with success.
  • userClient:didFailToRegisterWithIdentityProvider:error: - method called when registration action failed with error.
  • userClient:didReceivePinRegistrationChallenge: - method called when registration action requires creation of a PIN to continue.

Choose a PIN

The next step in the registration process is letting the user select a PIN. This process is triggered by the SDK. It delegates control over to the app by calling the userClient:didReceivePinRegistrationChallenge: method on the ONGRegistrationDelegate.

The userClient:didReceivePinRegistrationChallenge: method has two parameters:

  • userClient (ONGUserClient) user client performing registration.
  • challenge (ONGCreatePinChallenge) create pin challenge used to complete registration.

Challenge object represents create PIN challenge. It provides all information about the challenge and the sender awaiting for the response:

  • userProfile (ONGUserProfile) user profile for which create PIN challenge was sent.
  • pinLength (NSUInteger) required length for a new PIN.
  • error (NSError) error describing cause of failure of previous challenge response. Possible error domains: ONGPinValidationErrorDomain, ONGGenericErrorDomain.
  • sender (id<ONGCreatePinChallengeSender>) sender awaiting for response to the create PIN challenge.

Response to the create PIN challenge is sent using respondWithCreatedPin:challenge: method of the challenge sender.

Example implementation of userClient:didReceivePinRegistrationChallenge: delegate method:

- (void)userClient:(ONGUserClient *)userClient didReceivePinRegistrationChallenge:(ONGCreatePinChallenge *)challenge
{
    [self askUserToCreatePin:^(NSString *createdPin) {
        // Once the user has entered the PIN call the delegate
        [challenge.sender respondWithCreatedPin:createdPin challenge:challenge];
        // Or cancel challenge
        [challenge.sender cancelChallenge:challenge];
    }];
}

The respondWithCreatedPin:challenge: method of the ONGCreatePinChallengeSender needs to be called in order to let the SDK process the provided PIN. The SDK might trigger an error in case the chosen PIN is invalid. This could be because it is not compliant with PIN policy for example. The possible errors are specified in the ONGPinValidationErrorDomain.

Below follows an example implementation of challenge error handling:

- (void)userClient:(ONGUserClient *)userClient didReceivePinRegistrationChallenge:(ONGCreatePinChallenge *)challenge
{
    // Once the user has entered the PIN call the delegate
    [self askUserToCreatePin:^(NSString *createdPin) {
        [challenge.sender respondWithCreatedPin:createdPin challenge:challenge];
    };
    NSString *errorDescription = nil;

    if ([challenge.error.domain isEqualToString:ONGPinValidationErrorDomain]) {
        switch (challenge.error.code) {
            case ONGPinValidationErrorPinBlackListed:
                errorDescription = @"Provided PIN was marked as blacklisted on the Token Server.";
                break;

            case ONGPinValidationErrorPinShouldNotBeASequence:
                errorDescription = @"Provided PIN contains a not allowed sequence";
                break;

            case ONGPinValidationErrorPinTooShort:
                errorDescription = @"Provided PIN is too short";
                break;

            case ONGPinValidationErrorPinShouldNotUseSimilarDigits: {
                NSNumber *maxSimilarDigits = error.userInfo[ONGPinValidationErrorMaxSimilarDigitsKey];
                errorDescription = [NSString stringWithFormat:@"A PIN with less %zd similar digits must be chosen", maxSimilarDigits];
            }
                break;
        }
    } else {
        // general error
        errorDescription = error.localizedDescription;
    }

    // show error to user
    }

The PIN must not be stored anywhere on the device as this creates a security issue since an attacker potentially could extract it from the device.

Note: See the PIN handling recommendations for more information about handling the user PIN correctly.

After the user has successfully provided the PIN, the registration process is finished. One of the following methods on your implementation of the ONGRegistrationDelegate will be called, depending on the outcome of the registration process.

A successful outcome of the user registration will result in a user profile object. This object is the connection between the user and the registered profile in the SDK. We recommend to ask the end-user to provide a human readable reference to this profile (e.g. a name). There is also an identity provider object returned for which the user registration succeeded. Additionally in case when custom API identity provider was used, SDK might return the custom info object which might contain more detailed information.

In order to initiate authentication this user profile object needs to be provided to the SDK, therefore it is recommended to let the user choose a name for his profile so he can easily remember which user account it is linked to.

A failure outcome of the user registration will result in an error and identity provider object for which an error occured.

- (void)userClient:(ONGUserClient *)userClient didRegisterUser:(ONGUserProfile *)userProfile identityProvider:(ONGIdentityProvider *)identityProvider info:(ONGCustomInfo *_Nullable)info
{
    // the user is successfully registered
}

- (void)userClient:(ONGUserClient *)userClient didFailToRegisterWithError:(NSError *)error identityProvider:(ONGIdentityProvider *)identityProvider
{
    // handle authentication error
}

Deregister user

User deregistration implies the removal of all access and refresh tokens from the device for this user account. The SDK will also send a request to the token server to revoke all tokens server side.

The deregisterUser:completion: method requires two arguments:

  • userProfile (ONGUserProfile) the user profile that must be deregistered
  • completion (void (^)(BOOL deregistered, NSError *error)) the completion block that notifies caller about result of the deregistration action and error (if any). Possible error domains are ONGDeregistrationErrorDomain and ONGGenericErrorDomain.

The example below shows you how to call the deregisterUser:completion: method:

[[ONGUserClient sharedInstance] deregisterUser:user completion:^(BOOL deregistered, NSError * _Nullable error) {
    if (deregistered) {
        // Code invoked after the user is deregistered..
    } else {
        // depending on error reason the user has been deregistered locally but the communication with the server failed.
    }
}];