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.
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
.
Request consent
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)
}
Request consent when credentials already exist for the device
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
.
Request consent to create new credentials
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
.