Ping SDKs

Register a WebAuthn device

To register a WebAuthn device on receipt of a WebAuthnRegistrationCallback from the server, use the register() method.

if let registrationCallback = callback as? WebAuthnRegistrationCallback {

    registrationCallback.delegate = self

    registrationCallback.register(
        node: node,
        window: UIApplication.shared.windows.first,
        deviceName: UIDevice.current.name,
        usePasskeysIfAvailable: false)
    { (attestation) in
        // Registration is successful
        // Submit the Node using Node.next()
    } onError: { (error) in
        // An error occurred during the registration process
        // Submit the Node using Node.next()
    }
}

Use the optional deviceName parameter to assign a name to the device to help the user identify it.

Set the usePasskeysIfAvailable parameter to true to enable passkeys on supported devices.

Enable Passkey support

The Ping SDK for iOS supports passkeys when the app is running on iOS 16 or later, or recent versions of macOS. For more information, refer to Passkeys in the Apple developer documentation.

To enable the use of passkeys during registration, you should: - In PingAM, enable the Username to device option in the WebAuthn Registration node in your authentication journeys. - In the SDK, set the usePasskeysIfAvailable parameter to true in the registrationCallback.register function. - Run your app on a passkey-enabled version of iOS or macOS.

When passkeys are enabled the user is asked to create a new passkey on their device and is required to perform biometric authentication to confirm. The device syncs the generated passkey to the user’s iCloud account for use on their supported devices.

ios create passkey touch id en
Figure 1. Creating a new passkey on iOS

Detect WebAuthn keys on passkey-enabled devices

The localKeyExistsAndPasskeysAreAvailable() method is invoked when the SDK detects an existing WebAuthn key on the device, and that the device supports passkeys.

// MARK: PlatformAuthenticatorAuthenticationDelegate
func localKeyExistsAndPasskeysAreAvailable() {
    // You can prompt the user to Register a new Key to use with Apple Passkeys. From then on, use the `register` and `authenticate` methods passing the `usePasskeysIfAvailable: true`.
}

You can use this delegate method to offer a journey that reregisters the device. Make sure you set usePasskeysIfAvailable to true.

You might need to ask the user for consent to perform certain actions depending on the configuration of the authentication journey.

The Ping SDK for iOS provides the PlatformAuthenticatorRegistrationDelegate protocol for requesting user consent:

public protocol PlatformAuthenticatorRegistrationDelegate {
    func excludeCredentialDescriptorConsent(consentCallback: @escaping WebAuthnUserConsentCallback)
    func createNewCredentialConsent(keyName: String, rpName: String, rpId: String?, userName: String, userDisplayName: String, consentCallback: @escaping WebAuthnUserConsentCallback)
}

The SDK invokes the excludeCredentialDescriptorConsent() method when Limit registrations is enabled in the WebAuthn Registration node.

This setting prevents a device from being registered if the server has a set of matching keys already stored for it.

During registration, the server returns a list of key descriptor identifiers that the SDK compares with its stored keys. If there is a match, you must get consent from the user to generate a new set of identifiers without explaining the reason, which is they already exist.

For more information, refer to section (6.3.2.3) in the WebAuthn specification.

The following example shows how to request consent:

func excludeCredentialDescriptorConsent(consentCallback: @escaping WebAuthnUserConsentCallback) {
    let alert = UIAlertController(title: "Create Credentials", message: nil, preferredStyle: .alert)
    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: { (_) in
        consentCallback(.reject)
    })
    let allowAction = UIAlertAction(title: "Allow", style: .default) { (_) in
        consentCallback(.allow)
    }
    alert.addAction(cancelAction)
    alert.addAction(allowAction)

    guard let vc = self.viewController else {
        return
    }

    DispatchQueue.main.async {
        viewController.present(alert, animated: true, completion: nil)
    }
}

If the user selects Allow, the SDK returns WebAuthnError.notAllowed. If the user selects Cancel, the SDK returns WebAuthnError.invalidState.

The SDK invokes the createNewCredentialConsent() method to obtain user consent prior to the SDK generating a key-pair.

In addition to the consent, the SDK might prompt for biometric authentication if the WebAuthn Registration node’s User verification requirement is set to PREFERRED or REQUIRED.

For more information, refer to section 6.3.2.6 in the WebAuthn specification.

The following example shows how to request consent:

func createNewCredentialConsent(
    keyName: String,
    rpName: String,
    rpId: String?,
    userName: String,
    userDisplayName: String,
    consentCallback: @escaping WebAuthnUserConsentCallback)
    {
        let alert = UIAlertController(
            title: "Create Credentials",
            message: "KeyName: \(keyName) | Relying Party Name: \(rpName) | User Name: \(userName)",
            preferredStyle: .alert)

        let cancelAction = UIAlertAction(
            title: "Cancel",
            style: .cancel,
            handler: { (_) in
                consentCallback(.reject)
        })

        let allowAction = UIAlertAction(
            title: "Allow",
            style: .default) { (_) in
                consentCallback(.allow)
        }
        alert.addAction(cancelAction)
        alert.addAction(allowAction)

        guard let vc = self.viewController else {
            return
        }

        DispatchQueue.main.async {
            viewController.present(alert, animated: true, completion: nil)
        }
    }

If the user selects Allow, the SDK creates the key pair and performs the attestation. If the user selects Cancel, the SDK returns WebAuthnError.cancelled.