To enable multi-factor authentication (MFA), the user resource must have an MFA method associated with its user ID. PingOne supports email, SMS, voice, TOTP authenticator application, and native application method types for use in an MFA flow. Multiple MFA methods can be associated with a user ID. MFA methods must be in the active state to be used in the multi-factor login flow.
With this API, MFA methods are called MFA devices. The devices endpoints provide operations to manage device resources associated with a specified user ID. You need the Identity Data Admin role to perform operations on device resources.
With the release of the device order feature (Jan 11, 2021), the active devices of most users now have an order (first…last). By default, the order is according to the device activation time (oldest…newest). Each subsequently activated device is appended to the end of the order list. The first device on the list is designated the default device. In most cases, the default device is automatically used for authentication; users no longer need to select a device.
There are a small number of users whose devices do not have a default order with this feature. If a user has more than one active device as of the release of the device order feature, the current active devices and subsequently activated devices have no order. The user therefore has no default device and must choose a device each time they authenticate. In this case, the order must be explicitly set (see Setting device order).
In most cases, the default device is automatically used for authentication. However, there are two exceptions:
The operation POST /environments/{{envID}}/users/{{userID}}/devices
with required header Content-type: application/vnd.pingidentity.devices.reorder+json
explicitly orders a user’s existing active devices according to the request body. The active device listed first becomes the default device.
After this operation explicitly sets device order, subsequently activated devices are appended to the end of the order list. You can use this operation to explicitly reorder active devices as many times as needed.
The operation GET /environments/{{envID}}/users/{{userID}}/devices
returns the list of active devices sorted in their order, with the default device listed first. Devices with a status of ACTIVATION_REQUIRED
are listed after the active devices, in no particular order. If devices have no order, GET /environments/{{envID}}/users/{{userID}}/devices
returns the list of devices in no particular order.
You can expand the GET /environments/{{envID}}/users/{{userID}}/devices
results with the expand=order
query parameter. The response is then expanded to contain an array of activated device IDs listed according to device order. If devices have no order, an empty array is returned.
If the default (first) device is deleted, the second active device on the order list becomes the default device.
The operation POST /environments/{{envID}}/users/{{userID}}/devices
with required header Content-type: application/vnd.pingidentity.devices.order.remove+json
removes the ordering on a user’s active devices. With the execution of this operation, the user no longer has a default device.
To send a custom device pairing notification when a new email, SMS or voice device is created, add the notification
property to the request body of POST /environments/{{envID}}/users/{{userID}}/devices
. The status
of the created device must be ACTIVATION_REQUIRED
.
{
“notification”: {
“template”: {
“locale”: “en”,
“variant”: “variant_B”
"variables": {
"sum": "1,000,000",
"currency": "USD",
"recipient": "Charlie Parker"
}
}
}
}
When the device is created, a request is executed to select the content for the notification. The notification template is device_pairing
. The deliveryMethod
is Email
, SMS
or Voice
, depending on the device created. The locale
, variant
, and all dynamic variables are defined in notification
.
For more information on content selection, see Runtime logic for content selection. For more information on dynamic varables, see Dynamic variables.
When the flow returns a NO_USABLE_DEVICES
error, and the user has devices that are temporarily unavailable (for example, the device is locked because of too many invalid OTP retries), the IDs of these devices are returned as part of the response.
In the flow response, the status
property returns FAILED
, and the error message includes the NO_USABLE_DEVICES
error code. The following samples show common error messages for a device failure with identified unavailableDevices
:
"status": "FAILED",
"error": {
"code": "NO_USABLE_DEVICES",
"message": "Couldn't find authenticating device for user: {{userID}}",
"unavailableDevices": [
{
"id": "edccc773-6f31-4d28-a8e1-0f427d9a9df8"
}
]
},
"status": "FAILED",
"error": {
"code": "NO_USABLE_DEVICES",
"message": "Daily limit of SMS authentication attempts has been exceeded",
"unavailableDevices": [
{
"id": "7ea99e29-6f8f-42be-af75-232588235e30"
}
]
},
Property | Type | Required? | Mutable? | Description |
---|---|---|---|---|
block.status |
String | Optional | Read-only | Whether the device is currently blocked. The possible values are BLOCKED and UNBLOCKED . |
block.blockedAt |
Date | Optional | Read-only | The date and time that the device was blocked. |
createdAt |
Date | N/A | Read-only | The date the device was created. |
environment.id |
String | N/A | Read-only | The environment ID associated with the device resource. |
id |
String | N/A | Read-only | The device resource’s unique identifier. |
lock.status |
String | N/A | Read-only | Indication of whether the device is currently locked out due to too many failed attempts. Values are LOCKED, UNLOCKED. |
lock.expiresAt |
Date | N/A | Read-only | For devices that are currently locked out, the date and time when the lock will expire. |
lock.reason |
String | N/A | Read-only | For devices that are currently locked out, provides the reason for the lock. Values are OTP or PUSH. OTP means that the user passed the defined limit on the number of unsuccessful OTP tries. PUSH means that the user passed the limit on the number of push notifications that can be declined or ignored within the defined time period. |
nickname |
String | Optional | Mutable | Identifies the authentication method in the UI. If defined, this string also appears on the authentication screens. This property has a limit of 100 characters. All characters are supported. An empty string is also supported to delete the value. Use Update Device Nickname to set this property. |
notification.policy.id |
String | Optional | Mutable | The policy ID for the notification. |
policy.id |
String | Optional | Mutable | The device authentication policy ID associated with the device resource. Specifying a device authentication policy ID applies that policy on the API, which determines the MFA methods and mobile applications that are allowed. This property is not returned with GET operations and cannot be used with PUT operations. Currently, if a policy ID is not specified on the request, the environment policy is used. However, this behavior is temporary; it is highly recommended that you specify a policy ID in the POST operation request body. |
status |
String | Required | Mutable | The device status. Options:
|
type |
String | Required | Mutable | The device type which must be provided. Options:
|
updatedAt |
Date | N/A | Read-only | The date the device was last updated. |
user.id |
String | Optional | Mutable | The ID of the user associated with the device. |
Devices whose type
is EMAIL
also have the following properties:
Property | Type | Required? | Mutable? | Description |
---|---|---|---|---|
email |
String | Required | Immutable | The email address, which is required during POST only if the device type is EMAIL . The email address must be valid. |
notification |
String | Optional | Immutable | Contains notification information. When this property is supplied during device creation, the information within is used to create a custom device pairing notification. For more information, see Custom device pairing notification with device creation. |
notification.template |
String | Optional | Immutable | An object that contains template parameters. |
notification.template.locale |
String | N/A | Read-only | The ISO language code (string) used for the device created notification. For example, en . |
notification.template.variant |
String | N/A | Read-only | The unique user-defined name for the content variant that contains the message text used for the notification. For more information on variants, see Creating custom contents. |
notification.template.variables |
Map[String, String] | Optional | Read-only | An object of name-value pairs that defines the dynamic variables used by the content variant. For more information on dynamic variables, see Dynamic variables. |
testMode |
Boolean | Optional | Mutable | To simplify automated testing of your applications, you can create dedicated testing devices. When you use the API to send authentication requests to such a device, the OTP is not sent to the actual device, but instead is returned as part of the body of the response. To specify that a device should serve as a testing device, set the value of testMode to true . If this parameter is not provided, the default value is false . For dedicated testing devices, the response to authentication requests includes the OTP value in the field test.otp . |
test.otp |
Integer | Optional | Read-only | If you use the testMode parameter to create a dedicated testing device, and status is set to ACTIVATION_REQUIRED in the request, the response will include test.otp , which is the passcode that you should use to activate the device. |
Devices whose type
is SMS
or VOICE
also have the following properties:
Property | Type | Required? | Mutable? | Description |
---|---|---|---|---|
phone |
String | Required | Immutable | The phone number, which is required only if the device type is SMS or VOICE. It must be a well-formed phone number consisting of a leading plus sign, 1 to 3-digit country code, and 4 to 14-digit phone number (e.g. +11235557890). |
extension |
String | Optional | Immutable | When creating a device of type VOICE , use extension for phone numbers that also have an extension. Can include digits, commas, #, and *. For nested extensions, separate the parts with a comma. |
notification |
String | Optional | Immutable | Contains notification information. When this property is supplied during device creation, the information within is used to create a custom device pairing notification. For more information, see Custom device pairing notification with device creation. |
notification.template |
String | Optional | Immutable | Contains template parameters. |
notification.template.locale |
String | Optional | Read-only | The ISO language code used for the device created notification. For example, en . |
notification.template.variant |
String | Optional | Read-only | The unique user-defined name for the content variant that contains the message text used for the notification. For more information on variants, see Creating custom contents. |
notification.template.variables |
Map[String, String] | Optional | Read-only | An object of name-value pairs that defines the dynamic variables used by the content variant. For more information on dynamic variables, see Dynamic variables. |
testMode |
Boolean | Optional | Mutable | To simplify automated testing of your applications, you can create dedicated testing devices. When you use the API to send authentication requests to such a device, the OTP is not sent to the actual device, but instead is returned as part of the body of the response. To specify that a device should serve as a testing device, set the value of testMode to true. If this parameter is not provided, the default value is false. For dedicated testing devices, the response to authentication requests includes the OTP value in the field test.otp . |
test.otp |
Integer | N/A | Read-only | If you use the testMode parameter to create a dedicated testing device, and status is set to ACTIVATION_REQUIRED in the request, the response will include test.otp , which is the passcode that you should use to activate the device. |
Devices whose type
is MOBILE
also have the following properties:
Property | Type | Required? | Mutable? | Description |
---|---|---|---|---|
apiVersion |
String | Required | Mutable | The native SDK API version. |
application.id |
String | Required | Immutable | The ID of the native application associated with this device. |
application.nativeName |
String | Optional | Mutable | The name of the application retrieved from the native app in runtime. |
application.pushSandbox |
Boolean | Optional | Immutable | Indicates if the native application uses production or sandbox push credentials (if the app was built and installed by a developer from Xcode, or installed ad hoc). Only relevant on iOS devices. |
application.version |
String | Optional | Mutable | The version of the application retrieved from the native app in runtime. |
deviceIntegrityState.advice |
String | N/A | Read-only | If available, Google advice for the deviceIntegrityState.reason . |
deviceIntegrityState.compromised |
String | N/A | Read-only | Indicates if the device’s integrity is compromised:
|
deviceIntegrityState.reason |
String | N/A | Read-only | Indicates the cause of the device’s current integrity state:
|
deviceIntegrityState.timestamp |
Date | N/A | Read-only | The date and time (UTC) of the latest integrity check for the device. |
integrityStateCurrent |
String | N/A | Read-only | Used for internal PingOne purposes. |
locale |
String | Optional | Mutable | The device’s locale. |
lockEnabled |
Boolean | Optional | Mutable | Whether the device is lock enabled. |
logs.expiresAt |
Date | N/A | Read-only | The date and time the request for expires, if the logs have not been sent yet. The value is set at 24 hours from the time of the request, and remains only while the logs.status is PENDING. logs.expiresAt is reset when the logs are sent, or when the system date reaches the request’s expiry time. |
logs.level |
String | Optional | Mutable | The level of log detail. Values:
|
logs.status |
String | Optional | Mutable | The returned status of a request for logs from a particular user device. Possible values:
|
manufacturer |
String | N/A | Read-only | The manufacturer of the device. |
model.marketingName |
String | Required | Read-only | The model’s marketing name. |
model.name |
String | Required | Read-only | The device’s model name. |
name |
String | N/A | Read-only | The device name given by the manufacturer. |
notificationProvider |
String | N/A | Read-only | The messaging system used for push notifications. For the possible values, see the type property in the MFA push credentials data model. |
os.type |
String | Required | Read-only | The device’s operating system. |
os.version |
String | Required | Mutable | The device’s operating system version. |
otpEnabled |
Boolean | N/A | Read-only | Whether OTP authentication is enabled for the device. |
pushEnabled |
Boolean | N/A | Read-only | Whether push is enabled for the device. |
pushToken |
String | Optional | Mutable | The push token for this application on this device (for internal use). |
rooted (Deprecated) |
Boolean | Required | Mutable | Use deviceIntegrityState instead. |
sdkVersion |
String | N/A | Read-only | The version of the MFA Mobile SDK used. |
Devices whose type
is TOTP
also have the following properties:
Property | Type | Required? | Mutable? | Description |
---|---|---|---|---|
secret |
String | N/A | Read-only | The unique secret key shared by the prover (token) and the verifier (authentication server). Only returned if the device’s activation status is ACTIVATION_REQUIRED. Both the secret and the keyURI values expire after 30 minutes. |
keyUri |
String | N/A | Read-only | The authenticator key URI (for example, otpauth://totp/abc@example.com?secret={secretValue} . Both the secret and the keyURI values expire after 30 minutes. |
Devices whose type
is FIDO2
also have the following properties:
Property | Type | Required? | Mutable? | Description |
---|---|---|---|---|
attestation |
String | N/A | Read-only | Specifies the public key and signed challenge used to complete registration and device activation. Devices with a status of ACTIVATION_REQUIRED are activated using a valid attestation and origin . The attestation is generated by the browser as a response to a specific user action, such as a fingerprint or clicks on the security key. This is a required property for FIDO2 device activation. |
attributes |
Object | N/A | Read-only | Object returned in the response for FIDO2 devices. |
attributes.isCrossPlatform |
Boolean | N/A | Read-only | Value is true if the device has ever been cross-platform. |
attributes.previousDeviceType |
String | N/A | Read-only | Included in the response for devices that were converted to FIDO2 from one of the deprecated device types. Value can be SECURITY_KEY or PLATFORM. |
backup |
Object | N/A | Read-only | Included in the response, contains the information regarding the backup eligibility of the device. |
backup.backupEligibility |
Boolean | N/A | Read-only | Whether the public key credential source is allowed to be backed up. |
backup.backupState |
Boolean | N/A | Read-only | Whether the public key credential source is currently backed up. |
displayName |
String | N/A | Read-only | The name displayed for the device in self-service registration and authentication windows. The name is taken from the relevant FIDO2 policy. Returned in the response only for request to read all FIDO2 devices. |
origin |
String | Required | Read-only | The originating server (for example, https://apps.pingone.com ). This property and the attestation property are used to activate FIDO2 devices that have a status of ACTIVATION_REQUIRED . This is a required property for FIDO2 device activation. |
publicKeyCredentialCreationOptions |
String | N/A | Read-only | A JSON serialization of the client data returned for registering a FIDO2 device with the webauthn navigator.credentials.create API. |
rp |
Object | Optional | Immutable | Information on the relying party. If not provided, the relying party ID is taken from the associated FIDO2 policy. |
rp.id |
String | Optional | Immutable | The ID of the relying party. The value should be a domain name, such as example.com (in lower-case characters). |
rp.name |
String | Optional | Immutable | The relying party’s human-readable display name (for example, acme ). |
Devices whose type
is PLATFORM
or SECURITY_KEY
also have the following properties:
Property | Type | Required? | Mutable? | Description |
---|---|---|---|---|
platform |
String | N/A | Read-only | The type of platform associated with this MFA device. Options are BIOMETRICS , WINDOWS , ANDROID , MAC , and IPHONE . This property applies only to devices in which the type property is set to PLATFORM . The type of platform is based on the User-Agent HTTP header of the request. If it is not possible to identify the platform, the value defaults to BIOMETRICS . |
publicKeyCredentialCreationOptions |
String | N/A | Read-only | A JSON serialization of the client data returned for registering a FIDO2 device with the webauthn navigator.credentials.create API. |
rp.id |
String | Required | Immutable | The relying party identifier, which is based on a host’s domain name but without a scheme or port (for example, acme.com or login.acme.com ). |
rp.name |
String | Required | Immutable | The relying party’s human-readable display name (for example, acme ). |
Property | Type | Required? | Mutable? | Description |
---|---|---|---|---|
order |
String[] | Required | Mutable | An array of objects that determines the explicit order of a user’s devices. The first device listed becomes the default device. This property is used as a body parameter to set the order of existing devices. |
To see the effects of these events for an API call, see the event types in the Audit Report, Audit Activities API, or Webhook stream.
Service | Event |
---|---|
users | DEVICE.CREATED |
users | DEVICE.UPDATED |
users | DEVICE.DELETED |
users | DEVICE.LOGS_RECEIVED |
users | DEVICE.REORDERED |
users | DEVICE.ACTIVATION_OTP_INVALID |
users | DEVICE.ACTIVATION_OTP_FAILED |
Code | Message |
---|---|
200 | Successful operation. |
400 | The request was invalid. |
400 | The request could not be completed. |
401 | You do not have access to this resource. |
403 | You do not have permissions or are not licensed to make this request. |
404 | The requested resource was not found. |
500 | Unexpected server error. |
You can filter GET /environments/{{envID}}/users/{{userID}}/devices
results by applying a SCIM filtering expression to the request URL. For large collections, a filtering expression appended to the query returns a targeted, more useful data set.
SCIM operators can be applied to the following attributes:
Collection | Attribute | Supported operators | Valid values |
---|---|---|---|
Devices | mobilePayload | eq (equals) | The signed JWT payload from the PingOne Mobile SDK. The payload contains information about a specific device, so the collection returned will always contain just a single device. |
Devices | status | eq (equals) | “ACTIVE”, “ACTIVATION_REQUIRED” |
Devices | type | eq (equals) | “SMS”, “VOICE”, “EMAIL”, “TOTP”, “MOBILE”, “PLATFORM”, “SECURITY_KEY” |
The logical operators and
and or
can also be used to combine filter statements.
For example, the following URL-encoded SCIM filter returns a list of SMS devices that require activation:
{{apiPath}}/environments/{{envID}}/users/{{userID}}/devices?filter=(status%20eq%20%22ACTIVATION_REQUIRED%22)%20and%20(type%20eq%20%22SMS%22)
This URL returns the device that matches the information contained in the specified payload from the PingOne Mobile SDK:
{{apiPath}}/environments/{{envID}}/users/{{userID}}/devices?filter=mobilePayload eq "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImRlNjJjZWYxLWQzNmQtNGMxMC05NDBkLTczNzQzZDk5NmYxZiJ9.eyJpc3MiOiIyNjdmNmEwMC1iZjg2LTQ4ODUtYjRjMi1mYjg5YzUzNzVlNGYiLCJmbnAiOiJiMDY4YjI2YTNhZTI2MTRmIiwiZHZjIjoiZGU2MmNlZjEtZDM2ZC00YzEwLTk0MGQtNzM3NDNkOTk2ZjFmIiwiZXhwIjoxNjg3OTQ4MTY1NTkwLCJqdGkiOiI1M2FlMmQ5YS04NmZiLTRmNGQtYjFlYS04M2MzMDQwNWU2OWEifQ.LxPIyD1mmdkXRLUmt2z3Fjeryev9b5oPgJGR2M5QxcuRR-tnd9nKNVB37CyS0W5Hj926W2U-MoSgpldvPM6-anpM4w4Ywa0a65_FB7PA0tzv-5LI4Pduat5fxhG78PTVRLXF_bwMe1hopUEFu6MBcKj13LIjz-rcrHIMoQV3OWUH5caX4mV3FXx1FPxoB-3Ighcc0-SotO4JZXvpZk2vsD-P2XJ1lFf-N2QhXnwfmBy7WthuPDCU8Rc6_a0Ca2cnv1bWDAKUKkndEsqm6S0_VFpLueCVxmHKdSy98owh86SAVhGtoZeHfOTB7WEbOb9aCAH_AinEh-JEhLKn_hMO3w"
You can expand GET /environments/{{envID}}/users/{{userID}}/devices
results with the expand=<value>
query parameter. The following value is supported.
Value | Description |
---|---|
order |
The response is expanded to contain an array of activated device IDs listed according to device order. This value is relevant only if the devices are ordered. If devices are not ordered, and empty array is returned. For more information, see Setting device order. |