Secondary user verification lets you add second-factor security to voice commands. This lets you add additional security for certain actions such as turning off a security camera or opening a door. Secondary user verification is not tied to a specific device trait which allows you to decide when to have Google Assistant issue a challenge. For example, you can choose to issue a challenge for the OnOff trait for a security camera, but not issue a challenge for the OnOff trait for a light. You can also have Assistant issue challenges in certain situations for the same action. For example, you can request that Assistant issue a challenge request to open a door if an NFC keyfob is not in the proximity of that door, but not issue a challenge if the keyfob is present.
The Assistant can issue two types of challenges -
explicit acknowledgement or personal identification number (PIN). This adds a
challenge block to QUERY
and EXECUTE
intents sent from Assistant back to your action and accepts a challengeNeeded
error
response. Assistant then sends back the intent request to
your action with the challenge data in the challenge block. You can then
validate the challenge data to determine if the user gave the correct security
response.
Assistant uses dialog to issue the challenge, but if you use Assistant on non-voice surfaces, PIN and confirmations are done on-screen.
Supported device types
Secondary user verification is supported on all device types.
Supported device traits
Secondary user verification is supported for all device traits.
Supported challenge types
These are the supported secondary user verification challenge types:
- No challenge - A request and response that does not use a Secondary user verification challenge.
- ackNeeded - A secondary user verification that requires explicit acknowledgement (yes or no) and can also use trait states as response feedback. This challenge type is not recommended for security devices and traits.
- pinNeeded - A secondary user verification that requires a personal identification number (PIN), which is ideal for security devices and traits.
No challenge
This example shows a successful EXECUTE
request and response without a
challenge for turning on the lights.
User | Turn on the lights. |
Google Assistant | Ok, turning on 3 lights. |
{ "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf", "inputs": [{ "intent": "action.devices.EXECUTE", "payload": { "commands": [{ "devices": [{ "id": "123" }], "execution": [{ "command": "action.devices.commands.OnOff", "params": { "on": true } }] }] } }] }
{ "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf", "payload": { "commands": [{ "ids": ["123"], "status": "SUCCESS", "states": { "on": true, "online": true } }] } }
ackNeeded
A secondary user acknowledgement authentication that can use multiple states for a trait or a simple acknowledgement authentication.
There are the following types of ackNeeded
challenge types:
ackNeeded simple
This example shows a simple request and response with a ackNeeded
challenge
to dim a light and the confirmation to dim the light.
User | Dim the living room light. |
Google Assistant | Dimming the living room light. Are you sure? |
User | Yes. |
Google Assistant | Dimming the living room light. |
{ "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf", "inputs": [{ "intent": "action.devices.EXECUTE", "payload": { "commands": [{ "devices": [{ "id": "123" }], "execution": [{ "command": "action.devices.commands.BrightnessAbsolute", "params": { "brightness": 12 } }] }] } }] }
{ "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf", "payload": { "commands": [{ "ids": ["123"], "status": "ERROR", "errorCode": "challengeNeeded", "challengeNeeded": { "type": "ackNeeded" } }] } }
{ "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf", "inputs": [{ "intent": "action.devices.EXECUTE", "payload": { "commands": [{ "devices": [{ "id": "123" }], "execution": [{ "command": "action.devices.commands.BrightnessAbsolute", "params": { "brightness": 12 }, "challenge": { "ack": true } }] }] } }] }
{ "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf", "payload": { "commands": [{ "ids": ["123"], "status": "SUCCESS" }] } }
ackNeeded with trait states
A secondary user acknowledgement authentication that can use states for a
trait.
For example, if you are working with the
TemperatureSetting trait and both
thermostatMode
and thermostatTemperatureSetpoint
are set,
Assistant can ask Are you sure you want to set the heat
on the air conditioner to 28 degrees?
You can also include a state in a response to have Assistant perform a specific action based on a given request.
The following traits and states support ackNeeded
with trait states. A
listing of a specific trait indicates that all of its states are supported.
- ArmDisarm
currentArmLevel
currentStatusReport
- Fill
- LockUnlock
- OnOff
on
- OpenClose
- Scene
- TemperatureSetting
thermostatMode
thermostatTemperatureSetpoint
thermostatTemperatureSetpointHigh
thermostatTemperatureSetpointLow
This example shows a request and response with an ackNeeded
challenge that
uses a trait state. It changes the air conditioner mode to heat and sets the
temperature to 28 degrees. Then, Assistant asks the users
for the acknowledgement to turn on the heat and set the temperature to 28
degrees since a thermostatTemperatureSetpoint
of 28
is returned as a state
in the response.
User | Set AC mode to heat. |
Google Assistant | Are you sure you want to set the heat on the air conditioner to 28 degrees? |
User | Yes. |
Google Assistantnt | Setting the heat on the air conditioner to 28 degrees. |
{ "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf", "inputs": [{ "intent": "action.devices.EXECUTE", "payload": { "commands": [{ "devices": [{ "id": "123" }], "execution": [{ "command": "action.devices.commands.TemperatureSetting", "params": { "thermostatMode": "heat" } }] }] } }] }
{ "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf", "payload": { "commands": [{ "ids": ["123"], "status": "ERROR", "states": { "thermostatMode": "heat", "thermostatTemperatureSetpoint": 28 }, "errorCode": "challengeNeeded", "challengeNeeded": { "type": "ackNeeded" } }] } }
{ "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf", "inputs": [{ "intent": "action.devices.EXECUTE", "payload": { "commands": [{ "devices": [{ "id": "123" }], "execution": [{ "command": "action.devices.commands.TemperatureSetting", "params": { "thermostatMode": "heat" }, "challenge": { "ack": true } }] }] } }] }
{ "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf", "payload": { "commands": [{ "ids": ["123"], "status": "SUCCESS", "states": { "thermostatMode": "heat", "thermostatTemperatureSetpoint": 28 } }] } }
pinNeeded
The pinNeeded
challenge is recommended for security devices.
This example shows an initial request and response with a pinNeeded
challenge. The example returns a response with a pinNeeded
challenge, so
Assistant asks for the pin. At this point, the user can
provide an incorrect or valid pin.
Sample request and response for an incorrect or valid PIN:
User | Unlock the door. |
Google Assistant | Can I have your security code? |
{ "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf", "inputs": [{ "intent": "action.devices.EXECUTE", "payload": { "commands": [{ "devices": [{ "id": "123" }], "execution": [{ "command": "action.devices.commands.LockUnlock", "params": { "lock": false } }] }] } }] }
{ "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf", "payload": { "commands": [{ "ids": ["123"], "status": "ERROR", "errorCode": "challengeNeeded", "challengeNeeded": { "type": "pinNeeded" } }] } }
Incorrect PIN
This example shows the request and response with a challengeFailedPinNeeded
challenge. This challenge should be used after an initial pinNeeded
challenge
failed.
When a challengeFailedPinNeeded
type is returned,
Assistant asks for the security code again. If the user
performs too many failed attempts, you can return a tooManyFailedAttempts
error response. See Error responses.
User | 333222 |
Google Assistant | Sorry, the security code is incorrect. Can I have your security code? |
{ "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf", "inputs": [{ "intent": "action.devices.EXECUTE", "payload": { "commands": [{ "devices": [{ "id": "123" }], "execution": [{ "command": "action.devices.commands.LockUnlock", "params": { "lock": false }, "challenge": { "pin": "333222" } }] }] } }] }
{ "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf", "payload": { "commands": [{ "ids": ["123"], "status": "ERROR", "errorCode": "challengeNeeded", "challengeNeeded": { "type": "challengeFailedPinNeeded" } }] } }
Valid PIN
This example shows the request and response of a valid PIN.
User | 333444 |
Google Assistant | Unlocking the door. |
{ "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf", "inputs": [{ "intent": "action.devices.EXECUTE", "payload": { "commands": [{ "devices": [{ "id": "123" }], "execution": [{ "command": "action.devices.commands.LockUnlock", "params": { "lock": false }, "challenge": { "pin": "333444" } }] }] } }] }
{ "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf", "payload": { "commands": [{ "ids": ["123"], "status": "SUCCESS", "states": { "isLocked": false, "isJammed": false } }] } }
User | Dim the living room light. |
Google Assistant | Can I have your security code? |
{ "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf", "inputs": [{ "intent": "action.devices.EXECUTE", "payload": { "commands": [{ "devices": [{ "id": "123" }], "execution": [{ "command": "action.devices.commands.BrightnessAbsolute", "params": { "brightness": 12 } }] }] } }] }
{ "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf", "payload": { "commands": [{ "ids": ["123"], "status": "ERROR", "errorCode": "challengeNeeded", "challengeNeeded": { "type": "pinNeeded" } }] } }
Error responses
These are some error codes that can be returned with your responses:
- tooManyFailedAttempts - Sorry, too many failed attempts. Please go to your device's app to complete that action.
- pinIncorrect - Sorry, the security code is incorrect.
- userCancelled - Ok
See the full list of errors and exceptions.