Mobile authentication with Push

Two factor authentication can be implemented using APNs push notifications. It's a very secure and user friendly way of authentication. You can use this feature to allow users to confirm their transactions. Confirmation can be done using simple Accept button, PIN, Fingerprint or a FIDO authenticator. All transaction information is encrypted and no sensitive information is sent through APNs.

Configuration

Before mobile authentication with push can be used, you should configure:

When your app and token server are configured for push notifications you should be able to enroll for mobile authentication with push and handle push requests using Onegini SDK.

Enrollment

Push mobile authentication enrollment requires regular mobile authentication enrollment to be done first. Only after it is completed, you can enroll for the push.

Enrollment for the mobile authentication with push can be described as follows:

1. APP -> APNS: Register for remote notifications.
2. APNS -> APP: The device token is returned.
3. APP -> SDK: Enroll for push by providing the device token and completion block.
4. SDK -> Token Server: Enroll push mobile authentication with device token.
5. Token Server -> SDK: Acknowledge the enrollment process is completed.
6. SDK -> APP: The result of the enrollment flow is reported by completion block.

The first step is to obtain the deviceToken from APNs. Please follow the Apple remote notification guide for instructions on how to obtain it.

The next step is to enroll with the device token using the enrollForPushMobileAuthWithDeviceToken:completion: method of the ONGUserClient instance:

[[ONGUserClient sharedInstance] enrollForPushMobileAuthWithDeviceToken:deviceToken
                                                            completion:^(BOOL enrolled, NSError * _Nullable error) {}];

The result of the enrollment and, in case an error occurred, an error will be passed to the completion block.

Request handling

Once a user is enrolled, he/she should be able to receive push mobile authentication requests. To verify if the user is already enrolled for push mobile authentication, you should use the isUserEnrolledForPushMobileAuth: method on the ONGUserClient.

The entire push mobile authentication process from can be described as follows. In this flow we call the initiator of the mobile authentication request 'portal':

1. Portal -> Token Server: Initialize mobile authentication.
2. Token Server -> APNS: Send the push notification.
3. APNS -> Token Server: Push notification delivery report.
4. Token Server -> Portal: Identifier of the initialized mobile authentication transaction.
5. APNS -> APP: push notification.
6. APP -> SDK: Delegate handling of the push notification to the SDK.
7. SDK -> Token Server: Fetch PGP encrypted message from server.
8. Token Server -> SDK: Base64 encoded PGP encrypted authentication data.
9. SDK -> APP: The push message is decrypted and the SDK triggers a delegate so the app can show 
        a dialogue to the end-user.
10. APP -> SDK: Application responds with the authentication result.
11. SDK -> Token Server: The authentication result is send encrypted to the Token Server.
12. Token Server -> SDK: If the used push type requires feedback on the result e.g. pin usage 
        the result is communicated back to the SDK which will optionally perform a retry.
13. Token Server -> Portal: A callback is sent to inform the portal about the mobile 
        authentication result.

As you can see from the diagram above, the application has the following responsibilities:

  1. Passing push notification received from APNS to the Onegini SDK
  2. Responding to authentication challenges
    1. Displaying a dialog to the end-user when an authentication challenge is received
    2. Sending the users' response back to the SDK
  3. Handling the completion of the mobile authentication request

The Following paragraphs explain those steps and show how the responsibilities mentioned above can be implemented.

Passing a push notification (containing a mobile authentication request) to the SDK

The app itself is responsible for differentiating between different push notification messages. The reason why this responsibility is in the app is that one app can only have one push token. This allows the app to support more push messaging features besides mobile authentication provided by the Onegini SDK.

Before handling the push request its recommended to verify if the request can be handled by the Onegini SDK. It can be done by calling the canHandlePushMobileAuthRequest: method. If a push notification is intended for the SDK the payload will contain a transaction_id and the method will return YES.

Once the push request is verified it is handled by calling the handlePushMobileAuthRequest:delegate: on the ONGUserClient shared instance. Since notifications may require authentication, the SDK needs a delegate (ONGMobileAuthRequestDelegate) to authenticate.

Example code for push notification handling:

- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo 
{
  if ([[ONGUserClient sharedInstance] canHandlePushMobileAuthRequest:userInfo]) {
    [[ONGUserClient sharedInstance] handlePushMobileAuthRequest:userInfo delegate:delegate];
  } else {
    // Forward to another handler
  }
}

Responding to a challenge

After you have passed mobile authentication request to the SDK, the SDK will request the app to let the user either confirm or deny the request.

The SDK will delegate control back to the provided ONGMobileAuthRequestDelegate implementation. Hence, the application must contain a class that implements the methods specified below.

Mobile authentication requests are represented by ONGMobileAuthRequest class. Objects of this class are passed to every ONGMobileAuthRequestDelegate method. From those obejcts you can get following information about currently processes mobile authentication request:

  • userProfile - instance of ONGUserProfile for which request has been received.
  • type - string representing type of the notification which is configured in the Token Server admin panel. The type can be used to distinguish between business functionalities. For example, mobile authentication can be used for logging in or transaction approval.
  • message - message specified by the portal when initiating the mobile authentication request. This field represents the secure_message parameter sent while initiating the mobile authentication request. This message length is not limited.
  • userInfo - user info received from the -[UIApplicationDelegate application:didReceiveRemoteNotification:] The userInfo can also contain a message. The message specified in the userInfo object represents the message parameter that was sent while initiating the mobile authentication request. The length of this message is limited to 155 characters due to APNS' message length limitations. The value is set only for push mobile authentications.
  • transactionId - A unique identifier for each Mobile Authentication request.

When a challenge is received you should display UI containing selected information from ONGMobileAuthRequest and an interface which allows user to respond to the received challenge e.g. PIN screen when PIN challenge was received. The user's response should be send back to the SDK via the challenge sender object or through the confirmation block in case of confirmation challenge.

Confirmation

- (void)userClient:(ONGUserClient *)userClient 
        didReceiveConfirmationChallenge:(void (^)(BOOL confirmRequest))confirmation 
                             forRequest:(ONGMobileAuthRequest *)request 
{
    // Code to display your mobile authentication confirmation view here..

    // Once the user has answered the confirmation, call the confirm method specifying whether 
    // the user confirms or denies the request
    confirmation(YES);
}

PIN

- (void)userClient:(ONGUserClient *)userClient 
        didReceivePinChallenge:(ONGPinChallenge *)challenge 
                    forRequest:(ONGMobileAuthRequest *)request 
{
    // Code to display the PIN view here..

    // Once the user has entered the PIN call the delegate
    [challenge.sender respondWithPin:@"pin" challenge:challenge];

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

Fingerprint

- (void)userClient:(ONGUserClient *)userClient 
        didReceiveFingerprintChallenge:(ONGFingerprintChallenge *)challenge 
                            forRequest:(ONGMobileAuthRequest *)request
{
    // Code to display the mobile authentication view here..

    // Continue Mobile Authentication using Fingerprint with default prompt
    [challenge.sender respondWithDefaultPromptForChallenge:challenge];

    // Or use custom prompt
    [challenge.sender respondWithPrompt:@"Confirm money transfer" challenge:challenge];

    // Fallback to pin if needed
    [challenge.sender respondWithPinFallbackForChallenge:challenge];

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

Depending on your needs the challenge may be responded in a various ways: continue with default prompt, continue with custom prompt, fallback to pin or even cancel. After you have responded to the challenge, the SDK presents the TouchID authentication with the supplied (or default) prompt. Since this method is optional, the SDK will automatically fallback to PIN authentication if this method is not implemented.

Important: in order to receive fingerprint challenges you have to register the fingerprint authenticator first by following the Fingerprint Authenticator topic guide.

FIDO

- (void)userClient:(ONGUserClient *)userClient 
        didReceiveFIDOChallenge:(ONGFIDOChallenge *)challenge 
                     forRequest:(ONGMobileAuthRequest *)request
{
    // Code to display the mobile authentication view here..

    // Continue Mobile Authentication using FIDO authenticator
    [challenge.sender respondWithFIDOForChallenge:challenge];

    // Fallback to pin if needed
    [challenge.sender respondWithPinFallbackForChallenge:challenge];

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

You can respond to a FIDO challenge in three different ways. Responding with FIDO will present the FIDO view which will handle the authentication process. You can also provide the possibility to a user to authenticate with PIN instead of FIDO if needed. Cancelling the challenge will deny the mobile authentication request. The SDK will automatically fallback to PIN authentication in case the FIDO authenticator detects abuse due to too many failed authentication attempts.

Important: in order to receive FIDO challenges you has to register the FIDO authenticator first by following the FIDO Authenticator topic guide.

Completion

Once the mobile authentication request has been handled there are two callbacks on the ONGMobileAuthRequestDelegate that might be called: userClient:didHandleMobileAuthenticationRequest: and userClient:didFailToHandleMobileAuthenticationRequest:error: for success and failure correspondingly. Both methods are optionals.

For the success callback you may want to refresh your App's data or hide the view:

- (void)userClient:(ONGUserClient *)userClient 
        didHandleMobileAuthenticationRequest:(ONGMobileAuthRequest *)request
{
    // Hide the view, update application data, etc
}

For the failure callback, the situation is a bit more complex. It is strongly recommended to implement error handling. The SDK may deliver important errors such as user's (server-side) deregistration which requires special handling such as user logout, unwinding the UI to the login page, etc. However, it also may deliver errors that can be ignored such as the cancellation error which happens, when you cancel the challenge by calling the -[id<ONGFingerprintChallengeSender> cancelChallenge:] or -[id<ONGFingerprintChallengeSender> cancelChallenge:] methods:

- (void)userClient:(ONGUserClient *)userClient 
        didFailToHandleMobileAuthenticationRequest:(ONGMobileAuthRequest *)request 
                                             error:(NSError *)error
{
    switch (error.code) {
        case ONGGenericErrorDeviceDeregistered:
            // The device registration was removed from the Token Server. All locally stored data 
            // is removed from the device and the user needs to register again.
            break;
        case ONGGenericErrorUserDeregistered:
            // The user account is deregistered from the device. The user supplied the wrong PIN 
            // for too many times. All local data associated with the user profile has been removed.
            break;
        case ONGGenericErrorActionCancelled:
            // Requested action was cancelled.
            break;
        case ONGGenericErrorNetworkConnectivityFailure:
        case ONGGenericErrorServerNotReachable:
            // Networking issues.
            break;
        case ONGMobileAuthRequestErrorNotFound:
            // Mobile request was not found on the TS. We can either notify user or ignore it.
            break;
        case ONGMobileAuthRequestErrorNotHandleable:
            // Mobile request cannot be handled by the Onegini SDK.
            break;
        case ONGMobileAuthRequestErrorUserDisenrolled:
            // User that he was disenrolled for security reasons.
            break;
        case ONGMobileAuthRequestErrorNotEnrolled:
            // The user is not enrolled for mobile authentication.
            break;
        default:
            // Other errors
            break;
    }
}