Integrate mobile push authenticator

This topic enables the iOS mobile app to integrate a mobile push authenticator using the SDK

The CyberArk Identity iOS SDK provides highly secure and trusted multi-factor authentication (MFA) to your web app using the mobile push authenticator. Use the SDK to integrate the mobile push authenticator into the iOS mobile app, leverage the CyberArk Identity’s mobile push authentication mechanism, and deliver push notifications to a user’s pre-registered device using APNS (Apple Push Notification Service). Users can immediately allow or deny access to web applications using push notifications.

📘

Prerequisites

  1. An access token should be generated for the user and used to send the API calls for device enrollment. The access token can be generated using the OIDC authorization code with PKCE grant.

  2. The mobile device must be enrolled to CyberArk Identity to leverage the QR code authenticator. The Android SDK provides the capability to enroll the device to CyberArk Identity.

  3. Setup your custom FCM server on the CyberArk Identity

How it works?

11661166

Configure APNS Certificates

To leverage the push notification functionality, you need to set the APNS certificate at the tenant level. The following APIs must be invoked to set the APNS and delete the APNS certificates.
You can also follow the tutorial to generate the APNS certificate.

Tenant Configuration:

  • ClientAppKey: Mobile.IosCustomApp.ClientAppKey
  • APNSCert: Base64 string representation of the APNS certificate of p12 format
  • APNSPass: Password associated with the APNS Certificate
  • APNSTopic: The topic or client bundled related to the client application with which the push notification needs to be sent.

Set the APNS certificate

API: {tenantUrl}/Mobile/SetApnsCertForClientApp

This API sets the APNS Developer certificate so you can send push notifications to a mobile device. The storage of the APNSCert and other details happens at a Tenant level. The APNSCert details related to ClientKey are used to send the push notification. Earlier ClientAppKeys are ignored when sending the push notification.

📘

You need to have APNSCertificate management rights to use this API.

APIDescriptionTenant Configuration
ClientAppKeyThe client application key is a unique identifier for the client application that needs to be registered for APNS notifications. By default, this is the latest certificate.Mobile.IosCustomApp.ClientAppKey
APNSCertBase64 string representation of the APNS certificate of p12 format.{ClientAppKeyValue}_APNSCert
APNSPassThe password associated with the APNS certificate.{ClientAppKeyValue}_APNSPass
APNSTopicThe topic or client packageId related to client application with which the push notification needs to be sent.{ClientAppKeyValue}_APNSTopic
{
    "ClientAppKey":"bundleidentifier",
    "APNSCert":"hlsdfjflsdkjf",
    "APNSPass":"password”
    "APNSTopic":"bundleidentifier"
}

Delete the APNS certificate

API: {tenantUrl}/Mobile/DeleteApnsCertForClientApp

This API deletes the APNS Developer certificate. All the configuration settings as part of the SetApnCertForClientApp API are deleted as of a result.

📘

You need to have APNSCertificate management rights (Device Management Rights) to use this API.

ClientAppKey
The client key is a unique identifier for the client application and needs to be deleted in order to remove APNS notifications.

Integrate the mobile push authenticator into your app

Follow the below steps to integrate the mobile push authenticator into an iOS app:

Step 1: Enable remote notifications

  1. Click the project to navigate to your project settings.
  2. Select the Capability tab and find Background Modes.
  3. Double-click to add Background Modes to Signing & Capabilities.
  4. From Background Modes, select the Remote Notifications option.
420420

Step 2: Configure Apple Push Notification services (APNs)

private let categoryIdentifier = "MfaNotificationCategoryId"
private let kMfaNotificationApproveActionID = "MfaNotificationApproveActionId"
private let kMfaNotificationDenyActionID = "MfaNotificationDenyActionId"

        let application = UIApplication.shared
        UNUserNotificationCenter.current().requestAuthorization(options: [
            .badge, .sound, .alert
        ]) { granted, _ in
            guard granted else { return }
            self.registerCustomActions()
        }
        application.registerForRemoteNotifications()

        private func registerCustomActions() {

        let accept = UNNotificationAction(

           identifier: kMfaNotificationApproveActionID,

           title: "Approve",options: UNNotificationActionOptions(rawValue: 0))

        let reject = UNNotificationAction(

            identifier: kMfaNotificationDenyActionID,

            title: "Deny",options: UNNotificationActionOptions(rawValue: 0))

        let category = UNNotificationCategory(

            identifier: categoryIdentifier,

            actions: [accept, reject],

            intentIdentifiers: [],options: .customDismissAction)

        UNUserNotificationCenter.current()

            .setNotificationCategories([category])

    }

Step 3: Send the device token to your backend server

func application(

        _ application: UIApplication,

        didRegisterForRemoteNotificationsWithDeviceToken

        deviceToken: Data) {

            guard let config = plistValues(bundle: Bundle.main, plistFileName: "IdentityConfiguration") else { return }

            CyberArkAuthProvider.handlePushToken(token: deviceToken, baseURL: config.domain)


        }

Step 4: Implement support for handling incoming remote notifications

func userNotificationCenter(_ center: UNUserNotificationCenter,

           didReceive response: UNNotificationResponse,

           withCompletionHandler completionHandler:

                                @escaping () -> Void) {

        notificationcompletionHandler = completionHandler

        let identity = response.notification

            .request.content.categoryIdentifier

        let userInfo = response.notification.request.content.userInfo

        guard identity == categoryIdentifier, let action = NotificationActionIdentifier(rawValue: response.actionIdentifier) else {

                      Notification.Name.handleNotification.post(userInfo: userInfo)

                       completionHandler()

                  return

              }

        switch action {

        case .accept:

            self.performChallengeby(isAccepted: true, userInfo: userInfo, withCompletionHandler: nil)

        case .reject:

            self.performChallengeby(isAccepted: false, userInfo: userInfo, withCompletionHandler: nil)            

        }

    }

}

Step 5: Handle the push notification MFA challenge

Below is the snippet that Invokes the API based on the approve or deny action.

extension AppDelegate {
    func performChallengeby(isAccepted: Bool, userInfo: [AnyHashable : Any]? = nil, withCompletionHandler completionHandler:
                            CheckNotificationResult? ){
        let userInfo = userInfo?["payload"] as! [AnyHashable: Any]
        let info = userInfo["Options"] as! [AnyHashable: Any]
        let challenge =  info["ChallengeAnswer"]
        handleChallange(isAccepted: isAccepted, challenge: challenge as! String, withCompletionHandler: completionHandler)
    }
    func handleChallange(isAccepted: Bool, challenge: String, withCompletionHandler completionHandler:
                         CheckNotificationResult?) {
        guard let config = plistValues(bundle: Bundle.main, plistFileName: "IdentityConfiguration")
        else { return }
        mfaProvider.handleMFAChallenge(isAccepted: isAccepted, challenge: challenge, baseURL: config.domain, withCompletionHandler: completionHandler)
    }
    func addMFAObserver(){
        mfaProvider.didReceiveMFAApiResponse = { (result, message) in
            if let handler = self.notificationcompletionHandler {
                handler()
            }
        }
    }
}