---
title: Authenticate by using a WebAuthn device
description: After the user's mobile device has been registered in PingAM, the device can be used as an authenticator with its registered key pair through the WebAuthn Authentication node, which is returned as a WebAuthnAuthenticationCallback by the Ping (ForgeRock) SDK for iOS.
component: sdks
version: latest
page_id: sdks:sdks:use-cases/mobile-biometrics/ios/04-user-authentication
canonical_url: https://docs.pingidentity.com/sdks/latest/sdks/use-cases/mobile-biometrics/ios/04-user-authentication.html
llms_txt: https://docs.pingidentity.com/sdks/llms.txt
docs_for_agents: https://developer.pingidentity.com/build-with-ai/docs-for-agents.md
revdate: Wed, 14 Jun 2023 14:36:02 +0100
keywords: ["PingOne Advanced Identity Cloud", "PingAM", "Journeys", "Setup &amp; Configuration", "Source Code", "Use Case", "SDK"]
section_ids:
  select_credentials: Select credentials
---

# Authenticate by using a WebAuthn device

After the user's mobile device has been registered in PingAM, the device can be used as an authenticator with its registered key pair through the WebAuthn Authentication node, which is returned as a `WebAuthnAuthenticationCallback` by the Ping (ForgeRock) SDK for iOS.

If the device supports [Passkeys](https://developer.apple.com/passkeys/), the operating system displays passkeys that can be used:

![ios select passkey en](../../../../_images/ios/ios-select-passkey-en.png)Figure 1. Select a passkey to use for WebAuthn

Note that removing credentials stored on the client device does not remove the associated data from the server. You will need to register the device again after removing credentials from the client.

With `WebAuthnAuthenticationCallback`, you must implement the following protocol method to handle the authentication process:

```swift
public protocol PlatformAuthenticatorAuthenticationDelegate {
    func selectCredential(keyNames: [String], selectionCallback: @escaping WebAuthnCredentialsSelectionCallback)
}
```

As part of authentication process, the SDK provides the `WebAuthnAuthenticationCallback` for authenticating the device as a credential.

```swift
if let authenticationCallback = callback as? WebAuthnAuthenticationCallback {

    authenticationCallback.delegate = self

    // Note that the `Node` parameter in `.authenticate()` is an optional parameter.
    // If the node is provided, the SDK automatically returns the assertion
    // in the HiddenValueCallback.

    authenticationCallback.authenticate(
        node: node,
        window: UIApplication.shared.windows.first,
        preferImmediatelyAvailableCredentials: false,
        usePasskeysIfAvailable: true
    ) { (assertion) in
        // Authentication is successful
        // Submit the Node using Node.next()
    } onError: { (error) in
        // An error occurred during the authentication process
        // Submit the Node using Node.next()
    }
}
```

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

When passkeys are enabled, the device offers the ability to sign in using passkeys stored an a separate supported device, by first scanning a QR code.

![ios passkeys from another device en](../../../../_images/ios/ios-passkeys-from-another-device-en.png)Figure 2. Use a stored passkey from another device by first scanning the QR code

To prevent this behavior and only accept passkeys stored on the initial client device, set the `preferImmediatelyAvailableCredentials` parameter to `true`.

|   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | The `WebAuthnAuthenticationCallback.authenticate()` method has an optional parameter, `Node`.If the current node contains both `WebAuthnAuthenticationCallback` and `HiddenValueCallback` callbacks, and this node is passed as a parameter to the `WebAuthnAuthenticationCallback.authenticate()` method, then the SDK automatically returns the outcome of the authentication process for both success and failure into the designated `HiddenValueCallback`.If the node is not provided, the assertion or error outcome **must** be set manually. |

## Select credentials

The `func selectCredential()` method is invoked when `Username from device` is enabled in the WebAuthn Authentication node. This feature requires that `Username to device` is enabled in the WebAuthn Registration node as well. With these options enabled, the registered key pair is associated with the username, and the SDK can present a list of registered keys to the user to continue the authentication process without collecting a username.

|   |                                                                                                                                                                                                                                                                    |
| - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|   | The `keyName` is an array of strings constructed as `<User's displayName> <Registered Timestamp>`.You may alter the string value, and present the altered value to the user, but you **must** return the key name string as it was provided in the original array. |

```swift
func selectCredential(keyNames: [String], selectionCallback: @escaping WebAuthnCredentialsSelectionCallback) {
    let actionSheet = UIAlertController(title: "Select Credentials", message: nil, preferredStyle: .actionSheet)

    for keyName in keyNames {
        actionSheet.addAction(UIAlertAction(title: keyName, style: .default, handler: { (action) in
            selectionCallback(keyName)
        }))
    }

    actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (action) in
        selectionCallback(nil)
    }))

    guard let vc = self.viewController else {
        return
    }

    if actionSheet.popoverPresentationController != nil {
        actionSheet.popoverPresentationController?.sourceView = self
        actionSheet.popoverPresentationController?.sourceRect = self.bounds
    }

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