Mobile authentication
The mobile platform offers a two-factor authentication mechanism in a user friendly and secure way. You can take advantage of mobile authentication to add a second factor of authentication for your product, which can be used to improve the security of selected actions like logging in to your website or accepting a payment transaction.
The mobile authentication feature is an extensive feature that has a number of different possibilities.
- With push notifications the user gets a push notification on their phone to alert them that a mobile authentication transaction is pending.
- With a one-time-password (OTP) the user provides an OTP in order to confirm a mobile authentication transaction. Since the OTP is long, it is likely that the OTP is transformed into a QR code and the user scans this code with their mobile device.
Before mobile authentication can be used, you must configure the IDAAS-core to support this functionality. When the IDAAS-core is configured, you can enroll and handle mobile authentication requests using the iOS SDK.
Enrollment
During the enrollment process, the iOS SDK generates and exchanges PGP keys with the IDAAS-core. It enables the basic mobile authentication feature which allows handling OTP requests.
- APP -> SDK: Enroll for mobile authentication with completion block.
- SDK -> IDAAS-core: A PGP key pair is generated, the public key is sent to the IDAAS-core.
- IDAAS-core --> SDK: The IDAAS-core will also generate a key pair and return its public key.
- SDK -> APP: The result of the enrollment flow is reported to the handler.
Mobile authentication enrollment is begun by calling the enrollForMobileAuth
method.
Example: initialize mobile authentication enrollment
SharedUserClient.instance.enrollMobileAuth { error in
}
[[ONGUserClient sharedInstance] enrollForMobileAuth:^(BOOL enrolled, NSError * _Nullable error) {}];
Successive invocations of enrollment for mobile authentication will re-enroll the device only if the mobile authentication override is enabled in the IDAAS-core configuration.
Enrolling for mobile authentication will NOT enroll automatically for the push.
Note
It is advised to perform the enrollMobileAuth
step as soon as possible in your application. It is quite resource intensive because it generates a private key and certificate.
Request handling
To handle mobile authentication requests, the user needs to be enrolled for mobile authentication. To verify if the user is already enrolled, you should use the isMobileAuthEnrolled(for:)
method on the UserClient
.
The iOS SDK is capable of handling two types of mobile authentication requests:
- Push
- OTP
Mobile authentication with push
Two-factor authentication can be implemented using APNs push notifications. You can use push notifications to allow users to confirm their transactions. Confirmation can be done using a simple Accept button, PIN, biometrics, or a custom authenticator. All transaction information is encrypted and no sensitive information is sent through APNs.
Before mobile authentication with push can be used, you must configure:
- Remote notification support in your app: You can configure it by following the Apple push notification documentation.
- IDAAS-core
When your app and the IDAAS-core are configured for push notifications, you should be able to enroll for mobile authentication with push and handle push requests using the iOS SDK.
Enrollment
Mobile push authentication enrollment requires regular mobile authentication enrollment to be done first. Only after it is completed, you can enroll for push authentication.
Enrollment for mobile authentication with push can be described as follows:
- APP -> APNS: Register for remote notifications.
- APNS -> APP: The device token is returned.
- APP -> SDK: Enroll for push by providing the device token and completion block.
- SDK -> IDAAS-core: Enroll push mobile authentication with the device token.
- IDAAS-core -> SDK: Acknowledge the enrollment process is completed.
- SDK -> APP: The result of the enrollment flow is reported by completion block.
The first step is to obtain the deviceToken
from APNs. Refer to the Apple remote notification guide for more information about retrieving the token.
After you have the deviceToken
from APNs, you can enroll with the deviceToken
using the enrollPushMobileAuth(with:completion:)
method of the UserClient
instance:
userClient.enrollPushMobileAuth(with: deviceToken) { error in
guard let error = error else {
// proceed without error
}
// proceed with error
}
[[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.
Receiving requests
After the user is enrolled, they are able to receive push notifications. The iOS SDK represents them by the PendingMobileAuthRequest
class. Those requests do not contain any sensitive information, since those might be sent through unsecure channels like APNS. However, pending mobile authentication requests contain an identifier that is later used to fetch full mobile authentication request information, which is represented by the objects of a MobileAuthRequest
class.
From the PendingMobileAuthRequest
object, you can get the following information:
transactionId
is a unique identifier for each mobile authentication request.userProfile
is the user profile for which the mobile authentication request was sent.date
is the date when the mobile authentication request was sent.timeToLive
is the time-to-live for which the mobile authentication request was sent.message
is the message specified by the portal when initiating the mobile authentication request.userInfo
is the user information received from the APNS.
The iOS SDK supports two ways of obtaining pending mobile authentication requests: APNS and the IDAAS-core.
APNS
The process of receiving a push from the APNS can be described as follows. In this flow, you call the initiator of the mobile authentication request portal:
- Portal -> IDAAS-core: Initialize mobile authentication.
- IDAAS-core -> APNS: Send the push notification.
- APNS -> IDAAS-core: Push notification delivery report.
- IDAAS-core -> Portal: Identifier of the initialized mobile authentication transaction.
- APNS -> APP: Deliver the push notification to the APP.
- APP -> SDK: Parse the push notification received from the APNS.
When the application receives a push notification from APNS, it should be able to differentiate 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 the mobile authentication provided by the iOS SDK.
A push notification received from APNS is represented by a Dictionary
object, which you can obtain from the UNNotificationResponse
object.
func userNotificationCenter(_: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
handlePushMobileAuthenticationRequest(userInfo: response.notification.request.content.userInfo)
completionHandler()
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler
{
NSDictionary *pushNotificationInfo = response.notification.request.content.userInfo
...
}
Before handling the push request, you must verify that the request can be handled by the iOS SDK. You can verify the request by calling the pendingMobileAuthRequest(from:)
method. This method will try to parse the Dictionary
to PendingMobileAuthRequest
. If a push notification is intended for the iOS SDK, the method will return a PendingMobileAuthRequest
object with a transactionId
and userProfile
. Otherwise, it will return nil.
Example: parse a push notification received from APNS
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler
{
NSDictionary *pushNotificationInfo = response.notification.request.content.userInfo;
ONGPendingMobileAuthRequest *pendingMobileAuthRequest = [[ONGUserClient sharedInstance] pendingMobileAuthRequestFromUserInfo:pushNotificationInfo]];
...
completionHandler();
}
IDAAS-core
When the device did not receive sent push notifications, you can use this feature to fetch a list containing the pending mobile authentication requests. In this flow, you call the initiator of the mobile authentication request portal:
- Portal -> IDAAS-core: Initialize mobile authentication.
- IDAAS-core -> Portal: Identifier of the initialized mobile authentication transaction.
- APP -> SDK -> Token: Fetch all pending mobile authentication requests
Example: fetch pending mobile authentication requests
If the user does not have any pending mobile authentication requests, the method will return an empty list. The results of this request are sorted by the time sent (descending).
SharedUserClient.instance.pendingPushMobileAuthRequests { requests, error in
if error == nil {
// Handle list containing pending mobile authentication requests
} else {
switch error.code {
case ONGGenericError.deviceDeregistered.rawValue:
// The device registration was removed. All locally stored data
// is removed from the device and the user needs to register again.
case ONGGenericError.configurationInvalid.rawValue:
// The provided client credentials are not valid or the client is not a dynamic client.
default:
// Other errors
}
}
[[ONGUserClient sharedInstance] pendingPushMobileAuthRequests:^(NSArray<ONGPendingMobileAuthRequest *> * _Nullable pendingTransactions, NSError * _Nullable error) {
if (error == nil) {
// Handle list containing pending mobile authentication requests
} else {
switch (error.code) {
case ONGGenericErrorDeviceDeregistered:
// The device registration was removed. All locally stored data
// is removed from the device and the user needs to register again.
break;
case ONGGenericErrorConfigurationInvalid:
// The provided client credentials are not valid or the client is not a dynamic client.
break;
default:
// Other errors
break;
}
}
}];
Request handling
After push requests are received and parsed by PendingMobileAuthRequest
, they are handled by calling the handlePendingPushMobileAuthRequest:delegate:
on the UserClient
shared instance. Since notifications may require authentication, the iOS SDK needs a delegate (MobileAuthRequestDelegate
) to authenticate.
The entire process of handling pending requests can be described as follows.
- APP -> SDK: Handle the pending mobile authentication request.
- SDK -> IDAAS-core: Fetch the PGP-encrypted message from the server.
- IDAAS-core -> SDK: Base64 encoded PGP encrypted authentication data
- SDK -> APP: The push message is decrypted and the SDK triggers a delegate so the app can show a dialog box to the user.
- APP -> SDK: The application responds with the authentication result.
- SDK -> IDAAS-core: The encrypted authentication result is sent to the IDAAS-core.
- IDAAS-core -> SDK: If the used push type requires feedback on the result, for example PIN usage, the result is communicated back to the SDK, which will optionally perform a retry.
- IDAAS-core -> Portal: A callback is sent to inform the portal about the mobile authentication result.
The application has the following responsibilities during the request handling:
-
Responding to authentication challenges
-
Displaying a dialog box to the user when an authentication challenge is received
-
Sending the users' response back to the SDK
-
Handling the completion of the mobile authentication request
Responding to a challenge
After you have passed the mobile authentication request to the iOS SDK, the iOS SDK will request the app to let the user either confirm or deny the request. The iOS SDK will delegate control back to the provided MobileAuthRequestDelegate
implementation. Hence, the application must contain a class that implements the methods specified below.
Mobile authentication requests are represented by the MobileAuthRequest
class. Objects of this class are passed to every MobileAuthRequestDelegate
method. From those objects, you can get the following information about currently processed mobile authentication requests:
userProfile
is an instance of theUserProfile
for which a request has been received.type
is a string representing the type of the notification, which is configured in the IDAAS-core 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
is a message specified by the portal when initiating the mobile authentication request. This field represents thesecure_message
parameter sent while initiating the mobile authentication request. This message length is not limited.userInfo
is the user information received from the APNS. 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
is a unique identifier for each mobile authentication request.
When a challenge is received, you should display a user interface containing selected information from ONGMobileAuthRequest
, and an interface that allows the user to respond to the received challenge, such as a PIN screen when a PIN challenge was received. The user's response should be sent back to the iOS SDK via the challenge sender object or through the confirmation block in case of a confirmation challenge.
Depending on your needs, the challenge may be responded to in various ways: continue with custom prompt, fallback to PIN, or even cancel. After you have responded to the challenge, the iOS SDK presents the TouchID
authentication with the supplied (or default) prompt. Since this method is optional, the iOS SDK will automatically fall back to PIN authentication if this method is not implemented.
Example: confirmation
func userClient(_ userClient: UserClient,
didReceiveConfirmationChallenge confirmation: @escaping (Bool) -> Void,
for request: MobileAuthRequest) {
// 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(true);
}
- (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);
}
Example: PIN
func userClient(_ userClient: UserClient,
didReceivePinChallenge challenge: PinChallenge,
for request: MobileAuthRequest) {
// Code to display the PIN view here..
// Once the user has entered the PIN call the delegate
challenge.sender.respond(with: "pin", to: challenge)
// Or cancel challenge
challenge.sender.cancel(challenge)
}
- (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];
}
Example: biometrics
func userClient(_ userClient: UserClient,
didReceiveBiometricChallenge challenge: BiometricChallenge,
for request: MobileAuthRequest) {
// Code to display the mobile authentication view here..
// Continue Mobile Authentication using Fingerprint with custom prompt
challenge.sender.respond(with: "Confirm money transfer", to: challenge)
// Fallback to pin if needed
challenge.sender.respondWithPinFallback(to: challenge)
// Or cancel challenge
challenge.sender.cancel(challenge)
}
- (void)userClient:(ONGUserClient *)userClient
didReceiveBiometricChallenge:(ONGBiometricChallenge *)challenge
forRequest:(ONGMobileAuthRequest *)request
{
// Code to display the mobile authentication view here..
// Continue Mobile Authentication using Fingerprint with 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];
}
Example: custom
When you receive a custom authenticator challenge, you can respond to it with an optional data, PIN fallback, or cancellation. Responding with data will continue the authentication process, responding with the PIN will send a PIN challenge instead, and cancellation will deny the mobile authentication request. Authentication with a custom authenticator might fail with fallback to PIN. In this case, the CustomInfo
object is passed under the CustomAuthInfoKey
in the userInfo
of the error object within the PinChallenge
.
func userClient(_ userClient: UserClient,
didReceiveCustomAuthFinishAuthenticationChallenge challenge: CustomAuthFinishAuthenticationChallenge,
for request: MobileAuthRequest) {
// Code to display the mobile authentication view here..
// Continue Mobile Authentication using a custom authenticator
challenge.sender.respond(with: customAuthData, to: challenge)
// Fallback to pin if needed
challenge.sender.respondWithPinFallback(to: challenge)
// Or cancel challenge
challenge.sender.cancel(challenge)
}
- (void)userClient:(ONGUserClient *)userClient
didReceiveCustomAuthFinishAuthenticationChallenge:(ONGCustomAuthFinishAuthenticationChallenge *)challenge
forRequest:(ONGMobileAuthRequest *)request
{
// Code to display the mobile authentication view here..
// Continue Mobile Authentication using a custom authenticator
[challenge.sender respondWithData:customAuthData forChallenge:challenge];
// Fallback to pin if needed
[challenge.sender respondWithPinFallbackForChallenge:challenge];
// Or cancel challenge
[challenge.sender cancelChallenge:challenge];
}
Completion
After the mobile authentication request has been handled, there are two callbacks on the MobileAuthRequestDelegate
that might be called: userClient(_:request:authenticator:info:)
for success and userClient(_:didFailToHandleMobileAuthenticationRequest:authenticator:error:)
for failure. Both methods are optional.
For the success callback you can refresh your app's data or hide the view:
Example: success callback
func userClient(_ userClient: UserClient,
didHandle request: MobileAuthRequest,
authenticator: Authenticator?,
info customAuthenticatorInfo: CustomInfo?) {
// Hide the view, update application data, etc
}
- (void)userClient:(ONGUserClient *)userClient
didHandleMobileAuthenticationRequest:(ONGMobileAuthRequest *)request
authenticator:(ONGAuthenticator *_Nullable)authenticator
info:(ONGCustomInfo *_Nullable)customAuthInfo
{
// 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 iOS SDK may deliver important errors such as a user's (server-side) deregistration, which requires special handling such as user logout, unwinding the UI to the login page, and so on. 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 BiometricChallengeSender.cancel
methods. In case of failure during authentication with a custom authenticator, the returned error might include the CustomInfo
object under the CustomAuthInfoKey
in the userInfo
.
func userClient(_ userClient: UserClient,
didFailToHandle request: MobileAuthRequest,
authenticator: Authenticator?,
error: Error) {
switch error.code {
case ONGGenericError.deviceDeregistered.rawValue:
// The device registration was removed. All locally stored data
// is removed from the device and the user needs to register again.
case ONGGenericError.userDeregistered.rawValue:
// 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.
case ONGGenericError.actionCancelled.rawValue:
// Requested action was cancelled.
case ONGGenericError.networkConnectivityFailure.rawValue:
case ONGGenericError.serverNotReachable.rawValue:
// Networking issues.
case ONGMobileAuthRequestError.notFound.rawValue:
// Mobile request was not found on the TS. We can either notify user or ignore it.
case ONGMobileAuthRequestError.notHandleable.rawValue:
// Mobile request cannot be handled by the SDK.
case ONGMobileAuthRequestError.userDisenrolled.rawValue:
// User that he was disenrolled for security reasons.
case ONGMobileAuthRequestError.notEnrolled.rawValue:
// The user is not enrolled for mobile authentication.
default:
// Other errors
}
}
- (void)userClient:(ONGUserClient *)userClient
didFailToHandleMobileAuthenticationRequest:(ONGMobileAuthRequest *)request
authenticator:(ONGAuthenticator *_Nullable)authenticator
error:(NSError *)error
{
switch (error.code) {
case ONGGenericErrorDeviceDeregistered:
// The device registration was removed. 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 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;
}
}
Mobile authentication with OTP
The IDAAS-core offers the ability for mobile authentication with a one-time password (OTP). Mobile authentication with OTP provides users an easy and secure way for two-factor authentication or single-factor authentication where no passwords are required. All of the communication stays between app, web application, and IDAAS-core.
An Example implementation could work like this: A web application fetches the OTP from the IDAAS-core and displays it on the login page in the form of a QR code. The user opens your mobile application and scans the QR code with their camera and is automatically logged in to your website.
To use mobile authentication with OTP, you have to set it up in the IDAAS-core.
Enrollment
It's only required to enroll for mobile authentication to use OTP. To verify if the user is already enrolled for mobile authentication, you can use the isMobileAuthEnrolled(for:)
method on the UserClient
.
Request handling
The entire push mobile authentication process from can be described as follows. In this flow you call the initiator of the mobile authentication request portal:
- Portal -> IDAAS-core: Initialize a mobile authentication.
- IDAAS-core -> Portal: Identifier of the initialized mobile authentication transaction and base64-encoded OTP (which includes the transactionId and OTPcode)
- Portal -> app: Request containing the transactionId and OTP code
- App -> SDK: Delegate handling of the request to the SDK.
- SDK -> IDAAS-core: Fetch PGP-encrypted message from the server.
- IDAAS-core -> SDK: Base64-encoded, PGP-encrypted authentication data.
- SDK -> APP: The mobile authentication message is decrypted and the SDK triggers a delegate, so the app can show a dialog to the user.
- APP -> SDK: The application responds with the authentication result.
- SDK -> IDAAS-core: The authentication result is sent encrypted to the IDAAS-core.
- IDAAS-core -> Portal: A callback is sent to inform the portal about the mobile authentication result.
The application has the following responsibilities:
- Passing the mobile authentication request received from the initiator to the SDK
-
Responding to the confirmation challenge
-
(optionally) Displaying a dialog to the user when their confirmation is required
-
Sending the user response back to the SDK
-
Handling completion
Passing the OTP request to the iOS SDK
Before handling the request, it is recommended to verify if the request can be handled by the iOS SDK. It can be done by calling the canHandleOTPMobileAuthRequest(otp:)
method. If the request can be handled, this method returns Bool
.
To trigger mobile authentication with an OTP, a user has to be authenticated (logged in to your app). When that condition is satisfied and the user is enrolled for mobile authentication, you can call the handleOTPMobileAuthRequest(otp:delegate:)
method on the UserClient
instance. The request must be the OTP string(encoded in base64) retrieved from the IDAAS-core. This string contains an OTP code and the transaction_id
in JSON format encoded with UTF8.
If no user is authenticated, the iOS SDK will trigger the didFailToHandleMobileAuthRequest
selector on the delegate containing a user not authenticated error.
If all of the requirements are met, the iOS SDK will start the mobile authentication request processing and will inform your MobileAuthRequestDelegate
about the received confirmation challenge.
if SharedUserClient.instance.canHandleOTPMobileAuthRequest(otpRequest) {
SharedUserClient.instance.handleOTPMobileAuthRequest(otpRequest, for: delegate)
}
if ([[ONGUserClient sharedInstance] canHandleOTPMobileAuthRequest:otpRequest]) {
[[ONGUserClient sharedInstance] handleOTPMobileAuthRequest:otpRequest delegate:delegate];
}
Responding to a challenge
After you have passed the mobile authentication request to the iOS SDK, the iOS SDK will request the app to let the user either confirm or deny the request. The iOS SDK will delegate control back to the provided MobileAuthRequestDelegate
implementation. Hence, the application must contain a class that implements the methods specified below.
Mobile authentication requests are represented by the MobileAuthRequest
class. Objects of this class are passed to every MobileAuthRequestDelegate
method. From those objects, you can get the following information about the current mobile authentication request:
userProfile
is the instance of the UserProfile for which the request has been received.type
is a string representing the type of notification that is configured in the IDAAS-core admin panel. The type can be used to distinguish between different business functionality. For example, mobile authentication can be used for logging in or transaction approval.message
is the message specified by the initiator when initiating the mobile authentication request. This field represents the secure_message parameter sent while initiating the mobile authentication request. The message length is not limited.transactionId
is a unique identifier for each mobile authentication request.
When a confirmation challenge is received, you can display a user interface containing information from the MobileAuthRequest
and options to confirm or deny the request. After a response from the user is received, you should send it back to the iOS SDK by calling the confirmation block.
func userClient(_ userClient: UserClient,
didReceiveConfirmation confirmation: @escaping (Bool) -> Void,
for request: MobileAuthRequest) {
// 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(true);
}
- (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);
}
Completion
After the mobile authentication request has been handled, there are two callbacks on the MobileAuthRequestDelegate
that might be called: userClient(_:didHandleRequest:authenticator:info)
and userClient(_:didFailToHandle:authenticator:error:)
for success and failure correspondingly. Both methods are optional.
For the success callback, you may want to refresh your application data or hide the view that was used to display the mobile authentication request confirmation screen:
func userClient(_ userClient: UserClient,
didHandleRequest request: MobileAuthRequest,
authenticator: Authenticator?,
info customAuthenticatorInfo: CustomInfo?) {
// Hide the view, update application data, etc
}
- (void)userClient:(ONGUserClient *)userClient
didHandleMobileAuthenticationRequest:(ONGMobileAuthRequest *)request
authenticator:(ONGAuthenticator *_Nullable)authenticator
info:(ONGCustomInfo *_Nullable)customAuthenticatorInfo
{
// 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 (server-side) deregistration, which requires special handling such as user logout, unwinding the UI to the login page, and so on.
func userClient(_ userClient: UserClient,
didFailToHandle request: MobileAuthRequest,
authenticator: Authenticator?,
error: Error) {
switch error.code {
case ONGGenericError.deviceDeregistered.rawValue:
// The device registration was removed. All locally stored data
// is removed from the device and the user needs to register again.
case ONGGenericError.userDeregistered.rawValue:
// 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.
case ONGGenericError.networkConnectivityFailure.rawValue:
case ONGGenericError.serverNotReachable.rawValue:
// Networking issues.
case ONGMobileAuthRequestError.notFound.rawValue:
// Mobile request was not found on the TS. We can either notify user or ignore it.
case ONGMobileAuthRequestError.notHandleable.rawValue:
// Mobile request cannot be handled by the SDK.
case ONGMobileAuthRequestError.userDisenrolled.rawValue:
// User is disenrolled for mobile authentication for security reasons. You have to enroll the user again before he can perform mobile
// authentication again
case ONGMobileAuthRequestError.notEnrolled.rawValue:
// The user is not enrolled for mobile authentication.
case ONGMobileAuthRequestError.userNotAuthenticated.rawValue:
// No user is currently authenticated, possibly due to the fact that the access token
// has expired. A user must be authenticated in order to enroll for mobile
// authentication.
default:
// Other errors
}
}
- (void)userClient:(ONGUserClient *)userClient
didFailToHandleMobileAuthenticationRequest:(ONGMobileAuthRequest *)request
authenticator:(ONGAuthenticator *_Nullable)authenticator
error:(NSError *)error
{
switch (error.code) {
case ONGGenericErrorDeviceDeregistered:
// The device registration was removed. 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 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 SDK.
break;
case ONGMobileAuthRequestErrorUserDisenrolled:
// User is disenrolled for mobile authentication for security reasons. You have to enroll the user again before he can perform mobile
// authentication again
break;
case ONGMobileAuthRequestErrorNotEnrolled:
// The user is not enrolled for mobile authentication.
break;
case ONGMobileAuthRequestErrorUserNotAuthenticated:
// No user is currently authenticated, possibly due to the fact that the access token
// has expired. A user must be authenticated in order to enroll for mobile
// authentication.
break;
default:
// Other errors
break;
}
}