Secondary User Verification

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.
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 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.
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 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.

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.
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 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?
Request
{
  "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
          }
        }]
      }]
    }
  }]
}
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, 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.LockUnlock",
          "params": {
            "lock": false
          },
          "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 Unlocking the door.
Request
{
  "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"
          }
        }]
      }]
    }
  }]
}
Response
{
  "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?
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"
      }
    }]
  }
}

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.