Set up registered device self service
The Ping SDKs can retrieve a list of the devices your users register to their accounts. Users can then manage their own devices, for example delete or rename them.
PingOne Advanced Identity Cloud and PingAM support registration of many different device types to support your multi-factor authentication journeys:
- OATH devices
-
The registered device generates a one-time passcode that your users enter into the authentication journey.
Register OATH devices using the OATH Registration node.
To learn more about implementation, refer to Implement MFA using OATH one-time passwords.
- PUSH devices
-
The registered device receives a PUSH notification from the server that the user must approve to continue their authentication journey.
Register PUSH devices using the Push Registration node.
To learn more about implementation, refer to Implement MFA using push notifications.
- WebAuthn devices
-
The registered device acts as an authenticator and uses public-key cryptography to securely sign an assertion from the server.
Register WebAuthn devices using the WebAuthn Registration node.
To learn more about implementation, refer to Implement mobile biometrics and Implement web biometrics.
- Device binding
-
The registered device generates a key pair and a key ID. The Ping SDKs send the public key and key ID to PingOne Advanced Identity Cloud or PingAM for storage in the user’s profile.
Bind devices using the Device Binding node.
To learn more about implementation, refer to Bind and verify user devices.
- Device profiling
-
The Ping SDKs collect specific data about the registered device to create a profile that helps to identify it during authentication journeys.
Profile devices using the Device Profile Collector node.
To learn more about implementation, refer to Device profile client configuration.
The Ping SDKs provide utility methods for managing each type of registered device:
Type | Get | Update | Delete |
---|---|---|---|
OATH |
|
Not supported |
|
PUSH |
|
Not supported |
|
WebAuthn |
|
|
|
Device binding |
|
|
|
Device profiles |
|
|
|
Getting lists of devices
To get a list of devices you must have an active session for the user. The Ping SDKs include the session token when making calls to the device management endpoints.
Session tokens often have a short duration and expire after 5 minutes. If the client does not have an active session token you should trigger an authentication journey to obtain a new session token before attempting to manage registered devices.
Device management is not available when using OIDC login, as the Ping SDKs do not have direct access to the session token, which remains in the embedded browser. |
Examples
-
Android
-
iOS
-
JavaScript
-
Import and initialize
deviceClient
:import org.forgerock.android.auth.selfservice.Device private val deviceClient = DeviceClient()
-
Call the
get()
method to retrieve lists of devices:"Oath" -> deviceClient.oath.get() "Push" -> deviceClient.push.get() "WebAuthn" -> deviceClient.webAuthn.get() "Binding" -> deviceClient.bound.get() "Profile" -> deviceClient.profile.get()
-
Import
FRAuth
and initializedeviceClient
:import FRAuth let deviceClient = DeviceClient()
-
Call the
get()
method to retrieve lists of devices:let oathDevices = try await deviceClient.oath.get() let pushDevices = try await deviceClient.push.get() let webAuthnDevices = try await deviceClient.webAuthn.get() let bindingDevices = try await deviceClient.bound.get() let profileDevices = try await deviceClient.profile.get()
-
Import the
deviceClient
module from the Ping SDK for JavaScript, and provide aConfigOptions
object to initialize device self-service functionality:import { deviceClient } from '@forgerock/javascript-sdk/device-client'; import { type ConfigOptions } from '@forgerock/javascript-sdk'; const config: ConfigOptions = { serverConfig: { baseUrl: 'https://openam-forgerock-sdks.forgeblocks.com/am', }, realmPath: 'alpha', }; const deviceClient = deviceClient(config);
-
Call the
get()
method, with optional query, to retrieve a list of devices.For example, the following code gets a list of all the user’s OATH devices:
const oathQuery: RetrieveOathQuery = { /* your query parameters */ }; deviceClient.oath .get(oathQuery) .then((response) => { console.log('OATH Devices:', response); }) .catch((error) => { console.error('Error fetching OATH devices:', error); });
Renaming a device
You can rename some types of registered device, with the following caveats:
-
You can only rename these device types:
-
Bound devices
-
Device profiles
-
WebAuthn devices
-
-
The authentication journey that provided the users' session must fulfil one or more of the following criteria:
-
Used same multi-factor authentication method as the device you want to rename.
For example, to rename a WebAuthn device the authentication journey that created the session must also authenticate using a WebAuthn device.
Or:
-
Used the Enable Device Management node that alters the Device Check Enforcement Strategy.
-
Examples
-
Android
-
iOS
-
JavaScript
fun update(device: Device) {
viewModelScope.launch {
try {
when (device) {
is WebAuthnDevice -> deviceClient.webAuthn.update(device)
is BoundDevice -> deviceClient.bound.update(device)
is ProfileDevice -> deviceClient.profile.update(device)
else -> throw IllegalArgumentException("Unsupported Device Type")
}
fetch(selectedType)
} catch (e: Exception) {
yield()
state.update { it.copy(devices = emptyList(), throwable = e) }
}
}
}
let alert = UIAlertController(title: "Edit Device Name",
message: device.id,
preferredStyle: .alert)
alert.addTextField { textField in
textField.text = device.deviceName
}
let okAction = UIAlertAction(title: "Submit", style: .default) { [unowned alert] _ in
let updateDeviceName = alert.textFields![0].text!
Task {
do {
if var device = device as? BoundDevice {
device.deviceName = updateDeviceName
try await self.deviceClient.bound.update(device)
} else if var device = device as? ProfileDevice {
device.deviceName = updateDeviceName
try await self.deviceClient.profile.update(device)
} else if var device = device as? WebAuthnDevice {
device.deviceName = updateDeviceName
try await self.deviceClient.webAuthn.update(device)
}
} catch AuthApiError.apiFailureWithMessage(let reason, let message, let code, _) {
self.showAlert(title: reason, message: message + " - \(String(describing: code ?? 0))")
}
self.reloadAllDevices()
}
}
const updateWebAuthnQuery: WebAuthnQueryWithUUID & WebAuthnBody = {
/* your update query */
};
deviceClient.webAuthn
.update(updateWebAuthnQuery)
.then((response) => {
console.log('Updated WebAuthn Device:', response);
})
.catch((error) => {
console.error('Error updating WebAuthn device:', error);
});
Deleting a device
You can delete or deregister a device, with the following caveats:
-
The authentication journey that provided the users' session must fulfil one or more of the following criteria:
-
Used same multi-factor authentication method as the device you want to delete.
For example, to delete a WebAuthn device the authentication journey that created the session must also authenticate using a WebAuthn device.
Or:
-
Used the Enable Device Management node that alters the Device Check Enforcement Strategy.
-
Examples
-
Android
-
iOS
-
JavaScript
fun delete(device: Device) {
viewModelScope.launch {
try {
when (device) {
is OathDevice -> deviceClient.oath.delete(device)
is PushDevice -> deviceClient.push.delete(device)
is WebAuthnDevice -> deviceClient.webAuthn.delete(device)
is BoundDevice -> deviceClient.bound.delete(device)
is ProfileDevice -> deviceClient.profile.delete(device)
else -> throw IllegalArgumentException("Unsupported Device Type")
}
fetch(selectedType)
} catch (e: Exception) {
yield()
state.update { it.copy(devices = emptyList(), throwable = e) }
}
}
}
let delete = UIContextualAction(style: .destructive, title: "Delete") { (action, view, completion) in
let alert = UIAlertController(title: "Delete Device", message: "Are you sure you want to delete device \"\(device.deviceName)\"?", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Yes", style: .destructive, handler: { (alert: UIAlertAction!) in
Task {
do {
if let device = device as? BoundDevice {
try await self.deviceClient.bound.delete(device)
} else if let device = device as? ProfileDevice {
try await self.deviceClient.profile.delete(device)
} else if let device = device as? WebAuthnDevice {
try await self.deviceClient.webAuthn.delete(device)
} else if let device = device as? OathDevice {
try await self.deviceClient.oath.delete(device)
} else if let device = device as? PushDevice {
try await self.deviceClient.push.delete(device)
}
} catch AuthApiError.apiFailureWithMessage(let reason, let message, let code, _) {
self.showAlert(title: reason, message: message + " - \(String(describing: code ?? 0))")
}
self.reloadAllDevices()
}
completion(true)
}))
const deleteWebAuthnQuery: WebAuthnQueryWithUUID & WebAuthnBody = {
/* your delete query */
};
deviceClient.webauthn
.delete(deleteWebAuthnQuery)
.then((response) => {
console.log('Deleted WebAuthn Device:', response);
})
.catch((error) => {
console.error('Error deleting WebAuthn device:', error);
});