Two-factor authentication

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.

The Google Assistant uses dialog to issue the challenge, but if you use the 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.
Request
{
  "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
          }
        }]
      }]
    }
  }]
}
    
Response
{
  "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.
Request 1
{
  "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
          }
        }]
      }]
    }
  }]
}
Response 1
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [{
      "ids": ["123"],
      "status": "ERROR",
      "errorCode": "challengeNeeded",
      "challengeNeeded": {
        "type": "ackNeeded"
      }
    }]
  }
}
Request 2
{
  "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
          }
        }]
      }]
    }
  }]
}
Response 2
{
  "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, the 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.

  • TemperatureSetting
    • thermostatMode
    • thermostatTemperatureSetpoint
    • thermostatTemperatureSetpointHigh
    • thermostatTemperatureSetpointLow
  • OnOff
    • on
  • Scene

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, the 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.
Request 1
{
  "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"
          }
        }]
      }]
    }
  }]
}
Response 1
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [{
      "ids": ["123"],
      "status": "ERROR",
      "states": {
        "thermostatMode": "heat",
        "thermostatTemperatureSetpoint": 28
      },
      "errorCode": "challengeNeeded",
      "challengeNeeded": {
        "type": "ackNeeded"
      }
    }]
  }
}
Request 2
{
  "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
          }
        }]
      }]
    }
  }]
}
Response 2
{
  "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 the 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 Dim the living room light.
Google Assistant Can I have your security code?
Request
{
  "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
          }
        }]
      }]
    }
  }]
}
Response
{
  "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, the 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?
Request
{
  "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": {
            "pin": "333222"
          }
        }]
      }]
    }
  }]
}
Response
{
  "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 Dimming the living room light.
Request
{
  "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": {
            "pin": "333444"
          }
        }]
      }]
    }
  }]
}
Response
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [{
      "ids": ["123"],
      "status": "SUCCESS",
    }]
  }
}

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.