Two-factor authentication (2FA) 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. 2FA 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 Google Assistant issue challenges in certain situations for the same action. For example, you can request that Google 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 Google 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 Google
Assistant back to your action and accepts a challengeNeeded
error response. Google
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.
Google Assistant uses dialog to issue the challenge, but if you use Google Assistant on non-voice surfaces, PIN and confirmations are done on-screen.
Supported device types
Two-factor authentication is supported on all device types.
Supported device traits
Two-factor authentication is supported for all device traits.
Supported challenge types
These are the supported two-factor authentication challenge types:
- No challenge - A request and response that does not use a two-factor authentication challenge.
- ackNeeded - A two-factor authentication 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 two-factor authentication 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 two-factor 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 two-factor 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, Google 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 Google 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, Google Assistant asks the users for the acknowledgement
to turn on the heat and set the temperature to 28 degress 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 Assistant | 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 Google 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, Google 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:
challengeFailedNotSetup
- This action requires a security code but it hasn't been set up in your device's app.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.