Overview

The PingOne Mobile SDK provides the ability to integrate PingOne MFA functionality into your mobile applications.

The PingOne Mobile SDK API for iOS is declared in the PingOne.h header file included in the SDK package. This header file (replicated below) includes descriptions for all functions, parameters and error codes.

The PingOne Mobile SDK package is available for download at https://github.com/pingidentity/pingone-mobile-sdk-ios. Further details for setup and integrating PingOne Mobile SDK into your mobile apps are available in the README file.

See Edit an application in the admin guide for the server-side configuration steps.

PingOne Mobile SDK sample app

The PingOne Mobile SDK bundle provides a sample app that includes all the basic flows in order to help you get started.

The sample app package for iOS is available for download at https://github.com/pingidentity/pingone-mobile-sdk-ios. Further details are available in the README file.

Authenticator sample app

The Authenticator sample app is a mobile app that has the sole function of performing strong authentication. It provides a simple example for developers and solution architects, to enable easy and rapid deployment of an authenticator app with minimal effort.

For scenarios which solely require creation of a mobile authenticator rather than a full native mobile app, the Authenticator sample app offers a passwordless and secured solution, that only requires compilation of the sample with customer’s branding and credentials, and uploading it to the app store.

The Authenticator sample app package for iOS is available for download at https://github.com/pingidentity/pingone-authenticator-sample-app-ios. Further details are available in the README file.

PingOne Mobile SDK API - iOS (PingOne.h)

//
//  PingOne.h
//  PingOne
//
//  Created by Ping Identity on 3/12/19.
//  Copyright © 2019 Ping Identity. All rights reserved.
//

//! Project version number for PingOne.
public var PingOneVersionNumber: Double

/// AuthenticatorModel public class contains the acceptable authorization methods and its status
@objc public class AuthenticatorModel : NSObject {

    @objc public enum AuthenticatorType : NSInteger {

        /// Unknown type of authenticator
        case unknown = -1

        /// Authenticator with push type
        case push = 0

        /// Authenticator with one time passcode type
        case oneTimePasscode
    }

    @objc public enum AuthenticatorStatus : NSInteger {

        /// Unknown authenticator status
        case unknown = -1

        /// Authenticator received completed status
        case completed = 0

        /// Authenticator received failed status
        case failed
    }

    /// The Authenticator type
    @objc public let type: PingOne.AuthenticatorModel.AuthenticatorType

    /// The Authenticator status
    @objc public let status: PingOne.AuthenticatorModel.AuthenticatorStatus

    /// Error message in case of authorization method failure
    @objc public let errorCode: String?

    /// Error code in case of authorization method failure
    @objc public let errorMessage: String?
}

@objc public enum ErrorCode : NSInteger {

    /// Internal Error.
    case internalError = 10000

    /// Device token was missing and is required to complete this action.
    case deviceTokenIsMissing = 10001

    /// Remote notification isn't from PingOne.
    case unrecognizedRemoteNotification = 10002

    /// There was a server error.
    case serverError = 10003

    /// There was a problem with the network.
    case noConnectivity = 10004

    /// There was a problem with the pairing key.
    case pairingKey = 10005

    /// There was a problem with the bundle id.
    case bundleId = 10006

    /// Device may be paired in one regional data center only, and is already paired in another regional data center.
    case pairingKeyDataCenterMismatch = 10007

    /// Device is not paired.
    case deviceIsNotPaired = 10008

    /// Client confirmation delay responding to push notification, resulted in timeout.
    case pushConfirmationTimeout = 10009
    
    /// Client failed to verify due to invalid one time passcode sent to the server.
    case passcodeNotValid = 10010
}

/// A Notification Object represents an authentication request via remote notification. It can be approved or denied.
@objc public class NotificationObject : NSObject {

    /// Type that describes the purpose of the notification.
    @objc public enum NotificationType : NSInteger {

        /// Notification was not recognized.
        case none = -1

        /// Notification process has finished. No further action is required.
        case done

        /// Authentication notification that should be presented to the user and followed with the `approve` or `deny` method.
        case authentication
    }

    /// Describes the purpose of the notification.
    @objc public let notificationType: PingOne.NotificationObject.NotificationType

    /// The maximum time duration allowed from getting push till user response.
    @objc public let timeoutDuration: Int

    /// Extra parameters are passed to the client with the push object
    @objc public let clientContext: String

    /// Approve authentication
    /// - Parameters:
    ///   - withAuthenticationMethod: The `String` is the authentication method that was used to authenticate the user on the authenticating device, for example, fpt (fingerprint), face (facial recognition) etc. Refer to the "amr" (Authentication Method Reference) values in https://tools.ietf.org/html/rfc8176/#section-2 .
    ///   - completionHandler: Will return NSError in case of an error.
    @objc final public func approve(withAuthenticationMethod: String?, completionHandler: @escaping (NSError?) -> Void)

    /// Approve authentication
    ///
    /// - Parameter completionHandler: Will return NSError in case of an error.
    @available(*, deprecated, message: "please use approve(withAuthenticationMethod:completionHandler) instead")
    @objc final public func approve(completionHandler: @escaping (NSError?) -> Void)

    /// Deny authentication
    ///
    /// - Parameter completionHandler: Will return NSError in case of an error.
    @objc final public func deny(completionHandler: @escaping (NSError?) -> Void)
}

/// Public class that contains data of the One Time Passcode
@objc public class OneTimePasscodeInfo : NSObject {

    /// The generated passcode
    @objc public let passcode: String

    /// The time of expiration of the code.
    /// It is provided in double format which holds the future time in milliseconds divided by 1000 to represent seconds
    @objc public let validUntil: Double

    /// The time of creation of the passcode.
    @objc public let validFrom: Double

    /// The total life span of the passcode since it was created until it expired. The time unit is seconds.
    @objc public let timeWindowSize: Int
}

/// Public PairingInfo class contains data about pairing resolution
@objc public class PairingInfo : NSObject {

    /// List of authentication methods and their statuses
    @objc public var authenticatorsArray: [PingOne.AuthenticatorModel]
}

/// PairingObject represents a pairing request that can be approved or ignored.
@objc public class PairingObject : NSObject {

    /// Approve pairing
    ///
    /// - Parameter completionHandler: Will return NSError in case of an error.
    @available(*, deprecated, message: "please use approve(completion: @escaping (_ response: PairingInfo?, _ error: NSError?) -> Void)")
    @objc final public func approve(completionHandler: @escaping (NSError?) -> Void)

    /// Approve pairing
    ///
    /// - Parameter completionHandler: Will return PairingInfo object containing data about pairing resolution, and NSError in case of an error.
    @objc final public func approve(completion: @escaping (PingOne.PairingInfo?, NSError?) -> Void)
}

@objc public class PingOne : NSObject {

    /// Type that describes the APNS environment.
    @objc public enum APNSDeviceTokenType : NSInteger {

        /// Production environment.
        case production = 0

        /// Sandbox environment.
        case sandbox
    }

    /// Returns a payload string for any communication needed between the customer mobile app and the PingOne server.
    @objc public static func generateMobilePayload() throws -> String

    /// Pair device
    ///
    /// - Parameters:
    ///   - pairingKey:         The `String` value
    ///   - completionHandler:  Will return NSError in case of an error.
    @available(*, deprecated, message: "please use pair(_ pairingKey: String, completion: @escaping (_ response: PairingInfo? , NSError?) instead")
    @objc public static func pair(_ pairingKey: String, completionHandler: @escaping (NSError?) -> Void)

    /// Pair device
    ///
    /// - Parameters:
    ///   - pairingKey:         The `String` value
    ///   - completionHandler: Will return PairingInfo object containing data about pairing resolution, and NSError in case of an error. Documentation for pairing object error codes: https://apidocs.pingidentity.com/pingone/mobile-sdks/v1/api/#pingone-mobile-sdk-for-ios
    @objc public static func pair(_ pairingKey: String, completion: @escaping (PingOne.PairingInfo?, NSError?) -> Void)

    /// When using OpenID Connect, this is a mandatory post action method which should be executed after receiving an ID token from the PingOne server.
    ///
    /// - Parameters:
    ///   - idToken:         The `String` value
    ///   - completionHandler:  Will return NSError in case of an error. Will return PairingObject in case further action is required, such as approving the pairing.
    @objc public static func processIdToken(_ idToken: String, completionHandler: @escaping (PingOne.PairingObject?, NSError?) -> Void)

    ///  Set device remote notification token. Should be within application:didRegisterForRemoteNotificationsWithDeviceToken:
    ///
    /// - Parameters:
    ///   - deviceToken: The `Data` received within application:didRegisterForRemoteNotificationsWithDeviceToken:
    ///   - type: The `APNSDeviceTokenType` case.
    ///   - completionHandler: Will return NSError in case of an error.
    @objc public static func setDeviceToken(_ deviceToken: Data, type: PingOne.PingOne.APNSDeviceTokenType, completionHandler: @escaping (NSError?) -> Void)

    /// Get PingOne remote notification categories. Setting UNNotificationCategory more than once results in previous settings being overwritten.
    /// PingOne provides the needed categories. The developer may add categories.
    /// - Returns: The remote notification categories.
    @objc public static func getUNNotificationCategories() -> Set<UNNotificationCategory>

    /// Method that will notify the server not to send push messages to this device. Set to false to disable SDK push notifications.
    /// - Parameter allowed: a boolean that will tell the server to send push messages or not. Defaults to `true`.
    @objc (allowPushNotifications:) public static func pushNotification(allowed: Bool)

    /// Process the remote notification received from PingOne.
    ///
    /// - Parameters:
    ///   - userInfo: The `[AnyHashable : Any]` received in the AppDelegate application(_:didReceiveRemoteNotification:fetchCompletionHandler:) method.
    ///   - completionHandler: Will return NSError in case of an error. Will return NotificationObject in case further action is required, such as approving or denying an authentication.
    @objc public static func processRemoteNotification(_ userInfo: [AnyHashable : Any], completionHandler: @escaping (PingOne.NotificationObject?, NSError?) -> Void)

    ///  Tells PingOne server to perform the custom action specified by a remote notification. Should be within userNotificationCenter(_:didReceive:withCompletionHandler:) method.
    ///
    /// - Parameters:
    ///   - identifier: The `String` is the response.actionIdentifier received within userNotificationCenter(_:didReceive:withCompletionHandler:) method.
    ///   - userInfo: The `[AnyHashable : Any]` received within userNotificationCenter(_:didReceive:withCompletionHandler:) method.
    ///   - authenticationMethod: The `String` is the authentication method that was used to authenticate the user on the authenticating device, for example, fpt (fingerprint), face (facial recognition) etc. Refer to the "amr" (Authentication Method Reference) values in https://tools.ietf.org/html/rfc8176/#section-2 .
    ///   - completionHandler: Will return NSError in case of an error. NotificationObject will be returned in case an action is required.
    @objc public static func processRemoteNotificationAction(_ identifier: String, authenticationMethod: String?, forRemoteNotification userInfo: [AnyHashable : Any], completionHandler: @escaping (PingOne.NotificationObject?, NSError?) -> Void)

    ///  Returns all the paired users from the PingOne server.
    ///
    /// - Parameters:
    ///   - completionHandler:  Will return NSError in case of an error. Will return an array with information on all the paired users.
    @objc public static func getInfo(_ completionHandler: @escaping ([String : Any]?, NSError?) -> Void)

    /// Requests the SDK to provide one time passcode
    /// - Parameter completionHandler: Returns OneTimePasscodeInfo that contains data of the one time passcode if available, or error
    @objc public static func getOneTimePasscode(_ completionHandler: @escaping (PingOne.OneTimePasscodeInfo?, Error?) -> Void)

    ///  Tells PingOne server to perform the custom action specified by a remote notification. Should be within userNotificationCenter(_:didReceive:withCompletionHandler:) method.
    ///
    /// - Parameters:
    ///   - identifier: The `String` is the response.actionIdentifier received within userNotificationCenter(_:didReceive:withCompletionHandler:) method.
    ///   - userInfo: The `[AnyHashable : Any]` received within userNotificationCenter(_:didReceive:withCompletionHandler:) method.
    ///   - completionHandler: Will return NSError in case of an error. NotificationObject will be returned in case an action is required.
    @available(*, deprecated, message: "please use processRemoteNotificationAction(identifier:authenticationMethod:userInfo) instead")
    @objc public static func processRemoteNotificationAction(_ identifier: String, forRemoteNotification userInfo: [AnyHashable : Any], completionHandler: @escaping (PingOne.NotificationObject?, NSError?) -> Void)

    ///  **************** Warning  ****************
    /// Using this method will remove the trusted connection between the iOS SDK and the PingOne server
    /// server in a one sided manner, where only the iOS side will be removed.
    /// This method should not be used when logging out of your account.
    /// This method should only be used in development.
    @objc public static func removePingOneLocalData()

    /// The developer can decide if the device will stay paired after app reinstallation. This method should only be called once.
    ///
    /// - Parameter stayPaired: The `Bool` value. `true` to stay paired. Defaults to `false`.
    @objc public static func setDevicePairedAfterReinstall(_ stayPaired: Bool)

    /// Send logs to PingOne server.
    ///
    /// - Parameters:
    ///   - completionHandler:  Will return NSError in case of an error. A supportId will be returned when the logs have been sent successfully. The supportId can then be forwarded to the Ping Identity support team to review the logs.
    @objc public static func sendLogs(completionHandler: @escaping (String?, NSError?) -> Void)
}

Pairing object error codes

The pairing object always returns both a push authenticator status and an OTP status. If the status is FAILED, a Push authenticator error code and message or an OTP error code and message is returned with the status.

Push authenticator error codes

Error code Description
Any error string returned from APNS, for example Unregistered See more error codes and descriptions in Handling notification responses from APNs in the Apple developer portal.
MissingPushCredentials There are no push credentials on the PingOne server.
MissingDeviceToken There is no device token on the PingOne server.
PushDisabled The push was disabled via the mobile SDK API.

OTP error codes

Error code Description
OneTimePasscodeRetriesExceeded On device pairing, the OTP can be verified within 3 attempts.
On checkOTP, the OTP can be verified within 3 attempts in every 15 minutes.
InvalidOneTimePasscode The user entered an invalid OTP.
OneTimePasscodeExpired On device pairing, the OTP can be verified within 15 minutes.
On checkOTP, there are no limitations except for OneTimePasscodeRetriesExceeded.
UnSynchronizedClock The mobile clock not synchronized with the generated secret.

PingOne Mobile SDK API error codes

Error Status Description
10000 internalError Internal Error.
10001 deviceTokenIsMissing Device token was missing and is required to complete this action.
10002 unrecognizedRemoteNotification Remote notification isn’t from PingOne.
10003 serverError There was a server error.
10004 noConnectivity There was a problem with the network.
10005 pairingKey There was a problem with the pairing key.
10006 bundleId There was a problem with the bundle ID.
10007 pairingKeyDataCenterMismatch Device may be paired in one regional data center only, and is already paired in another regional data center.
10008 deviceIsNotPaired Device is not paired.
10009 pushConfirmationTimeout Client confirmation delay responding to push notification, resulted in timeout.
10010 passcodeNotValid Client failed to verify due to invalid one time passcode sent to the server.