PingOne Native SDKs

The PingOne Native SDKs are native iOS and Android client SDKs for PingOne services built to interact with the PingOne Platform API. Currently, native SDKs are available for these services:

PingOne MFA Native SDKs

The PingOne Native SDK provides the ability to integrate PingOne MFA functionality into your native applications. Topics include:

PingOne MFA Native SDK flows

Pairing - automatic enrollment

The automatic enrollment flow requires as little as one extra step from the user. The first time the user logs into an application which has an embedded PingOne Native SDK component, they are asked if they wish to trust that device. Once they approve, PingOne works behind the scenes, without requiring anything else from the user.

During user authentication, a native app communicates with the PingOne platform to generate a token. The token allows pairing the device to the user in the context of a customer application. The user is not required to type or scan anything.

  1. The user is identified on the customer native application, usually with a unique user identifier, for example, a username.
  2. The PingOne Native SDK returns a native payload to the customer native application. The payload is a small data package created by the PingOne Native SDK component, which is used as part of the device's authorization.
  3. The customer native application sends an authentication request to the PingOne Platform, including the native payload.
  4. The customer native application receives an ID token.
  5. The customer native application passes the ID token to the PingOne Native SDK.
  6. The PingOne Native SDK returns a pairing object to the customer native application, to pair or ignore the device.
  7. The customer native application prompts the user for the approve or deny action via a dialog. Based on the user's choice, the customer native application notifies PingOne Native SDK.
  8. The PingOne Native SDK completes the transaction accordingly, by communicating directly with PingOne Platform.

Implement automatic pairing of native app as MFA authenticator app

In order to enable automatic pairing of a native app as an MFA authenticator app, there are several tasks that must be coordinated between admin and developers.
In brief, you will do the following:

  • Create a native application with Authenticator configuration.
  • Configure a sign-on policy containing an MFA step that references an MFA policy where the native application is configured as an authenticator.
  • Assign the sign-on policy to the native app.
  • Write code in the application to support automatic app enrollment.

Follow the detailed steps below:

Supply the relevant details for the admin to do the following in the PingOne admin console:

Admin tasks
  1. Create a native app. See Add an application - Native.
  2. In Edit an application, on the Mobile tab:
    • Add the Package name (Android) and Bundle ID (iOS) of your native application.
    • Configure the push credentials per platform.
  3. Create a new MFA policy.
  4. In the MFA policy, use the Add Application option to select the name of your mobile app. In the settings for the app you added, select the Auto Enrollment option.
  5. Create a sign-on policy, and add an MFA step. See Add an authentication policy.
  6. In the MFA step, select the MFA policy that you configured. Also, if you want to allow automatic enrollment even if the user does not have any existing paired devices, set the "NONE OR INCOMPATIBLE METHODS" setting to Bypass.
  7. Return to the Applications page and edit your mobile application. On the Policies tab, choose the sign-on policy that you created. This is necessary so that the authenticator element of your application will be launched when users try to access the application.
Developer tasks

In your native application code (also described in the iOS and Android README.md files, see PingOne Native SDK for iOS or PingOne Native SDK for Android):

  1. Get the native payload from the SDK (PingOne.generateMobilePayload())
  2. Pass the received payload of the OIDC request to the authorization service, as the mobilePayload query parameter.
  3. Call processIdToken() with the token you received from PingOne platform.
  4. If automatic pairing is triggered (i.e. the user was not already paired with the device), processIdToken() will return a pairing object with approve() and deny() functions. Calling approve() will pair the user with the device.

Automatic device authorization

During automatic device authorization, a native app communicates with the PingOne platform to generate a token. The token allows authenticating the user device in the context of a customer application. The user is not aware of this, and is not required to type or scan anything.

  1. The customer native app requests a native payload from the PingOne Native SDK.
  2. The PingOne Native SDK returns a native payload to the customer native application.
  3. The customer native application sends an authentication request to the PingOne Platform, including the native payload.
  4. If the platform's authentication flow (sign-on policy) contains an MFA step, and extra verification is disabled, the platform verifies that the native device is paired and active, authenticates the native device, and the MFA step succeeds. The flow skips to step 9.
  5. The platform verifies that the native device is paired and active and sends a "silent" push notification to the native application via the APNS/GCM notification service.
  6. The native application passes the "silent" notification to the PingOne Native SDK.
  7. The PingOne Native SDK acknowledges receiving the "silent" push by sending a confirmation directly to the PingOne platform.
  8. The platform authenticates the native device, and the MFA step succeeds.
  9. The customer native application receives an ID token from the PingOne Platform.
  10. The customer native application passes the ID token to the PingOne Native SDK.
  11. The PingOne Native SDK returns null to the customer native application, indicating that authorization has completed and no further action needs to be taken.

Implement automatic device authorization

Admin tasks

The admin configuration that was implemented for automatic enrollment, is applied to automatic device authorization.

  1. Create a native app, or edit an existing app. See Add an application - Native.
  2. In Edit an application, on the Mobile tab:
    • Add the Package name (Android) and Bundle ID (iOS) of your native application.
    • Configure the push credentials per platform.
  3. Create a new MFA policy.
  4. In the MFA policy, use the Add Application option to select the name of your mobile app. In the settings for the app you added, enable Device Authorization. In the Extra Verification drop-down list, you can optionally select Permissive or Restrictive. For details on these two options, see Adding an MFA policy.
  5. Create a sign-on policy, and add an MFA step. See Add an authentication policy.
  6. In the MFA step, select the MFA policy that you configured.
  7. Return to the Applications page and edit your mobile application. On the Policies tab, choose the sign-on policy that you created. This is necessary so that the MFA policy you configured and included in the sign-on policy will be applied when users try to access the application.
Developer tasks

In your native application code (also described in the iOS and Android README.md files, see PingOne Native SDK for iOS or PingOne Native SDK for Android):

  1. Get the native payload from the SDK (PingOne.generateMobilePayload())
  2. Pass the received payload of the OIDC request to the authorization service, as the mobilePayload query parameter.
  3. Call processIdToken() with the token you received from PingOne platform.
  4. If device authorization is triggered (i.e. verification that the user's device is already paired and active), processIdToken() will return null, indicating that authorization has completed and no further action needs to be taken.

Authentication code flow

The authentication code flow enables users to sign on without any data entry, such as providing a username, password, or entering a one-time passcode. The user scans the code, and if successful, gains access to an application's services.

During an authentication code flow, a native app communicates with the PingOne platform to initiate authentication with an authentication code, which can be a QR code. The flow starts with a call to the Create Authentication Code endpoint. The Mobile SDK validates the code value and returns an AuthenticationObject to the mobile app.

  1. The customer mobile app requests an authentication code flow from the PingOne Mobile SDK.
  2. The Mobile SDK requests validation of the authentication code value from the PingOne platform.
  3. If the authentication code value is validated by the PingOne platform, the Mobile SDK creates an AuthenticationObject.
  4. The Mobile SDK returns the AuthenticationObject to the customer mobile app.
  5. If the status property value of the AuthenticationObject is CLAIMED, the flow continues. For all other status values, the flow ends.
  6. If the number of users is two or more, the flow presents the user with an option to choose a specific user from the list. If the AuthenticationObject specifies only one user, the flow continues without requiring this step.
  7. If the user approval setting has a value of REQUIRED, the mobile app prompts the user to approve or deny the current authentication session. If user approval is set to NOT_REQUIRED, the authentication flow skips this step.
  8. The customer mobile app makes a validation request to the Mobile SDK.
  9. The Mobile SDK claims authentication with the selected user and queries the PingOne server.
  10. The PingOne server returns an authentication status.

Implement an authentication code flow

Admin tasks

To configure direct triggering of the mobile application in an authentication code flow:

  1. Create a native app, or edit an existing app. See Add an application - Native.
  2. Use the Authenticator tab to allow mobile authentication for the app. If your organization uses the PingOne MFA SDK to allow authentication with a QR code in certain flows, the admin can optionally configure a universal link or schema app link to enable direct triggering of the mobile application when scanning a QR code with a QR scanner. See Editing an application - Native.
Developer tasks

In your native application code (also described in the iOS and Android README.md files, see PingOne Native SDK for iOS or PingOne Native SDK for Android):

  1. Pass the retrieved authentication code to the mobile SDK by calling PingOne.authenticate().
  2. Parse the retrieved AuthenticationObject. If the status field equals CLAIMED, proceed to the next step.
  3. If the number of users is more than one and/or the value of the field needsApproval equals REQUIRED, the AuthenticationObject will contain approve() and deny() options.
  4. Call the approve() method of the AuthenticationObject with the corresponding userId to complete the authentication.

PingOne MFA SDK for Android

Overview

The PingOne MFA Native SDK provides the ability to integrate PingOne MFA functionality into your native applications.

The PingOne MFA Native SDK API for Android is included in the SDK package. The functions, parameters and error codes are listed below.

The PingOne MFA Native SDK package is available for download at https://github.com/pingidentity/pingone-mobile-sdk-android. Further details for setup and integrating PingOne MFA Native SDK into your native apps are available in the README file in the Android folder of the downloadable package.

The PingOne SDK for Android supports the following software versions:

  • Android 8 (API 26) and greater

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

PingOne MFA Native SDK sample app

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

The sample app package for Android is available for download at https://github.com/pingidentity/pingone-mobile-sdk-android. Further details are available in the README file in the Android folder of the downloadable package.

Authenticator sample app

The Authenticator sample app is a native 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 native authenticator rather than a full native native 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 Android is available for download at https://github.com/pingidentity/pingone-authenticator-sample-app-android/. Further details are available in the README file.

Mobile device integrity check

PingOne has an integrated mobile device integrity check in its MFA flows, which allows mobile applications to deny access when a mobile device is suspected to be compromised.

Mobile device integrity check - admin UI configuration

Each application must be set up and configured in the organization's PingOne environment, either in the admin UI, or using the MFA devices API. The development team provides the admin with the application name and details.

The admin's configuration of device integrity detection is detailed in the PingOne admin guide. See Editing an application - Native.

Mobile device integrity check - Android implementation

PingOne uses Google's Play Integrity API to check the integrity of the mobile device. For details on the capabilities of the Play Integrity API, see the Play Integrity API documentation.

Mobile app developers are responsible for enabling and monitoring usage of the Play Integrity API.

The following steps are required:

  1. Create a Google Cloud project or use an existing one
    For details on working with Google Cloud projects, see Creating and managing projects. The PingOne mobile SDK component requires the number of your Google Cloud project.

  2. Enable the Google Play Integration API
    Go to APIs and Services and select Enable APIs and Services. Search for the Play Integrity API, select it, and then select Enable.

  3. Link your application to the Google Cloud project
    Applications distributed on Google Play must be linked to the Google Cloud project so that they can call the Play Integrity API. In the developer console of the Google Play Store, choose your application. Go to Setup > App integrity > Google Cloud Project, and link your application to the Google Cloud project where you've enabled the Play Integrity API.

  4. Configure how your responses are encrypted and decrypted (optional)
    For applications distributed on Google Play, you can choose between Google-managed response encryption (the default and recommended option) and self-managed response encryption. For both of these options, you'll need to provide the relevant keys in the PingOne console when you define the application. See Configure how your responses are encrypted and decrypted for more information on managing and downloading response encryption keys.

  5. Monitor Play Integrity API usage
    If your quota for Play Integrity API usage is reached, users could end up getting blocked. So it's important to monitor Play Integrity usage. For more information on usage tiers and requesting a higher quota, see API usage tiers.

  6. Request a higher quota if needed
    The form for requesting a move to a higher usage tier includes questions that are application-dependent. For the question How are you calling the Play Integrity API?, select the A third party I'm using in the app is calling the API option, and specify PingOne Mobile SDK Android.

  7. Estimate the number of queries per day to request a specific tier
    The quota request should take into account both your application's expected traffic and the mobile SDK component's caching and retry policy. If there was a successful response from the Play Integrity API that passed the integrity test, no additional Play Integration requests will be made until after the integrity check cache duration that you defined for the application.

PingOne MFA Native SDK API - Android

See the API documentation.

PingOne MFA SDK for iOS

Overview

The PingOne MFA Native SDK provides the ability to integrate PingOne MFA functionality into your native applications.

The PingOne MFA Native 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 MFA Native SDK package is available for download at https://github.com/pingidentity/pingone-mobile-sdk-ios. Further details for setup and integrating PingOne MFA Native SDK into your native apps are available in the README file.

The PingOne SDK for iOS supports the following software versions:

  • Xcode 14 and above
  • iOS 12.0 and above

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

PingOne MFA Native SDK sample app

The PingOne MFA Native 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 native 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 native authenticator rather than a full native native 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.

Mobile device integrity check

PingOne has an integrated mobile device integrity check in its MFA flows, that allows mobile applications to deny access when a mobile device is suspected to be compromised.

Mobile device integrity check - admin UI configuration

Each application must be set up and configured in the organization's PingOne environment, either in the admin UI, or using the MFA devices API. The development team provides the admin with the application name and details.

The admin's configuration of device integrity detection is detailed in the PingOne admin guide. See Editing an application - Native.

PingOne MFA Native SDK API - iOS

See the API documentation.

PingOne MFA SDK error codes

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.
Any error string returned from FCM, for example Unregistered See more error codes and descriptions in Error codes for FCM failure conditions in the Firebase 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 native 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 native clock not synchronized with the generated secret.

PingOne Neo Native SDKs

PingOne Neo is a decentralized identity solution that gives control of identity data back to users. PingOne Neo empowers businesses to give their users full control over how they securely store and share verified credentials without unnecessary friction.

PingOne Neo provides enterprises with identity verification capabilities and the capability to issue identity claims for users to store in their wallet app and verify user data. Embed personal identity using these SDKs into a service to issue digital cards to users and let them store verifiable, shareable data in their wallet app.

PingOne Neo has two components:

PingOne Verify Native SDKs

PingOne Verify Native SDKs collect information required for verifying a user’s identity and share the collected information with the PingOne Verify service. PingOne Verify Native SDKs are available in for two operating systems:

PingOne Verify SDK for iOS

PingOneVerify iOS SDK provides a secure interface for an iOS app to use the PingOne Verify service for validating a user’s identity. The SDK also parses the responses received from the service for different operations and forwards the same to the app via callbacks.

Running the Sample App

Prerequisites
  • Xcode 12 or greater
  • iOS 13 or greater
Set Up and Clone or Download

The sample app cannot run on a simulator and works only on a device, because the app requires the camera to capture a selfie and the related user ID documents.

  1. Ensure your Xcode is set up with a provisioning profile and a signing certificate to be able to install the app on a device. See the Apple Xcode document Run an app on a device for more information.

  2. Clone or download the PingOne Verify SDK for iOS sample code to your computer and open PingOneVerify.xcodeproj located in the PingOneVerify_iOS directory.

    You will find all other XCFramework dependencies required for PingOne Verify in the PingOneVerify_iOS/dependencies directory.

  3. To run the sample app, select the scheme PingOneVerify_iOS --> , and click Run.

Integrating PingOne Verify SDK with Your App

PingOneVerify iOS SDK provides a secure interface for an iOS app to use the PingOne Verify service for validating a user’s identity. The SDK also parses the responses received from the service for different operations and forwards the same to the app via callbacks.

Getting started

Add the dependencies needed for your application.

The PingOne Verify iOS SDK relies on XCFramework components. You’ll need to add these to Xcode for use by your application.

  1. Drag and drop the following components from the SDK folder to the section Frameworks, Libraries, and Embedded Content in Xcode:

    • PingOneVerify.xcframework

    • BlinkID.xcframework

    • VoiceSdk.xcframework

  2. Right click from your project folder and select Add Files to (your project name).

  3. Add import PingOneVerify to the top of the Swift file where the SDK is initialized

Initializing PingOneVerifyClient
  1. Import PingOneVerify_iOS in your desired ViewController (It must extend UIViewController)

    import PingOneVerify_iOS
    
  2. Extend DocumentSubmissionListener protocol and its functions

    class YourViewController: UIViewController, DocumentSubmissionListener {
    
        func onDocumentSubmitted(response: DocumentSubmissionResponse) {
            // Callback when document is successfully submitted
        }
    
        func onSubmissionComplete(status: DocumentSubmissionStatus) {
            // Callback when verification transaction is completed
        }
    
        func onSubmissionError(error: DocumentSubmissionError) {
        // Callback when there is an error during submission
        }
    
    }
    
  3. Instantiate a PingOneVerifyClient.Builder and set its listener and rootViewController (Required)

    PingOneVerifyClient.Builder()
        .setListener(self)
        .setRootViewController(self)
    
  4. Optionally, you can set an explicit qrString using the PingOneVerifyClient.Builder

    PingOneVerifyClient.Builder()
        .setListener(self)
        .setRootViewController(self)
        .setQrString(qrString: "https://api.pingone.com...")
    
  5. Optionally, you can set a Selfie Capture Settings with your preference using the PingOneVerifyClient.Builder.

    // Default is 45 seconds for captureTime and true for shouldCaptureAfterTimeout
    let selfieCaptureSettings = SelfieCaptureSettings(captureTime: 15, shouldCaptureAfterTimeout: false)
    PingOneVerifyClient.Builder()
        .setListener(self)
        .setRootViewController(self)
        .setDocumentCaptureSettings(documentCaptureSettings: [selfieCaptureSettings])
    
  6. Start Verification Process

    PingOneVerifyClient.Builder()
        .setListener(self)
        .setRootViewController(self)
        .startVerification { pingOneVerifyClient, clientBuilderError in
            if let pingOneVerifyClient = pingOneVerifyClient {
                // Handle pingOneVerifyClient
            } else if let clientBuilderError = clientBuilderError {
                // Handle builderError
            }
        }
    
DocumentSubmissionListener Callbacks
  1. onDocumentSubmitted(response: DocumentSubmissionResponse)

    func onDocumentSubmitted(response: DocumentSubmissionResponse) {
        print("The document status is \(response.documentStatus)")
        print("The document submission status is \(response.documentSubmissionStatus)")
            
        guard let documents = response.document else { return }
        for (key, value) in documents {
            print("\(key): \(value)")
        }
    }
    
  2. onSubmissionComplete(status: DocumentSubmissionStatus)

    • Called when all required documents have been submitted for a transaction.
    • DocumentSubmissionStatus will always be .completed
    func onSubmissionComplete(status: DocumentSubmissionStatus) {
        // present a basic alert to indicate completion
        let alertController = UIAlertController(title: "Document Submission Complete", message: "All documents have been successfully submitted", preferredStyle: .alert)
        alertController.addAction(UIAlertAction(title: "Okay", style: .default))
        DispatchQueue.main.async {
            self.present(alertController, animated: true)
        }
    }
    
  3. onSubmissionError(error: DocumentSubmissionError)

    func onSubmissionError(error: DocumentSubmissionError) {
        print(error.localizedDescription)
    }
    

Class reference

DocumentSubmissionResponse

DocumentSubmissionResponse object holds information pertaining to the document that was successfully submitted to the ID Verification service.

@objc public class DocumentSubmissionResponse: NSObject, Codable {
    public var documentStatus: [String: DocumentStatus]
    public var documentSubmissionStatus: DocumentSubmissionStatus
    public var document: [String: String]
    public var createdAt: String // Timestamp of when transaction was created
    public var updatedAt: String // Timestamp of when transaction was last updated
    public var expiresAt: String // Timestamp of when transaction expires

    public func getDocumentStatus() -> [String: DocumentStatus]
    public func getDocumentSubmissionStatus() -> DocumentSubmissionStatus
    public func getDocument() -> [String: String]
    public func getCreatedAt() -> String
    public func getUpdatedAt() -> String
    public func getExpiresAt() -> String
}

documentStatus dictionary shows the status of each document requested. For example, if the requested documents for a certain transaction are the following:

  • Email

  • Phone

  • Selfie

and the callback onDocumentSubmitted(response: DocumentSubmissionResponse was fired after submitting Email, the documentStatus property will look like this:

["Email": .PROCESSED, "Phone": .REQUIRED, "Selfie", .REQUIRED]

The list of DocumentStatus states can be found in DocumentStatus

documentSubmissionStatus property shows the status of the entire verification transaction. Detailed information regarding DocumentSubmissionStatus can be found in DocumentSubmissionStatus

document dictionary holds information about the document that was just submitted to the ID Verification service. Only applicable keys are populated in the document dictionary

Data model of document

Key Description
frontImage Base64 encoded string of the front image of a document
backImage Base64 encoded string of the back image of a document
barcode Barcode Data found on the document
mrzData MRZData found on passport and other relevant document
firstName User’s first name as shown on the document
middleName User’s middle name as shown on the document
lastName User’s last name as shown on the document
fullName User’s full name
additionalNameInfo Additional name info about the user
addressStreet User’s street address as shown on the document
addressCity User’s residence city as shown on the document
addressState User’s residence state as shown on the document
addressZip User’s zip code as shown on the document
country User’s residence country as shown on the document
sex User’s sex as shown on the document
dateOfBirth User’s date of birth as shown on the document
placeOfBirth User’s place of birth as shown on the document
nationality User’s nationality as shown on the document
maritalStatus User’s marital status as shown on the document
race User’s race as shown on the document
religion User’s religion as shown on the document
residentialStatus User’s residential status as shown on the document
documentNumber Document number as shown on the document
documentAdditionalNumber Additional document number as shown on the document
personalIdNumber Personal Id number as shown on the document
dateOfIssue Date of issuance of the document
dateOfExpiry Date of expiration of the document
issuingAuthority Issuing authority of the document
employer Employer as shown on the document
profession Profession as shown on the document
DocumentStatus

An enum describing the status of a particular document

@objc public enum DocumentStatus {
    case REQUIRED // document is required
    case OPTIONAL // document is optional; user may choose to skip
    case COLLECTED // document has been collected
    case PROCESSED // document has been processed
    case SKIPPED // document is skipped by user's choice
}
DocumentSubmissionStatus

An enum describing the status of the verification transaction

@objc public enum DocumentSubmissionStatus {
    case not_started // transaction has not been initiated
    case started // transaction has been initiated, but not completed
    case process // transcation is being processed
    case completed // transaction has been processed and is completed
}
SelfieCaptureSettings

A configurable object to customize selfie capture experience

@objc public class SelfieCaptureSettings {
    public let captureTime: TimeInterval // selfie capture time (default is 45 seconds)
    public let shouldCaptureAfterTimeout: Bool // whether user should be able to capture selfie after timeout (default is true)
    public var optional: Bool // whether user can decide to skip selfie capture (default is false)
}

PingOne Verify SDK Errors

ClientBuilderError

ClientBuilderError is returned when PingOneVerify SDK is initialized incorrectly. It subclasses BuilderError and QRError and is returned during Builder.startVerification()

BuilderError
Error Description
.missingRootViewController RootViewController was not set using .setRootViewController(viewController: UIViewController) in the builder
.missingDocumentSubmissionListener DocumentSubmissionListener was not set using .setDocumentSubmissionListener(listener: DocumentSubmissionListener) in the builder
QRError
Error Description
.invalidQR Not a valid PingOne QR Code
.unableToParse Unable to parse QR Code
.missingQueryItems QR Code is missing important query items required to start transaction
.missingVerificationCode QR Code is missing verification code
.missingTransactionId QR Code is missing transactionId
DocumentSubmissionError
Error Description
.initiateDocumentTransactionError Error when initiating a transaction
.submissionError Error when submitting a document
.noDocumentToSubmitError No more document to submit
.missingDocumentType Document type is missing
.invalidKeyMap A valid key map for the document does not exist
.documentCaptureError Error when capturing the data
.documentSubmissionTimeoutError Document Submission has expired
.missingOTPDestination OTP Destination is missing
.failedOTP OTP failed with invalid code

UI Customization

UI Customization for PingOne Verify
UIAppearanceSettings

UIAppearanceSettings instance allows you to customize the SDK's user interface during run time.

@objc public class UIAppearanceSettings: NSObject {
	private var logoImage: UIImage?
	private var backgroundColor: UIColor?
	private var bodyTextColor: UIColor?
	private var headingTextColor: UIColor?
	private var navigationBarColor: UIColor?
	private var navigationBarTextColor: UIColor?
	private var iconTintColor: UIColor?
	private var solidButtonAppearance: ButtonAppearance?
	private var borderedButtonAppearance: ButtonAppearance?
}
Method Description
setLogoImage(_ image: UIImage) -> UIAppearanceSetting Set logo image that is shown at the center of the navigation bar
setBackgroundColor(_ color: UIColor) -> UIAppearanceSetting Set application background color
setBodyTextColor(_ color: UIColor) -> UIAppearanceSetting Set body text color
setHeadingTextColor(_ color: UIColor) -> UIAppearanceSetting Set heading text color
setNavigationBarColor(_ color: UIColor) -> UIAppearanceSetting Set navigation bar background color
setNavigationBarTextColor(_ color: UIColor) -> UIAppearanceSetting Set navigation bar text color
setIconTintColor(_ color: UIColor) -> UIAppearanceSetting Set icon tint color
setSolidButtonAppearance(_ buttonAppearance: ButtonAppearance) -> UIAppearanceSettings Set solid button appearance
setBorderedButtonAppearance(_ buttonAppearance: ButtonAppearance) -> UIAppearanceSettings Set bordered button appearance

Example usage:

    private func getUiAppearanceSettings() -> UIAppearanceSettings {
        let solidButtonAppearance = ButtonAppearance(backgroundColor: .red, textColor: .white, borderColor: .red)
        let borderedButtonAppearance = ButtonAppearance(backgroundColor: .clear, textColor: .red, borderColor: .red)
        
        return UIAppearanceSettings()
            .setSolidButtonAppearance(solidButtonAppearance)
            .setBorderedButtonAppearance(borderedButtonAppearance)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let uiAppearanceSetting = self.getUiAppearanceSettings()
        
        PingOneVerifyClient.Builder(isOverridingAssets: false)
        .setListener(self)
        .setRootViewController(self)
        .setUIAppearanceSetting(uiAppearanceSetting)
        .startVerification { pingOneVerifyClient, clientBuilderError in
            if let pingOneVerifyClient = pingOneVerifyClient {
                // Handle pingOneVerifyClient
            } else if let clientBuilderError = clientBuilderError {
                // Handle builderError
            }
        }
    }
UI Customization
Customizing icon tint color

If using custom image resources, set PingOneVerifyClient.Builder(isOverridingAssets: Bool) to true. When the isOverridingAssets flag is true, the icon tint color is not applied to the custom images.

If PingOneVerifyClient.Builder(isOverridingAssets: Bool) is set to false, the icon tint color is automatically applied to all the icon images.

Customizing image resource

You can customize these images:

Asset Name Description
idv_logo Logo image that appears at the center of the navigation bar
idv_gov_id Image that is shown when government id is requested
idv_selfie Image that is shown when selfie is requested
idv_phone Image that is shown when phone number verification is requested
idv_email Image that is shown when email verification is requested
idv_cancel Image that is used for cancel button at top left of the navigation bar

To customize an image resource:

  1. Include your custom image with the same name in the app asset folder
Customizing color resource

You can customize the following color resources:

  • navigation color

  • button color

  • button background color

  • button text color

  • button border color

  • application background color

  • heading text color

  • body text color

To customize:

  1. Pass a custom UIAppearanceSettings instance in the PingOneVerifyClient.Builder.

  2. Use Branding from the PingOne platform API.

  3. Use Branding & Themes tab found in PingOne Admin Console -> Experiences -> Branding & Themes as described in Branding and themes.

UIAppearanceSettings always has higher priority than Branding and themes.

Thus, if both UIAppearanceSettings and Branding and themes are used, the configuaration specified in UIAppearanceSettings is shown.

Customizing localization

For localization and messages, you can replace the values found in PingOneVerifyLocalizable.strings.

UI Customization from PingOne Admin Console

You can customize items such as:

  • logo

  • navigation color

  • button color

  • button background

  • button text

  • application background

  • heading text

  • body text

To customize:

  • Use Branding from the PingOne platform API.

  • Use Branding & Themes tab found in PingOne Admin Console -> Experiences -> Branding & Themes as described in Branding and themes.

For Localization, use the Localizable.strings file to modify.

Verify Policy

PingOne Verify Native SDK utilizes Verify Policies. You can apply policies two ways:

  • Use Verify Policies from the PingOne platform API.

  • Use Policies tab found in PingOne Admin Console -> PingOne Verify -> Policies to customize verify policy for a particular environment.

PingOne Verify SDK for Android

PingOneVerify Android SDK provides a secure interface for an android app to use the PingOne Verify service for validating a user’s identity. The SDK also parses the responses received from the service for different operations and forwards the same to the app via callbacks.

Running the Sample App

Prerequisites
  • Android Studio with Gradle
  • Android SDK 24 and up
Set Up and Clone or Download

The sample app cannot run on a simulator and works only on a device, because the app requires the camera to capture a selfie and and the related user ID documents.

  1. Clone or download the PingOne Verify SDK for Android sample code to your computer.

    The Sample Code directory contains the Android project that is ready to be built when the prerequisites are satisfied.

  2. To open the sample app as a project in Android Studio, go to File --> New --> Import Project. Choose the SampleCode/PingOneVerify folder as the project's root folder.

Integrating PingOne Verify SDK with Your App

PingOneVerify Android SDK provides a secure interface for an Android app to use the PingOne Verify service for validating a user’s identity. The SDK also parses the responses received from the service for different operations and forwards the same to the app via callbacks.

Getting started

Add the dependencies needed for your application.

If you haven't done so already, clone or download the PingOne Verify SDK for Android sample app. You'll find the *.aar and *.jar dependencies required for the PingOne Verify Android SDK in the SDK directory.

  1. Create a libs folder, if it doesn’t exist under your module, and copy the downloaded *.aar dependencies:

    • PingOneVerify-2.1.0.aar

    • id_scanner_sdk.aar

    • voice_sdk.aar

  2. Add the following to your module level build.gradle file to include the dependencies in your module:

    dependencies {
        implementation fileTree(include: ["*.aar"], dir: "libs")
        ...
    }
    
  3. Because these components are loaded locally, you must also include the SDK’s dependencies in the configuration to compile and run it.

    dependencies {
    
        implementation fileTree(include: ["*.aar"], dir: "libs")
    
        implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
        implementation 'androidx.fragment:fragment:1.6.1'
        implementation 'androidx.appcompat:appcompat:1.6.1'
        implementation 'androidx.camera:camera-camera2:1.2.3'
        implementation 'androidx.camera:camera-core:1.2.3'
        implementation 'androidx.camera:camera-view:1.2.3'
        implementation 'androidx.camera:camera-lifecycle:1.2.3'
        implementation 'androidx.annotation:annotation:1.6.0'
    
        implementation 'com.github.bumptech.glide:glide:4.13.0'
        annotationProcessor 'com.github.bumptech.glide:compiler:4.13.0'
    
        implementation 'com.google.android.material:material:1.9.0'
        implementation 'com.google.android.gms:play-services-mlkit-barcode-scanning:18.3.0'
        implementation 'com.google.android.gms:play-services-mlkit-face-detection:17.1.0'
        implementation 'com.google.code.gson:gson:2.9.0'
        implementation group: 'com.googlecode.libphonenumber', name: 'libphonenumber', version: '8.13.7'
    
        implementation 'com.squareup.retrofit2:converter-moshi:2.7.2'
        implementation 'com.squareup.retrofit2:retrofit:2.9.0'
        implementation 'com.squareup.okhttp3:okhttp:4.9.3'
        implementation 'com.squareup.moshi:moshi:1.14.0'
        implementation group: 'com.squareup.okhttp3', name: 'okhttp-urlconnection', version: '4.9.3'
    
        implementation 'com.squareup.moshi:moshi:1.14.0'
        implementation 'com.squareup.moshi:moshi-kotlin:1.14.0'
        implementation 'com.google.code.gson:gson:2.9.0'
        implementation("androidx.fragment:fragment-ktx:1.6.1")
    
        implementation("com.appmattus.certificatetransparency:certificatetransparency-android:1.1.1")
    
        }
    
Initializing PingOneVerifyClient
  1. Import com.pingidentity.sdk.pingoneverify.PingOneVerifyClient in your desired Activity or Fragment

    import com.pingidentity.sdk.pingoneverify.PingOneVerifyClient;
    
  2. Implement the DocumentSubmissionListener interface and its functions

    public class MainFragment extends Fragment implements DocumentSubmissionListener {
        @Override
        public void onDocumentSubmitted(DocumentSubmissionResponse response) {
            // Callback when document is successfully submitted
        }
        @Override
        public void onSubmissionComplete(DocumentSubmissionStatus status) {
            // Callback when verification transaction is completed
        }
        @Override
        public void onSubmissionError(DocumentSubmissionError error) {
            // Callback when there is an error during submission
        }
    }
    
  3. Instantiate a PingOneVerifyClient.Builder and set its listener and rootActivity (Required)

    new PingOneVerifyClient.Builder()
        .setListener(this)
        .setRootActivity(getActivity())
    
  4. Optionally, you can set an explicit qrString using the PingOneVerifyClient.Builder

    new PingOneVerifyClient.Builder()
        .setListener(this)
        .setRootActivity(getActivity())
        .setQrString(qrString: "https://api.pingone.com...")
    
  5. Optionally, you can set a Selfie Capture Settings with your preference using the PingOneVerifyClient.Builder.

    // Default is 45 seconds for captureTime and true for shouldCaptureAfterTimeout
    SelfieCaptureSettings selfieCaptureSettings = new SelfieCaptureSettings(15, false)
    List<CaptureSettings> settings = new ArrayList<>();
    settings.add(selfieCaptureSettings);
    
    new PingOneVerifyClient.Builder()
        .setRootActivity(getActivity())
        .setListener(this)
        .setDocumentCaptureSettings(Collections.singletonList(new SelfieCaptureSettings(15, false)));
    
  6. Start Verification Process

    new PingOneVerifyClient.Builder()
        .setListener(this)
        .setRootActivity(getActivity())
        .startVerification(new PingOneVerifyClient.Builder.BuilderCallback() {
            @Override
            public void onSuccess(PingOneVerifyClient client) {
                Log.d("initPingOneClient", "success");
            }
    
            @Override
            public void onError(String errorMessage) {
                Log.e(TAG, "Init Client failed with " + errorMessage);
            }
        });
    }
    
DocumentSubmissionListener Callbacks
  1. onDocumentSubmitted(DocumentSubmissionResponse response)

    public void onDocumentSubmitted(DocumentSubmissionResponse response)  {
        Log.d("The  document  status  is :", response.getDocumentStatus())
        Log.d("The  document  submission  status  is",          response.getDocumentSubmissionStatus())
        Map<String,String> documents = response.getDocument();  
        documents.forEach((k,v)->Log.d("(Key, Value):", "("+ k + ","+ v +")"));
    }
    
  2. onSubmissionComplete(DocumentSubmissionStatus status)

    • Called when all required documents have been submitted for a transaction.
    • DocumentSubmissionStatus will always be .COMPLETED
    public void onSubmissionComplete(DocumentSubmissionStatus status) {
        //  present  a  basic  alert  to  indicate  completion
        new AlertDialog.Builder(getActivity())  
            .setTitle("Document SubmissionCOMPLETE")  
            .setMessage("All  documents  have  been  successfully  submitted")  
            .create()  
            .show();
    }
    
  3. onSubmissionError(DocumentSubmissionError error)

    public void onSubmissionError(DocumentSubmissionError error) {  
        Log.e("onSubmissionError", error.getMessage());
    }
    

Class Reference

DocumentSubmissionResponse

DocumentSubmissionResponse object holds information pertaining to the document that was successfully submitted to the ID Verification service.

public class DocumentSubmissionResponse implements Serializable{
    private Map<String, String> documentStatus;
    private DocumentSubmissionStatus documentSubmissionStatus
    private Map<String, String> document
    private String createdAt; // Timestamp of when transaction was created
    private String updatedAt; // Timestamp of when transaction was last updated
    private String expiresAt; // Timestamp of when transaction expires
    public func getDocumentStatus() -> [String: DocumentStatus]
    public func getDocumentSubmissionStatus() -> DocumentSubmissionStatus
    public Map<String, String> getDocument()
    public Date getCreatedAt()
    public Date getUpdatedAt()
    public Date getExpiresAt()
}

documentStatus dictionary shows the status of each document requested. For example, if the requested documents for a certain transaction are the following:

  • Email

  • Phone

  • Selfie

and the callback onDocumentSubmitted(DocumentSubmissionResponse response) was fired after submitting Email, the documentStatus property will look like this:

["Email": .PROCESSED, "Phone": .REQUIRED, "Selfie", .REQUIRED]

The list of DocumentStatus states is in DocumentStatus.

DocumentSubmissionStatus property shows the status of the entire verification transaction. Detailed information regarding DocumentSubmissionStatus is in DocumentSubmissionStatus.

document dictionary holds information about the document that was just submitted to the ID Verification service. Only applicable keys are populated in the document dictionary.

Data model of document

Key Description
frontImage Base64 encoded string of the front image of a document
backImage Base64 encoded string of the back image of a document
barcode Barcode Data found on the document
mrzData MRZData found on passport and other relevant document
firstName User's first name as shown on the document
middleName User's middle name as shown on the document
lastName User's last name as shown on the document
fullName User's full name
additionalNameInfo Additional name info about the user
addressStreet User's street address as shown on the document
addressCity User's residence city as shown on the document
addressState User's residence state as shown on the document
addressZip User's zip code as shown on the document
country User's residence country as shown on the document
sex User's sex as shown on the document
dateOfBirth User's date of birth as shown on the document
placeOfBirth User's place of birth as shown on the document
nationality User's nationality as shown on the document
maritalStatus User's marital status as shown on the document
race User's race as shown on the document
religion User's religion as shown on the document
residentialStatus User's residential status as shown on the document
documentNumber Document number as shown on the document
documentAdditionalNumber Additional document number as shown on the document
personalIdNumber Personal Id number as shown on the document
dateOfIssue Date of issuance of the document
dateOfExpiry Date of expiration of the document
issuingAuthority Issuing authority of the document
employer Employer as shown on the document
profession Profession as shown on the document
DocumentStatus

An enum describing the status of a particular document

public enum DocumentStatus {
    case REQUIRED, // document is required
    case OPTIONAL, // document is optional; user may choose to skip
    case COLLECTED, // document has been collected
    case PROCESSED, // document has been processed
    case SKIPPED; // document is skipped by user's choice
}
DocumentSubmissionStatus

An enum describing the status of the verification transaction

public enum DocumentSubmissionStatus implements Serializable {
    @Json(name = "NOT_STARTED") NOT_STARTED, // transaction has not been initiated
    @Json(name = "STARTED") STARTED,// transaction has been initiated, but not completed
    @Json(name = "COMPLETED") COMPLETED, // transcation is being processed
    @Json(name = "PROCESS") PROCESS // transaction has been processed and is completed
}
SelfieCaptureSettings

A configurable object to customize selfie capture experience

public class SelfieCaptureSettings {
    public int captureTime; // selfie capture time (default is 45 seconds)
    public boolean shouldCaptureAfterTimeout; // whether user should be able to capture selfie after timeout (default is true)
}

PingOne Verify SDK Errors

ClientBuilderError

ClientBuilderError is returned when PingOneVerify SDK is initialized incorrectly. It subclasses BuilderError and QRError and is returned during Builder.startVerification()

BuilderError
Error Description
"Must Set RootActivity" RootActivity was not set using .setRootActivity(getActivity()) in the builder
"Must Set DocumentSubmissionListener" DocumentSubmissionListener was not set using .setDocumentSubmissionListener(listener) in the builder
QRError
Error Description
"Unable to parse queryItems from QR String: " Unable to parse QR Code
"Missing verification code" QR Code is missing verification code
"Missing TransactionId" QR Code is missing transactionId
DocumentSubmissionError
Error Description
"Unable to initiate document transaction for transactionId:" Error when initiating a transaction
"initiateDocumentCollection error" Error when submitting a document
"There are no documents to submit for this transaction" No more document to submit
"Missing Document Type" Document type is missing
"Invalid key map for documentType:" A valid key map for the document does not exist
"Document Capture Error" Error when capturing the data
.documentSubmissionTimeoutError Document Submission has expired
"Missing OTP Destination for:" OTP Destination is missing
"Verification Code failed for %s" OTP failed with invalid code

UI Customization

UI Customization for PingOne Verify
UIAppearanceSettings

UIAppearanceSettings instance allows you to customize the SDK's user interface during run time.

public class UIAppearanceSettings {

    private ImageLink logoImage;
    private String backgroundColor;
    private String bodyTextColor;
    private String headingTextColor;
    private String navigationBarColor;
    private String navigationBarTextColor;
    private String iconTintColor;
    private ButtonAppearance solidButtonAppearance;
    private ButtonAppearance borderedButtonAppearance;
}
Method Description
public UIAppearanceSettings setLogoImage(Bitmap logoImage) Set logo image that is shown at the center of the navigation bar
public UIAppearanceSettings setBackgroundColor(String backgroundColor) Set application background color
public UIAppearanceSettings setBodyTextColor(String bodyTextColor) Set body text color
public UIAppearanceSettings setHeadingTextColor(String headingTextColor) Set heading text color
public UIAppearanceSettings setNavigationBarColor(String navigationBarColor) Set navigation bar background color
public UIAppearanceSettings setNavigationBarTextColor(String navigationBarTextColor) Set navigation bar text color
public UIAppearanceSettings setIconTintColor(String iconTintColor) Set icon tint color
public UIAppearanceSettings setSolidButtonAppearance(ButtonAppearance solidButton) Set solid button appearance
public UIAppearanceSettings setBorderedButtonAppearance(ButtonAppearance borderedButton) Set bordered button appearance

Example usage:

	final UIAppearanceSettings settings = new UIAppearanceSettings()
                .setLogoImage(logoImage)
                .setSolidButtonAppearance(new ButtonAppearance("#FF0000","#FF0000","#FFFFFF")) // red backgroundColor, red borderColor, white textColor
                .setBorderedButtonAppearance(new ButtonAppearance("#00FFFFFF","#FF0000","#FF0000")); // clear backgroundColor, red borderColor, red textColor
	
	new PingOneVerifyClient.Builder(false)
                .setRootActivity(getActivity())
                .setListener(this)
                .setUIAppearance(settings)
                .startVerification(new PingOneVerifyClient.Builder.BuilderCallback() {
                    @Override
                    public void onSuccess(PingOneVerifyClient client) {
                        // Use pingOneVerifyClient
                    }

                    @Override
                    public void onError(String errorMessage) {
                        // Handle builderError
                    }
                });
UI Customization
Customizing icon tint color

If using custom image resources, set PingOneVerifyClient.Builder(bool) to true. When the boolean flag is true, the icon tint color is not applied to the custom images.

If PingOneVerifyClient.Builder(bool) is set to false, the icon tint color is automatically applied to all the icon images.

Customizing image resource

You can customize these images:

Asset Name Description
idv_logo Logo image that appears at the center of the navigation bar
idv_gov_id Image that is shown when government id is requested
idv_selfie Image that is shown when selfie is requested
idv_phone Image that is shown when phone number verification is requested
idv_email Image that is shown when email verification is requested
idv_cancel Image that is used for cancel button at top left of the navigation bar

To customize an image resource:

  1. Include your custom image with the same name in the corresponding drawable folder.
Customizing color resource

You can customize the following color resources:

  • navigation color

  • button color

  • button background color

  • button text color

  • application background color

  • heading text color

  • body text color

To customize:

  1. Pass a custom UIAppearanceSettings instance in the PingOneVerifyClient.Builder.

  2. Use [Branding]/pingone/platform/v1/api/#branding) from the PingOne platform API.

  3. Use Branding & Themes tab found in PingOne Admin Console -> Experiences -> Branding & Themes as described in Branding and themes.

UIAppearanceSettings always has higher priority than Branding and themes.

Thus, if both UIAppearanceSettings and Branding and themes are used, the configuaration specified in UIAppearanceSettings is shown.

Customizing localization

For localization and messages, you can replace the values found in PingOneVerifyLocalizable.xml.

UI Customization from PingOne Admin Console

You can customize items such as:

  • logo

  • navigation color

  • button color

  • button background

  • button text

  • application background

  • heading text

  • body text

To customize:

  • Use Branding from the PingOne platform API.

  • Use Branding & Themes tab found in PingOne Admin Console -> Experiences -> Branding & Themes as described in Branding and themes.

For Localization, use the strings.xml file in res/values to modify.

Verify Policy

PingOne Verify Native SDK utilizes Verify Policies. You can apply policies two ways:

  • Use Verify Policies from the PingOne platform API.

  • Use Policies tab found in PingOne Admin Console -> PingOne Verify -> Policies to customize verify policy for a particular environment.

PingOne Wallet Native SDKs

This defines the usage and interfaces of the PingOne Wallet Native SDKs to interact with PingOne credentialing services. The SDK provides for a user to receive, save, and share credentials for identification and verification purposes. PingOne Wallet Native SDKs are available in for two operating systems:

PingOne Wallet Native SDK for iOS

This defines the usage and interfaces of the PingOne Wallet SDK for iOS to interact with PingOne credentialing services. The SDK provides for a user to receive, save, and share credentials for identification and verification purposes.

Running the sample app

Installation prerequisites
  • Xcode 12 or greater

  • iOS 13 or greater

Set up and clone or download

The sample app can not run on a simulator and works only on a device because the app uses the secure enclave and keychain for storing information and the app requires the camera to capture a selfie for profile creation.

  1. Ensure your Xcode is set up with a provisioning profile and a signing certificate to install the app on a device. See the Apple Xcode document Run an app on a device for more information.

  2. Clone or download the PingOne Wallet SDK for iOS sample code to your machine and open the PingOneWalletSample.xcodeproj file located under the PingOneWalletSample directory.

    You will find all other XCFramework dependencies required for PingOne Wallet iOS SDK in the SDK directory.

  3. To run the sample app, select the scheme PingOneWalletSample --> , and click the Run button.

Integrating PingOne Wallet SDK for iOS with your app

Getting started: Add the dependencies needed for your application

The PingOne Wallet SDK for iOS relies on XCFramework components. You'll need to add these to Xcode for use by your application.

  1. If you haven't done so already, clone or download the PingOne Wallet SDK for iOS sample app. You will find the XCFramework dependencies required for the PingOne Wallet iOS SDK in the SDK directory.

  2. Add the .xcframework dependencies:

    a. Click on your target in the project navigator.

    b. Drag and drop all the xcframework dependencies to the section Frameworks, Libraries, and Embedded Content in Xcode.

  3. Add SVGKit via Swift Package Manager

    a. In Xcode go to File -> Add Packages...

    b. Type https://github.com/SVGKit/SVGKit in the search bar.

    c. Choose Dependency Role and download the dependency.

Installation and configuration

Set up iOS push messaging.

App prerequisites

Ensure you have the following information necessary to set up push notifications for your PingOne Wallet application:

  • Key ID

  • Team ID

  • Token .p8 file

  • Bundle ID

See the Apple guide Establishing a Token-Based Connection to APNs for more information.

Configure push notifications
  1. See the PingOne documentation for Adding an application - Native to register your wallet app.

  2. After adding your wallet application, go to Mobile -> Edit () -> Configure for iOS -> Add Push Notifications

  3. Upload your .p8 token and fill in the Key ID, Team ID, and Bundle ID values.

  4. Save your changes.

See the PingOne documentation Edit an application - Native for more information.

Protocols

PingOneWalletClient

PingOneWalletClient provides the protocols to interact with the wallet methods and register callback handlers.

Methods
func registerCallbackHandler(_ callbackHandler: WalletCallbackHandler)

Call this method to register your wallet and create a new application instance for your wallet. If an application instance already exists, the SDK will retrieve the same instance instead of creating a new one.

Parameter Description
callbackHandler Instance of WalletCallbackHandler to handle important events such as credential issuance, revocation, or presentation
func registerStorageManager(_ storageManager: StorageManagerContract)

Call this method to register an optional storage manager that can be used by the SDK to maintain the values for claims and other data.

Parameter Description
storageManager Implementation of the StorageManager interface
func updatePushToken(_ pushToken: String)

Updates APNs push token to receive notifications from the service

Parameter Description
pushToken APNs Token
func processQrContent(_ qrContent: String)

Call this method to handle the content from the QR codes for issuance or presentation.

Parameter Description
qrContent Raw content from the QR code
func pairWallet(for presentationRequest: PresentationRequest, pushToken: String?) -> CompletionHandler<ApplicationInstance>

Call this method to handle the wallet pairing request.

Returns a completion handler with an updated application instance for storage if a push notification token was supplied

Parameter Description
presentationRequest Request from service for wallet pairing containing the issuer ID and session id required for pairing
pushToken Optional push token
func findMatchingCredentialsForRequest(_ request: PresentationRequest, credentials: [Claim]) -> PresentationMatcherResult

Call this method to filter the verifiable credentials that match the schema defined in the input descriptor in the presentation request.

This method returns a PresentationMatcherResult that contains the list of VerifiableCredentials matching the criteria defined in the presentation request

Parameter Description
request Presentation Request for the claims
credentials List of claims saved in the Wallet
func presentCredentials(_ presentation: CredentialsPresentation) -> CompletionHandler<PresentationResult>

Call this method to send the verifiable presentation to the redirect uri defined in the presentation request.

This method returns a completion handler with PresentationResult denoting whether presentation was successful.

Parameter Description
presentation CredentialPresentation object containing filtered credentials and presentation request
func reportCredentialDeletion(claim: Claim)

Reports when a credential is deleted from the Wallet.

Parameter Description
claim Claim that was deleted from wallet
StorageManagerContract

PingOne Wallet Native SDK for iOS does not persist any information and relies on the app for maintaining the keys and credentials. Applications can implement the StorageManagerContract and provide an instance of the same to the PingOneWalletClient.

Methods
func saveApplicationInstance(_ applicationInstance: ApplicationInstance)

Saves the ApplicationInstance created for the wallet on initialization.

Parameter Description
applicationInstance ApplicationInstance for the wallet
func getApplicationInstance() -> ApplicationInstance?

Retrieves the saved ApplicationInstance that was created when the wallet was initialized for the first time, return nil if not found.

func saveClaim(_ claim: Claim)

Saves an issued credential to storage.

Parameter Description
claim Claim object
func getClaim(claimId: String) -> Claim?

Returns a Claim object matching the provided claimId if found, nil otherwise.

Parameter Description
claimId String UUID for claim lookup
func deleteClaim(_ claimId: String)

Deletes a claim from the storage if it exists.

Parameter Description
claimId String UUID for claim
func getClaims() -> [Claim]

Returns a list of all the claims from storage.

func saveString(_ str: String, for key: String)

Saves a generic String to storage.

Parameter Description
str String to be saved
key String to be used to retrieve the saved string
func getString(for key: String) -> String?

Retrieves the String previously saved for the given key, return nil if not found.

Parameter Description
key A String previously used to save another String to the wallet
WalletCallbackHandler

Implement the WalletCallbackHandler to handle different credential events such as issuance, revocation, or presentation.

Methods
func handleCredentialIssuance(issuer: String, message: String?, challenge: Challenge?, claim: Claim, errors: [WalletException]) -> Bool

Implement this method to handle newly issued credentials.

Returns true if the user accepts the credential and false if the user rejects the credential.

Parameter Description
issuer applicationInstanceID of the credential issuer
message Optional string message
challenge Optional challenge
claim Issued credential
errors List of any errors while processingor verifying the credential
func handleCredentialRevocation(issuer: String, message: String?, challenge: Challenge?, claimReference: ClaimReference, errors: [WalletException]) -> Bool

Handles the revocation of a credential.

Returns true if the user accepts the revocation and false if the user rejects the revocation.

Parameter Description
issuer applicationInstanceID of the credential issuer
message Optional string message
challenge Optional challenge
claimReference ClaimReference for the revoked credential
errors List of any errors that occurred while verifying the revocation of the credential
func handleCredentialPresentation(sender: String, message: String?, challenge: Challenge?, claim: [Share], errors: [WalletException])

Triggered when another wallet shares a credential with the current application instance.

Parameter Description
sender applicationInstanceID of the sender
message Optional string message
challenge Optional challenge
claim Presented or shared credentials
errors List of any errors that occurred while verifying the presented credentials
func handleCredentialRequest(_ presentationRequest: PresentationRequest)

Triggered when a presentation request is received by the wallet in the form of a QR code or a Universal link or via push notification.

Parameter Description
presentationRequest Request for presenting one or more credentials from the wallet
func handleError(_ error: WalletException)

Triggered when the SDK runs into any errors while processing the events or messages.

Parameter Description
error An error that can be used to describe an error by error code and error message

Class reference

ApplicationInstance

The ApplicationInstance class represents an instance of a compatible wallet app.

When the wallet SDK is initialized for the first time, it creates a new application instance, registers with the credentials service, and saves the application identifier with cryptographic keys locally if a storage manager is provided. If an app does not provide an instance of StorageManagerContract, it will be the app's responsibility to store the ApplicationInstance and provide the same instance back to the SDK on each initialization.

Property Description
id The UUID for the compatible wallet.
jwks The JSON Web Key Set (JWKS) the application will use to sign the presentations and verify the credentials.
pushToken A string used to send push notifications to compatible wallet apps.
osType A string identifying the operating system of a compatible wallet app.
Challenge

Use the Challenge class to correlate separate requests, or to expire a request after a certain time. For example, a new compatible session is created when a client creates a presentation exchange request for another wallet instance. When the receiving client sends the data back, it must send the same Challenge object. The recipient's SDK instance checks the expiration time passed in the challenge (if any), and terminates any further communication on the expired challenge.

Property Description
id The UUID for the Challenge object.
expiresAt An Instant object containing the UNIX timestamp.
Claim

A Claim represents a set of keys and values that are asserted to be correct by the issuer and their integrity can be verified using the ClaimReference information from the Claim object.

Property Description
claimData Salted claim data
otherFormats Formats that can be used to create objects like VerifiableCredential from the claim.
ClaimReference

The ClaimReference class is identical to the Claim class, with the exception of the claimData property. Use the ClaimReference class as a reference to expire a claim, without having to retain personally-identifiable information (PII).

Property Description
id A string containing the unique ID of the claim locator.
createDate An Instant object containing the timestamp for when the claim was created.
issuer A SaltedData object containing the claim issuer information.
subject A SaltedData object containing the claim subject information.
holder A SaltedData object containing the claim holder information.
referenceClaimID (Optional) A SaltedData object used to reference the claim that provided the original data.
dataJSON A string containing the claim information in JSON format.
dataSignature A string containing the signature for the claim.
dataHash A string containing a hash of the claim information.
CredentialMatcherResult

The CredentialMatcherResult class contains a list of requestedKeys and the claims matching the filtering criteria from the presentation request.

Property Description
requestedKeys A list of keys that were requested
claims A list of Claims that contain the keys in requestedKeys
CredentialsPresentation

The CredentialsPresentation class represents the response to a PresentationRequest. It contains the claims matching the filtering criteria and picked by the user if more than one claim matches the criteria.

Property Description
presentationRequest The PresentationRequest object containing the filtering criteria and other information about the request such as requestor identifier, purpose, or session
Method Description
isEmpty() Returns a boolean that describes whether or not any Claims have been added to the Presentation
addClaimForKey(_ claim: Claim, keys: [String]) Adds a claim to be shared for a List of corresponding requested keys
PresentationMatcherResult

The PresentationMatcherResult contains a list of credentials matching the filtering criteria for a presentation request.

Property Description
credentialMatcherResult A list of one or more CredentialMatcherResult that satisfy the requestedKeys of a credential request
PresentationRequest

The PresentationRequest includes the requested keys and information about the requestor.

Method Description
getRequestor() Returns the applicationInstanceID of the requestor
getSessionID() Returns the unique ID for the presentation session
getPurpose() Returns an Optional purpose String
getKeys() Returns a [RequestedKey] object that contains the requested keys of a presentation request
getStringKeys() Returns a [String] object that contains the requested keys of a presentation request
PresentationResult

The PresentationResult class contains information on whether or not a presentation was successful.

Property Description
result Whether or not the presentation was successful
details [String: Any]? response body from presentation
RequestedKey

RequestedKey contains the card type and card key requested for a singular key.

Property Description
rawKey A raw String that can be parsed to obtain the cardKey and cardType
cardKey The key requested in the rawKey
cardType The type of card requested in the rawKey
issuerIds List of issuerIds associated with the requestedKey
Share

The Share class encapsulates the data and the associated claim to verify the data. This object can be used by the verifier to validate the integrity of the information in the claim.

Property Description
keys A list of strings containing the requested keys
claim The Claim object to use for verification of the data
WalletException

The WalletException class is the base class for all exceptions thrown by the PingOne Wallet Native SDK.

Property Description
errorDescription exception Message

Integration Examples

This section explains how to integrate the wallet SDK for various use cases.

Integrate the SDK with no user interaction

The sample app is designed for the use case where the wallet SDK embedded in the application is paired with a PingOne environment by an explicit pairing request initiated by the PingOne environment. In that pairing process the PingOne environment admin sends an email to the user with a Universal Link to open the wallet application to complete the pairing.

This example illustrates how to integrate the digital wallet SDK with no user interaction (silent mode).

Initialization and wallet pairing

The illustrated workflow is followed to instantiate a wallet SDK that triggers a pairing request from the app. We must instantiate the wallet SDK and get the applicationInstanceId, which is a UUID that uniquely identifies the wallet SDK instance in the app. This applicationInstanceId is sent to a server trusted by the app. The server in turns calls a PingOne API to initiate and silently complete the wallet pairing.

workflow to silently integrate a wallet SDK with no user interaction

Steps 1 and 2 - Get the applicationInstanceId

The illustrated workflow requires modification of the PingOneWalletHelper.swift file (at line 21 in the source file) to get the applicationInstanceId from the instantiated SDK to enable a backend pairing request.

This code requires that:

  • The application has already established the user to which the wallet belongs using existing authentication means

  • The application has a trusted service backend with which it can communicate.

    let clientBuilder = PingOneWalletClient.Builder()
    // set storage manager for easy manangement of encrypted storage
    if let storageManager = storageManager {
        clientBuilder.setStorageManager(storageManager)
    }
    // Using the builder pattern, once the clientBuilder is setup 
    clientBuilder.build()
        .onError { error in
            completionHandler.setError(error)
        }
        .onResult { client in
            // You need the applicationInstanceId for the instantiated 
            let applicationInstanceId = client.getApplicationInstance().getId()
            // Send this applicationInstanceId to a trusted service
            // to pair the wallet with the "user" in the application.
            ...
        }
Step 3 - Request pairing

Send a request to pair userId from the application with the applicationInstanceId of the wallet SDK. This requires custom code and the details depend on the application. Ping Identity recommends that mobile applications do not directly call the PingOne OAuth APIs.

Step 4 - Create a user and pair the wallet

Call the PingOne APIs to create a user in your PingOne environment and pair a digital wallet.

Create User API

curl -X POST https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/users

Create digital wallet API

curl -X POST https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/users/49825b76-e1df-4cdc-b973-0c580f1cb049/digitalWallets

with a body similar to

Authorization: Bearer {{accessToken}}
Content-type: application/json

{
    "digitalWalletApplication": {
        "id": "{{digitalWalletApplicationID}}"
    },
    "applicationInstance": {
        "id": "{{applicationInstanceId}}"
    }
}
Step 5 - Pairing request

PingOne sends a pairing request to the wallet SDK embedded in the user app identified by applicationInstanceId.

  1. The pairing request contains a “cryptographically secure random challenge string” that the wallet SDK signs and returns to the PingOne credentials service.

  2. PingOne credentials service sends an end-to-end encrypted message to the wallet SDK embedded in the user app. The PingOne Mailbox Service sends this message.

  3. The wallet SDK inside the app polls the PingOne Mailbox service every 3 seconds. This is default behavior so there is no need to write additional code or make any modifications.

  4. When the app receives the encrypted message from the PingOne Credentials service, it decrypts the message and calls the registered message handler as defined in PingOneWalletHelper.swift.

  5. Code below is modified from PingOneWalletHelper.swift to ensure that no user interaction is required to complete the pairing process. This is a method in the WalletCallbackHandler swift protocol implemented in the PingOneWalletHelper.swift file.

    func handleCredentialRequest(_ presentationRequest: PresentationRequest) {
        if presentationRequest.isPairingRequest() {
            self.pingoneWalletClient.pairWallet(for: presentationRequest)
            .onResult({ _ in
                logattention("Wallet pairing successful")
            })
            .onError { err in
                logerror("Wallet pairing failed: \(err.localizedDescription)")
            }
            return        
        }
        ...
    }
Step 6 - Wallet pairs

The call to SDK method pairWallet (on line 3) in the modified code responds to the pairing request and the app pairs with the user in the PingOne environment.

Step 6a in the illustrated workflow is the call to pairWallet.

Step 6b in the illustrated workflow is the feedback .onResult (on lines 4) and .onError (on line 7) in the modified code responds on success or failure of the message delivery for pairing.

Issuance and revocation

To implement the credential issuance and revocation workflow requires changes to the sample app code.

Modify the sample app code

The sample app uses popup messages (also called toasts) to alert the user that the wallet SDK has received a notification about an issued credential or a revoked credential. You must modify the code to mute the popup messages and in the sample app.

Step 6 - Modify the sample app code

The illustrated workflow requires modification of the PingOneWalletHelper.swift file to not display a popup when a credential issuance request is received.

    func handleCredentialIssuance(issuer: String, 
                                  message: String?, 
                                  challenge: Challenge?, 
                                  claim: Claim, 
                                  errors: [PingOneWallet.WalletException]) -> Bool {
        logattention("Credential received: Issuer: \(issuer), 
                      message: \(message ?? "none")")
//        NotificationUtils.showToast(message: "Received a new credential")
        DataRepository.shared.saveClaim(claim)
//        EventObserverUtils.broadcastClaimsUpdatedNotification()
        return true
    }
    
    func handleCredentialRevocation(issuer: String, 
                                    message: String?,
                                    challenge: Challenge?,
                                    claimReference: ClaimReference, 
                                    errors: [PingOneWallet.WalletException]) -> Bool {
        logattention("Credential revoked: Issuer: \(issuer), message: \(message ?? "none")")
//        NotificationUtils.showToast(message: "Credential Revoked")
        DataRepository.shared.saveRevokedClaimReference(claimReference)
//        EventObserverUtils.broadcastClaimsUpdatedNotification()
        return true
    }
Step 7 - Write to local storage

DataRepository defined in the DataRepository.swift has sample code to securely write to local application storage using the keys stored in the secure enclave.

You can always override the DataRepository implementation by writing your own classes that implement the DataRepositoryProtocol defined in the DataRepositoryProtocol.swift file.

Complete process for issuance and revocation

credential issuance and revocation workflow

  1. An API orchestration layer or an administrator using the Admin Console makes changes to user attributes in the user directory.

  2. The PingOne Credentials Lifecycle Manager listens to directory change events and reviews the changes to determine if credentials must be issued or revoked based on credential issuance rules. If a credential needs to be issued or revoked the lifecycle manager makes entries in the staging area.

  3. The PingOne Credentials API is invoked periodically to process all staged changes. The PingOne Credentials API issues or revokes credentials as determined by the Lifecycle Manager.

  4. The credentials that are issued or revoked are bound to the wallet and are sent to the wallet using secure end-to-end encrypted messages using the Mailbox functionality of the PingOne Neo platform.

  5. The Wallet SDK embedded inside the app polls the Mailbox API to check for new messages. The mailbox API returns newly issued or recently revoked credential message as an encrypted message meant for the SDK to read.

  6. The Wallet SDK calls the app via the callback method handleCredentialIssuance or handleCredentialRevocation which the app has registered via the callback handler described earlier.

  7. The User App handles the callback by storing the issued credential to or deleting the revoked credential from storage using storage manager implementation.

Presentation

The sample app uses the PingOneWalletHelper class in PingOneWalletHelper.swift to handle links, QR code content, and push notification requests for presentation of credentials.

class PingOneWalletHelper {
    
    static func initializeWallet(_ storageManager: StorageManagerContract?) 
                -> CompletionHandler<Bool> {
        let completionHandler = CompletionHandler<Bool>()
        if let _ = shared {
            completionHandler.setResult(true)
            return completionHandler
        }
        
        let clientBuilder = PingOneWalletClient.Builder()
        if let storageManager = storageManager {
            clientBuilder.setStorageManager(storageManager)
        }
        clientBuilder.build()
            .onError { error in
                completionHandler.setError(error)
            }
            .onResult { client in
                shared = PingOneWalletHelper(client, 
                              storageManager: storageManager)
                completionHandler.setResult(true)
            }
        
        return completionHandler
    }
    
    public static var shared: PingOneWalletHelper!
    
    private var pingoneWalletClient: PingOneWalletClient!
    
    private init(_ pingoneWalletClient: PingOneWalletClient, 
                 storageManager: StorageManagerContract?) {
        self.pingoneWalletClient = pingoneWalletClient
        self.pingoneWalletClient.registerCallbackHandler(self)
        if let storageManager = storageManager {
            self.pingoneWalletClient.registerStorageManager(storageManager)
        }
        DataRepository.shared.
                storageManager.
                saveApplicationInstance(
                    pingoneWalletClient.getApplicationInstance()
                )
    }
    
    func processQrContent(_ qrContent: String) {
        self.pingoneWalletClient.processQrContent(qrContent)
    }

}

Notes on the PingOneWalletHelper class implementation:

  1. It implements a singleton pattern to instantiate a shared instance of the class at line 19.

  2. It instantiates the PingOneWalletClient to communicate with the PingOne Neo backend services. For more information, see PingOne Wallet Native SDK for iOS.

  3. It uses the pingoneWalletClient instance to updatePushToken at line 40 to allow the PingOne Neo service to send push notifications. This line can be safely commented out to avoid getting push notifications from the PingOne Neo service (if the server application is configured to send push notifications).

  4. The code at line 43 can be used to parse and manage QR code content that can be identified as belonging to the PingOne Neo platform. When line 44 calls self.pingoneWalletClient.processQrContent(qrContent), the SDK can interpret the content of the QR code and handle the presentation request. It does so by calling the app using the callback handler methods registered at line 32.

Following code is used to demonstrate how to handle the callback when the SDK receives a request to share a credential due to processing of a QR code, a deep link or a push notification request.

func handleCredentialRequest(_ presentationRequest: PresentationRequest) {
    // handle pairing request as described above
    
    let allClaims = DataRepository.shared.getAllClaims()
    let credentialMatcherResults = self.pingoneWalletClient.
                findMatchingCredentialsForRequest(
                        presentationRequest, 
                        credentials: allClaims).
                getResult()
    
    var matchingCredentials: Bool = false
    for credentialMatcherResult in credentialMatcherResults {
        if !(credentialMatcherResult.claims.isEmpty) {
            matchingCredentials = true
            break
        }
    }
    
    guard matchingCredentials else {
        // handle no matching credential found in user's wallet
        return
    }
    
    // handle logic to select the credential to present 
    // if multiple matching credentials are found in the wallet.
    
    // handle presentation of the credentials (assuming that 
    // only one credential matched the wallet)
    
    let credentialPresentation = CredentialsPresentation(presentationRequest: presentationRequest)
    guard let claim = credentialMatcherResults.first?.claims.first else {
        //No matching credentials
        return
    }
    credentialPresentation.addClaimForKeys(claim, keys: presentationRequest.getStringKeys())
    
    self.pingoneWalletClient.presentCredentials(credentialPresentation)
        .onResult { result in
            switch result.getPresentationStatus() {
            case .success:
                    // Credential presentation successful
            case .failure:
                // Credential presentation failed
                logerror("Error sharing information:
                            \(result.getDetails()?.debugDescription ?? "None")")
//                case .requiresAction(let action):
                    // Handle the action sent by the verifier 
                    // for the wallet as response to the presentation
            }
        }
        .onError { err in
            logerror("Error sharing information: \(err.localizedDescription)")
        }
        
    }

PingOne Wallet Native SDK for Android

This defines the usage and interfaces of the PingOne Wallet SDK for Android to interact with PingOne credentialing services. The SDK provides for a user to receive, save, and share credentials for identification and verification purposes.

Running the sample app

Installation prerequisites
  • Android Studio with Gradle

  • Android SDK 24 and later

Set up and clone or download
  1. Clone or download the PingOne Wallet SDK for Android sample code to your computer.

    The Sample Code directory contains the Android project that is ready to be built when the prerequisites are satisfied.

  2. To open the sample app as a project in Android Studio, go to File --> New --> Import Project. Choose the build.gradle from the root folder and open the file to configure the project.

Integrating PingOne Wallet SDK for Android with your app

Getting started: Add the dependencies needed for your application

If you haven't done so already, clone or download the PingOne Wallet SDK for Android sample app. You will find the *.aar and *.jar dependencies required for the PingOne Wallet Android SDK in the SDK dependencies directory.

  1. Add the following to your module level build.gradle file to include the dependencies in your module:

    dependencies {
    
    implementation fileTree(dir: '../dependencies/', include: ['*.aar', '*.jar'], exclude: [])
    
    ...
    }
    
  2. Because these components are loaded locally, you will also need to include the SDK's dependencies in the configuration to compile and run it.

    dependencies {
    	implementation fileTree(dir: '../dependencies/', include: ['*.aar', '*.jar'], exclude: [])
    		implementation 'org.bitbucket.b_c:jose4j:0.8.0'
    		implementation 'androidx.appcompat:appcompat:1.5.1'
    
    		implementation 'com.google.android.material:material:1.7.0'
    
    		implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    		implementation 'androidx.annotation:annotation:1.5.0'
    		implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    		implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.5.1'
    		implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'
    		implementation 'androidx.camera:camera-camera2:1.2.0'
    		implementation 'androidx.camera:camera-core:1.2.0'
    		implementation 'androidx.camera:camera-view:1.2.0'
    		implementation 'androidx.camera:camera-lifecycle:1.1.0'
    		implementation 'androidx.security:security-crypto:1.1.0-alpha04'
    		implementation 'androidx.security:security-identity-credential:1.0.0-alpha03'
    		implementation 'androidx.biometric:biometric:1.1.0'
    
    		implementation 'com.google.android.gms:play-services-mlkit-barcode-scanning:18.1.0'
    		implementation 'com.google.firebase:firebase-messaging:23.1.1'
    
    		implementation 'com.squareup.retrofit2:converter-moshi:2.7.2'
    		implementation 'com.squareup.retrofit2:converter-gson:2.7.2'
    		implementation 'com.squareup.retrofit2:converter-scalars:2.7.2'
    		implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'
    		implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    		implementation 'com.squareup.okhttp3:okhttp-urlconnection:4.9.3'
    		implementation 'com.squareup.moshi:moshi:1.14.0'
    		implementation 'com.squareup.moshi:moshi-adapters:1.14.0'
    
    		implementation 'com.caverock:androidsvg-aar:1.4'
    
    		implementation 'io.github.erdtman:java-json-canonicalization:1.1'
    
    		implementation 'io.reactivex.rxjava3:rxjava:3.0.12'
    		implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
    
    		implementation 'com.google.dagger:dagger:2.44.2'
    		implementation 'com.google.dagger:dagger-android:2.44.2'
    		implementation 'com.google.dagger:dagger-android-support:2.44.2'
    
    		annotationProcessor 'com.google.dagger:dagger-android-processor:2.31.2'
    		annotationProcessor 'com.google.dagger:dagger-compiler:2.44.2'
    }
    
Installation and configuration

Set up Android push messaging.

App prerequisites

Ensure you have the following information needed to set up push notifications for your PingOne Wallet application using Firebase Cloud Messaging (FCM):

  • Server Key

  • Package Name

  • google-services.json configuration file

See the Firebase guide Add Firebase to your Android for more information.

Configure push notifications
  1. Add the google-services.json file to your app and copy the Server Key from your project in the Firebase Console.

  2. See the PingOne documentation for Adding an application - Native to register your wallet app.

  3. After adding your wallet application, go to Mobile -> Edit () -> Configure for Android -> Add Push Notifications

  4. Add the Package Name and paste your Server Key from step 1 here.

  5. Save your changes.

See the PingOne documentation Edit an application - Native for more information.

Interfaces

PingOneWalletClient

PingOneWalletClient provides the interfaces to interact with the wallet methods and register callback handlers.

Methods
void registerCallbackHandler(final WalletCallbackHandler callbackHandler);

Call this method to register your wallet and create a new application instance for your wallet. If an application instance already exists, the SDK will retrieve the same instead of creating a new one.

Parameter Description
callbackHandler Instance of WalletCallbackHandler to handle important events such as credential issuance, revocation, or presentation
void registerStorageManager(final StorageManagerContract storageManager);

Call this method to register the optional storage manager that can be used by the SDK to maintain the values for claims and other data.

Parameter Description
storageManager Implementation of the StorageManager interface
ApplicationInstance updatePushToken(final String pushToken);

Updates firebase push token to receive notifications from the service.

Returns the updated application instance with the push notification token.

Parameter Description
pushToken Firebase Push Notification Token
void processQrContent(final String qrContent);

Call this method to handle the content from the QR codes for issuance or presentation.

Parameter Description
qrContent Raw content from the QR code
ApplicationInstance pairWallet(PresentationRequest presentationRequest, Context context, String pushToken) throws WalletException;

Call this method to handle the wallet pairing request.

Returns the updated application instance for storage if a push notification token was supplied.

Throws WalletException if any errors while pairing the wallet.

Parameter Description
presentationRequest Request from service for wallet pairing containing the issuer id and session id required for pairing
context Context required to read application metadata, such as application package
pushToken Optional push token
PresentationMatcherResult findMatchingCredentialsForRequest(final PresentationRequest presentationRequest, final List<Claim> claims);

Call this method to filter the verifiable credentials that match the schema defined in the input descriptor in the presentation request.

This method returns a PresentationMatcherResult that contains the list of VerifiableCredentials matching the criteria defined in the presentation request.

Parameter Description
presentationRequest Presentation Request for the claims
claims List of claims saved in the Wallet
Single<PresentationResult> presentCredentials(final CredentialsPresentation presentation);

Call this method to send the verifiable presentation to the redirect uri defined in the presentation request.

This method returns a VerifiablePresentationResult for the POST request containing Verifiable Presentation.

Parameter Description
presentation CredentialPresentation object containing filtered credentials and presentation request
void reportCredentialDeletion(final Claim claim);

Reports when a credential is deleted from the Wallet.

Parameter Description
claim Claim that was deleted from wallet
StorageManagerContract

PingOne Wallet Native SDK does not persist any information and relies on the app for maintaining the keys and credentials. Applications can implement the StorageManagerContract and provide an instance of the same to the PingOneWalletClient.

Methods
void saveApplicationInstance(final ApplicationInstance applicationInstance);

Saves the ApplicationInstance created for the wallet on initialization.

Parameter Description
applicationInstance ApplicationInstance for the wallet
ApplicationInstance getApplicationInstance();

Retrieves the saved ApplicationInstance that was created when the wallet was initialized for the first time, returns null if not found.

void saveClaim(final Claim claim);

Saves an issued credential to storage.

Parameter Description
claim Claim object
Claim getClaim(final String claimId);

Returns a Claim object matching the provided claimId if found, null otherwise.

Parameter Description
claimId String UUID for claim lookup
void deleteClaim(String claimId);

Deletes a claim from the storage if it exists.

Parameter Description
claimId String UUID for claim
List<Claim> getClaims();

Returns a list of all the claims from storage.

void saveString(final String str, final String key);

Saves a generic String to storage.

Parameter Description
str A String to be saved
key A String to be used to retrieve the saved string
String getString(final String key);

Retrieves the String previously saved for the given key, return null if not found.

Parameter Description
key A String previously used to save another string to the wallet
WalletCallbackHandler

Implement the WalletCallbackHandler to handle different credential events such as issuance, revocation, or presentation.

Methods
boolean handleCredentialIssuance(String issuer, String message, Challenge challenge, Claim claim, List<WalletException> errors);

Implement this method to handle newly issued credentials.

Returns true if the user accepts the credential and false if the user rejects the credential.

Parameter Description
issuer applicationInstanceID of the credential issuer
message Optional string message
challenge Optional challenge
claim Issued credential
errors List of any errors while processing or verifying the credential
boolean handleCredentialRevocation(String issuer, String message, Challenge challenge, ClaimReference claimReference, List<WalletException> errors);

Handles the revocation of a credential.

Returns true if the user accepts the revocation and false if the user rejects the revocation.

Parameter Description
issuer applicationInstanceID of the credential issuer
message Optional string message
challenge Optional challenge
claimReference ClaimReference for the revoked credential
errors List of any errors that occurred while verifying the revocation of the credential
void handleCredentialPresentation(String sender, String message, Challenge challenge, List<Share> claim, List<WalletException> errors);

This callback is triggered when another wallet shares a credential with the current application instance.

Parameter Description
sender applicationInstanceID for the sender of the credential presentation
message Optional string message
challenge Optional challenge
claim Presented or shared credentials
errors List of any errors that occurred while verifying the presented credentials
void handleCredentialRequest(PresentationRequest presentationRequest);

This callback is triggered when a presentation request is received by the wallet in the form of a QR code or a Universal link or via push notification.

Parameter Description
presentationRequest Request for presenting one or more credentials from the wallet
void handleError(WalletException error);

This callback is triggered when the SDK runs into any errors while processing the events/messages.

Parameter Description
error An error that can be used to describe an error by error code and error message

Class reference

ApplicationInstance

The ApplicationInstance class represents an instance of a compatible wallet app.

When the Wallet SDK is initialized for the first time, it creates a new application instance, registers the same with the credentials service, and saves the application identifier with cryptographic keys locally if a storage manager is provided. If an app does not provide an instance of StorageManagerContract, it is the app's responsibility to store the ApplicationInstance and provide the same instance back to the SDK on each initialization.

Property Description
applicationInstanceId The UUID for the compatible wallet.
jwks The JSON Web Key Set (JWKS) the application will use to sign the presentations and verify the credentials.
pushToken A string used to send push notifications to compatible wallet apps.
osType A string identifying the operating system of a compatible wallet app.
Method Description
toJson() Serializes the ApplicationInstance object to JSON.
Challenge

Use the Challenge class to correlate separate requests, or to expire a request after a certain time. For example, a new compatible session is created when a client creates a presentation exchange request for another wallet instance. When the receiving client sends the data back, it must send the same Challenge object. The recipient's SDK instance checks the expiration time passed in the challenge (if any), and terminates any further communication on the expired challenge.

Property Description
id The UUID for the Challenge object.
expiresAt An Instant object containing the UNIX timestamp.
Claim

A Claim represents a set of keys and values that are asserted to be correct by the issuer and their integrity can be verified using the ClaimReference information from the Claim object.

Property Description
claimData Salted claim data
otherFormats Formats that can be used to create objects, such as VerifiableCredential from the claim.
ClaimReference

The ClaimReference class is identical to the Claim class, with the exception of the claimData property. Use the ClaimReference class as a reference to expire a claim, without having to retain personally-identifiable information (PII).

Property Description
claimID A string containing the unique ID of the claim locator.
createDate An Instant object containing the timestamp for when the claim was created.
issuer A SaltedData object containing the claim issuer information.
subject A SaltedData object containing the claim subject information.
holder A SaltedData object containing the claim holder information.
referenceClaimID (Optional) A SaltedData object used to reference the claim that provided the original data.
dataJSON A string containing the claim information in JSON format.
dataSignature A string containing the signature for the claim.
dataHash A string containing a hash of the claim information.
CredentialMatcherResult

The CredenitalMatcherResult class contains a list of requestedKeys and the claims matching the filtering criteria from the presentation request.

Property Description
requestedKeys A list of keys that were requested
claims A list of Claims that contain the keys in requestedKeys
CredentialsPresentation

The CredentialsPresentation class represents the response to a PresentationRequest. It contains the claims matching the filtering criteria and picked by the user if more than one claim matches the criteria.

Property Description
presentationRequest The PresentationRequest object containing the filtering criteria and other information about the request such as requestor identifier, purpose, or session
Method Description
isEmpty() Returns a boolean that describes whether or not any Claims have been added to the Presentation
addClaimForKey(List<String> keys, Claim claim) Adds a claim to be shared for a List of corresponding requested keys
PresentationMatcherResult

The PresentationMatcherResult contains a list of credentials matching the filtering criteria for a presentation request.

Property Description
credentialMatcherResult A list of one or more CredentialMatcherResult that satisfy the requestedKeys of a credential request
PresentationRequest

The PresentationRequest includes the requested keys and information about the requestor.

Method Description
getRequestor() Returns a String of the applicationInstanceID of the requestor
getSessionID() Returns a String of the unique ID for the presentation session
getPurpose() Returns an Optional purpose String
getKeys() Returns a List object that contains the requested keys of a presentation request
getStringKeys() Returns a List object that contains the requested keys of a presentation request
PresentationResult

The PresentationResult class contains information on whether or not a presentation was successful.

Property Description
result Whether or not the the presentation was successful
details Optional Map<String, String> response body from presentation
error Exceptions if any occur while presenting credentials
RequestedKey

A RequestedKey contains the card type and card key requested for a singular key.

Property Description
rawKey A raw String that can be parsed to obtain the cardKey and cardType
cardKey The key requested in the rawKey
cardType The type of card requested in the rawKey
Share

The Share class encapsulates the data and the associated claim to verify the data. This object can be used by the verifier to validate the integrity of the information in the claim.

Property Description
keys A list of strings containing the requested keys
claim The Claim object to use for verification of the data.
WalletException

The WalletException class is the base class for all exceptions thrown by the PingOne Wallet Native SDK.

Method Description
getMessage() Returns the exception message.
getLocalizedMessage() Returns a localized version of the exception message, if available.
getCause() Returns the cause of the error

Integration Examples

This section explains how to integrate the wallet SDK for various use cases.

Integrate the SDK with no user interaction

The sample app is designed for the use case where the wallet SDK embedded in the application is paired with a PingOne environment by an explicit pairing request initiated by the PingOne environment. In that pairing process the PingOne environment admin sends an email to the user with a Universal Link to open the wallet application to complete the pairing.

This example illustrates how to integrate the digital wallet SDK with no user interaction (silent mode).

Initialization and wallet pairing

The illustrated workflow is followed to instantiate a wallet SDK that triggers a pairing request from the app. We must instantiate the wallet SDK and get the applicationInstanceId, which is a UUID that uniquely identifies the wallet SDK instance in the app. This applicationInstanceId is sent to a server trusted by the app. The server in turns calls a PingOne API to initiate and silently complete the wallet pairing.

workflow to silently integrate a wallet SDK with no user interaction

Steps 1 and 2 - Get the applicationInstanceId

The script below instantiates the wallet SDK to trigger a pairing request from the app. To instantiate the wallet SDK requires the applicationInstanceId, which is a UUID that uniquely identifies the wallet SDK instance in the app. This applicationInstanceId must be sent to a server trusted by the app. The server in turns calls a PingOne API to initiate and silently complete the wallet pairing.

This code requires that:

  • The application has already established the user to which the wallet belongs using existing authentication means

  • The application has a trusted service backend with which it can communicate.

Modified code from the PingOneWalletHelper.java file to get the applicationInstanceId from the instantiated SDK to enable backend pairing request.

    final PingOneWalletClient.Builder clientBuilder = new PingOneWalletClient.Builder();
    // set storage manager for easy management of encrypted storage
    if (storageManager != null) {
        clientBuilder.setStorageManager(storageManager);
    }
    // Using the builder pattern, once the clientBuilder is setup
    Completable.fromRunnable(() -> {
                final PingOneWalletClient client = clientBuilder.build();
                // You need the applicationInstanceId for the instantiated SDK
                final UUID applicationInstanceId = client.getApplicationInstance().getId();
                // Send this applicationInstanceId to a trusted service 
                // to pair the wallet with the "user" in the application.
            })
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe();
Step 3 - Request pairing

Send a request to pair userId from the application with the applicationInstanceId of the wallet SDK. This requires custom code and the details depend on the application. Ping Identity recommends that mobile applications do not directly call the PingOne OAuth APIs.

Step 4 - Create a user and pair the wallet

Call the PingOne APIs to create a user in your PingOne environment and pair a digital wallet.

Create user API

curl -X POST https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/users

Create digital wallet API

curl -X POST https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/users/49825b76-e1df-4cdc-b973-0c580f1cb049/digitalWallets

with a body similar to

Authorization: Bearer {{accessToken}}
Content-type: application/json

{
    "digitalWalletApplication": {
        "id": "{{digitalWalletApplicationID}}"
    },
    "applicationInstance": {
        "id": "{{applicationInstanceId}}"
    }
}
Step 5 - Pairing request

PingOne sends a pairing request to the wallet SDK embedded in the user app identified by the applicationInstanceId.

  1. The pairing request contains a “cryptographically secure random challenge string” that the wallet SDK signs and returns to the PingOne credentials service.

  2. PingOne credentials service sends an end-to-end encrypted message to the wallet SDK embedded in the user app. The PingOne Mailbox Service sends this message.

  3. The wallet SDK inside the app polls the PingOne Mailbox service every 3 seconds.

    Note: This is default behavior so there is no need to write additional code or make any modifications.

  4. When the app receives the encrypted message from the PingOne Credentials service, it decrypts the message and calls the registered message handler as defined in PingOneWalletHelper.java.

  5. Code below is modified from PingOneWalletHelper.java to ensure that no user interaction is required to complete the pairing process. This is a method in the WalletCallbackHandler interface implemented in the PingOneWalletHelper.java file.

  6. Modify the handlePairingRequest private method in the PingOneWalletHelper.java as follows. This ensures that no user interaction is required to complete the pairing process. This is a method in the WalletCallbackHandler interface which is implemented in the PingOneWalletHelper.java file.

private boolean handlePairingRequest(@NonNull final PresentationRequest presentationRequest) {

    if (!presentationRequest.isPairingRequest()) {
      return false;
    }
    BackgroundThreadHandler.singleBackgroundThreadHandler().post(new Runnable() {
      @Override
      public void run() {
          try {
              mPingOneWalletClient.pairWallet(presentationRequest, context, null);
          } catch (Exception e) {
              Log.e(TAG, "Failed to pair wallet", e);
          }
      }
    });
    return true;
}
Step 6 - Wallet pairs

The call to SDK method pairWallet (on line 7 in the modified code) responds to the pairing request and the app pairs with the user in the PingOne environment. This corresponds to steps 6a and 6b in the illustrated workflow.

Issuance and revocation

To implement the credential issuance and revocation workflow requires changes to the sample app code.

Modify the sample app code

The sample app uses popup messages (also called toasts) to alert the user that the wallet SDK has received a notification about an issued credential or a revoked credential. You must modify the code to mute the popup messages and in the sample app.

Step 6 - Modify the sample app code

The illustrated workflow requires modification of the PingOneWalletHelper.java file to not display a popup when a credential issuance request is received.

    @Override
    public boolean handleCredentialIssuance(String issuer, 
            String message, 
            Challenge challenge, 
            Claim claim, 
            List<WalletException> errors) {
        Log.i(TAG,"Credential received: Issuer: " + issuer + " message: " + message);
        mDataRepository.saveClaim(claim);
        return true;
    }
    
    @Override
    public boolean handleCredentialRevocation(String issuer, 
            String message, 
            Challenge challenge, 
            ClaimReference claimReference, 
            List<WalletException> errors) {
        Log.i(TAG,"Credential revoked: Issuer: " + issuer + " message: " + message);
        mDataRepository.saveRevokedClaimReference(claimReference);
        return true;
    }
Step 7 - Write to local storage

DataRepository defined in the DataRepositoryImpl.java has sample code to securely write to local application storage using the keys stored in the Android Key store.

You can always override the DataRepository implementation by writing your own classes that implement the DataRepositoryProtocol defined in the DataRepository.java file.

Complete process for issuance and revocation

credential issuance and revocation workflow

  1. An API orchestration layer or an administrator using the Admin Console makes changes to user attributes in the user directory.

  2. The PingOne Credentials Lifecycle Manager listens to directory change events and reviews the changes to determine if credentials must be issued or revoked based on credential issuance rules. If a credential needs to be issued or revoked the lifecycle manager makes entries in the staging area.

  3. The PingOne Credentials API is invoked periodically to process all staged changes. The PingOne Credentials API issues or revokes credentials as determined by the Lifecycle Manager.

  4. The credentials that are issued or revoked are bound to the wallet and are sent to the wallet using secure end-to-end encrypted messages using the Mailbox functionality of the PingOne Neo platform.

  5. The Wallet SDK embedded inside the app polls the Mailbox API to check for new messages. The mailbox API returns newly issued or recently revoked credential message as an encrypted message meant for the SDK to read.

  6. The Wallet SDK calls the app via the callback method handleCredentialIssuance or handleCredentialRevocation which the app has registered via the callback handler described earlier.

  7. The User App handles the callback by storing the issued credential to or deleting the revoked credential from storage using storage manager implementation.

Presentation

The sample app uses the PingOneWalletHelper class in PingOneWalletHelper.java to handle links, QR code content, and push notification requests for presentation of credentials.

These lines of code in the PingOneWalletHelper.java must be changed to allow for silent responses to presentation requests. Replace the handleCredentialRequest method with the code below.

@Override
public void handleCredentialRequest(PresentationRequest presentationRequest) {

    // Handle wallet pairing request
    if (handlePairingRequest(presentationRequest)) {
        return;
    }

    // Search for credentials matching the presentation request from the data repository
    final List<Claim> allClaims = mDataRepository.getAllClaims();
    final List<CredentialMatcherResult> credentialMatcherResults = mPingOneWalletClient
        .findMatchingCredentialsForRequest(presentationRequest, allClaims).getResult();

    boolean matchingCredentials = false;

    if (credentialMatcherResults != null) {
      for (CredentialMatcherResult credentialMatcherResult : credentialMatcherResults) {
        if (!credentialMatcherResult.getClaims().isEmpty()) {
          matchingCredentials = true;
          break;
        }
      }
    }

    if (!matchingCredentials) {
      // TODO: Application dependent custom handling
      // Handle no matching credential found in user's wallet
      return;
    }

    // TODO: Application dependent custom handling
    // handle logic to select the credential to present if
    // multiple matching credentials are found in the wallet.

    // handle presentation of the credentials (assuming that only
    // one credential in the wallet matched the criteria in the presentation
    // request)

    CredentialsPresentation credentialsPresentation = new CredentialsPresentation(presentationRequest);
    credentialsPresentation.addClaimForKeys(
        presentationRequest.getStringKeys(),
        credentialMatcherResults.get(0).getClaims().get(0));

    // POSTing the credential response back needs to be done on the background thread 
    BackgroundThreadHandler.singleBackgroundThreadHandler()
        .post(() -> mPingOneWalletClient.presentCredentials(credentialsPresentation)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(presentationResult -> {
              switch (presentationResult.getPresentationStatus().getStatus()) {
                case SUCCESS:
                  // Credential presentation successful
                  break;
                case FAILURE:
                  // Credential presentation failed
                  if (presentationResult.getError() != null) {
                    Log.e(TAG, "\"Error sharing information: ",
                        presentationResult.getError());
                  }
                  Log.e(TAG, String.format("Presentation failed. %s",
                      presentationResult.getDetails()));
                  break;
                case REQUIRES_ACTION:
                  // Handle the action sent by the verifier
                  // for the wallet as response to the presentation
              }
            }));
}

PingOne Protect Native SDKs

You can use the PingOne Signals (Protect) SDK to obtain information for additional risk-related variables and then pass this information on to the risk evaluation.

The data provided by the Signals SDK can be used with the PingOne Protect Integration Kit for PingFederate or PingOne Risk Integration Kit for PingFederate, with the PingOne Protect API, or as part of a flow designed with DaVinci.

PingOne Protect SDK for iOS

PingOne Signals (Protect) SDK for iOS (version 5.2.7)

Using the iOS version of the SDK involves the following steps:

  • Adding the SDK to your app using CocoaPods or Swift Package Manager
  • Importing the SDK module
  • Initializing the SDK
  • Getting the data for risk assessment

Adding the SDK to your app

Adding the SDK to your app using CocoaPods

If you’re new to CocoaPods, see the official documentation for information on how to create and use Podfiles.

Open your project’s Podfile and add the following to your app’s target:

pod 'PingOneSignals', '~> 5.2.7'

Run pod install from the command line:

pod install

Adding the SDK to your app using Swift Package Manager
  1. Select File > Add Packages… in Xcode’s menu bar.
  2. Search for the PingOne Signals SDK using the repo's URL: https://github.com/pingidentity/pingone-signals-sdk-ios
  3. Set the Dependency Rule to Branch with the value 'main' or select an exact version, and make sure that Add to Project is set to your project.
  4. Select Add Package.
  5. Verify that the package was downloaded in your project.

SDK initialization

Initialize the SDK. You'll typically do this in your app's application:didFinishLaunchingWithOptions: method, or any other entry point during your application launch. For example:

import PingOneSignals

let initParams = POInitParams()
initParams.envId = <envId> // optional
// If you are using the PingFed authentication API and version 1.3 of the Integration Kit, uncomment the following line to turn off the collection of behavioral data
// initParams.behavioralDataCollection = false
let pingOneSignals = PingOneSignals.initSDK(initParams: initParams)

pingOneSignals.setInitCallback { error in
    if let error = error {
        print("Init failed - \(error.localizedDescription)")
    } else {
        print("SDK Initialized")
    }
}

Optionally, set an event listener to get calls on successful or failed SDK initialization.

Getting the data for risk assessment

Get the data for risk assessment by adding a call to the SDK's getData method, for example:

import PingOneSignals

let pingOneSignals = PingOneSignals.sharedInstance()
pingOneSignals?.getData { data, error in
    if let data = data {
        print("data: \(data)")
    } else if let error = error {
        print("error getting data: \(error)")
    }
}

PingOne Protect SDK for Android

PingOne Signals (Protect) SDK for Android (version 5.1.2)

Using the Android version of the SDK involves the following steps:

  • Adding Maven Central repository
  • Adding the SDK to your app dependencies
  • Initializing the SDK
  • Getting the data for risk assessment

Adding the Maven Central repository

Add the mavenCentral repository to your root build.gradle file:

allprojects {
    repositories {
        mavenCentral()
        …
    }
}

Adding the SDK to your app dependencies

Add the following to your application-level build.gradle file:

implementation "com.pingidentity.signals:android-sdk:5.1.2"

SDK initialization

Extend the Application class and add the following in the onCreate method:

public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        // optional
        PingOneSignals.setInitCallback(new InitCallback() {
            @Override
            public void onError(@NonNull String message, @NonNull String code, @NonNull String id) {
                Log.i("PingOneSignals", "onError " + message + " code: " + code + " id: " + id);
            }

            @Override
            public void onInitialized() {
                Log.i("PingOneSignals ", "SDK Initialized");
            }
        });

      POInitParams initParams = new POInitParams();
      initParams.setEnvId(<envId>); // optional
      // If you are using the PingFed authentication API and version 1.3 of the Integration Kit, uncomment the following line to turn off the collection of behavioral data
      // initParams.setBehavioralDataCollection(false);
      PingOneSignals.init(this, initParams);
    }
}

Optionally, set an event listener to get calls on successful or failed SDK initialization.

Getting the data for risk assessment

Get the data for risk assessment by adding a call to the SDK's getData method, and pass as a parameter a class that implements the GetDataCallback interface, for example:

import com.pingidentity.signalssdk.sdk.GetDataCallback;
import com.pingidentity.signalssdk.sdk.SignalsCollection;

public class MyClass {

    public void callGetData() {
          PingOneSignals.getData(new GetDataCallback() {
                   @Override
                     public void onSuccess(@NonNull String data) {
                              Log.i("PingOneSignals ", "data:  " + data);
                      }

                    @Override
                    public void onFailure(@NonNull String reason) {
                             Log.i("PingOneSignals ", "onFailure reason: " + reason);
                    }
           });
    } 
}

PingOne Protect SDK for Web

PingOne Signals (Protect) SDK for Web

Version of the Signals SDK to use

When using the PingFederate Authentication API, use the version of the Signals SDK that supports the Risk/Protect Integration Kit that you installed in PingFederate:

  • For all versions of the PingOne Protect Integration Kit, use version 5.2.10 or later of the PingOne Signals SDK.
  • For PingOne Risk Integration Kit 1.3.1, use version 5.2.10 or later of the PingOne Signals SDK.
  • For PingOne Risk Integration Kit 1.3, use version 5.0.3 of the PingOne Signals SDK.

When integrating through the PingOne API, always use the latest version of the PingOne Signals SDK

Main steps

Using the web SDK involves the following steps:

  • Importing the necessary script
  • Initializing the SDK
  • Getting the data for risk assessment
Importing the script

Import the required script by including the following code segment in each relevant page.

<script
        src="https://apps.pingone.com/signals/web-sdk/5.2.10/signals-sdk.js"
        defer>
</script>
Initializing the SDK

Initialize the SDK by adding a listener for the PingOneSignalsReadyEvent event:

function onPingOneSignalsReady(callback) {
    if (window['_pingOneSignalsReady']) {
        callback();
    } else {
        document.addEventListener('PingOneSignalsReadyEvent', callback);
    }
}

Then, if you are using version 5.0.3 or earlier of the Signals SDK, use this code:

onPingOneSignalsReady(function () {
    _pingOneSignals.initSilent({
        envId : <envId>
    }).then(function () {
        console.log("PingOne Signals initialized successfully");
    }).catch(function (e) {
        console.error("SDK Init failed", e);
    });
});

If you are using version 5.2.1 or later of the Signals SDK, use this code:

onPingOneSignalsReady(function () {
    _pingOneSignals.init({
        // If you are using the PingFed authentication API and version 1.3 of the Integration Kit, uncomment the following line to turn off the collection of behavioral data
        // behavioralDataCollection: false
    }).then(function () {
        console.log("PingOne Signals initialized successfully");
    }).catch(function (e) {
        console.error("SDK Init failed", e);
    });
});

Getting the data for risk assessment

Get the data for risk assessment by adding a call to the SDK's getData method, for example:

_pingOneSignals.getData()
   .then(function (result) {
       console.log("get data completed: " + result)
   }).catch(function (e) {
       console.error('getData Error!', e);
});