# Account linking with Google Sign-In

Google Sign-In for the Assistant provides the simplest and easiest user experience
to users and developers both for account linking and account creation. Your Action
can request access to your user's Google profile during a conversation,
including the user's name, email address, and profile picture.

The profile information can be used to create a personalized user experience
in your Action. If you have apps on other platforms and they use Google Sign-In,
you can also find and link to an existing user's account, create a new account,
and establish a direct channel of communication to the user.

To perform account linking with Google Sign-In, you ask the user to give consent
to access their Google profile. You then use the information in their profile, for
example their email address, to identify the user in your system.

## Implement Google Sign-In account linking

Follow the steps in the following sections to add Google Sign-In account linking to your
Action.

> [!NOTE]
> **Note:** If you're implementing account linking to handle financial information, note that additional policies may apply to your Action. It can take us up to six weeks to review an Action with account linking for financial information, so factor that time in when planning your release schedule. To ease the review process, make sure you comply with the [financial services policies](https://developers.google.com/assistant/console/policies/general-policies#financial_services) before submitting your Action for review.

### Configure the project

To configure your project to use Google Sign-In account linking, follow these steps:

1. Open the Actions Console and select a project.
2. Click the **Develop** tab and choose **Account linking**.
3. Enable the switch next to **Account linking**.
4. In the **Account creation** section, select **Yes**.
5. In **Linking type** , select **Google Sign In**.

   ![](https://developers.google.com/static/assistant/identity/images/configure_linking_type_gsi.png)
6. Open **Client Information** and take note of the value of **Client ID issued by Google to your Actions**.

7. Click **Save**.

### Design the voice user interface for the authentication flow

> [!WARNING]
> **Warning:** Don't give users a required account linking prompt at the start of the conversation with your Action. Instead, give unauthenticated users a guest flow to show how your Action works, and then only ask for account linking if it's necessary to proceed. If users are leaving the Action consistently because of account linking issues, Google will not actively promote the Action, which may decrease the Action's user traffic.
>
>
> [!NOTE]
> **Note:** You must use [Actions Builder](https://developers.google.com/assistant/conversational/build#actions_builder) to build an Action that implements account linking.

#### Check if the user is verified and start the account linking flow

1. Open your Actions Builder project in the [Actions Console](https://console.actions.google.com).
2. Create a new scene to start account linking in your Action:
   1. Click **Scenes**.
   2. Click the **add** (+) icon to add a new scene.
3. In the newly created scene, click the add icon for **Conditions**.
4. Add a condition that checks if the user associated with the conversation is a a verified user. If the check fails, your Action can't perform account linking during the conversation, and should fall back to providing access to functionality that doesn't require account linking.
   1. In the `Enter new expression` field under **Condition** , enter the following logic: `user.verificationStatus != "VERIFIED"`
   2. Under **Transition**, select a scene that doesn't require account linking or a scene that is the entry point to guest-only functionality.

![](https://developers.google.com/static/assistant/identity/images/ab_vui_verified_condition.png)

1. Click the add icon for **Conditions**.
2. Add a condition to trigger an account linking flow if the user doesn't have an associated identity.
   1. In the `Enter new expression` field under **Condition** , enter the following logic:: `user.verificationStatus == "VERIFIED"`
   2. Under **Transition** , select the **Account Linking** system scene.
   3. Click **Save**.

![](https://developers.google.com/static/assistant/identity/images/ab_vui_al_transition.png)

After saving, a new account linking system scene called `<SceneName>_AccountLinking`
is added to your project.

#### Customize the account linking scene

1. Under **Scenes**, select the account linking system scene.
2. Click **Send prompt** and add a short sentence to describe to the user why the Action needs to access their identity (for example "To save your preferences").
3. Click **Save**.

![](https://developers.google.com/static/assistant/identity/images/ab_vui_context.png)

1. Under **Conditions** , click **If user successfully completes account linking**.
2. Configure how the flow should proceed if the user agrees to link their account. For example, call the webhook to process any custom business logic required and transition back to the originating scene.
3. Click **Save**.

![](https://developers.google.com/static/assistant/identity/images/ab_vui_user_yes.png)

1. Under **Conditions** , click **If user cancels or dismisses account linking**.
2. Configure how the flow should proceed if the user doesn't agree to link their account. For example, send an acknowledging message and redirect to scenes that provide functionality that doesn't require account linking.
3. Click **Save**.

![](https://developers.google.com/static/assistant/identity/images/ab_vui_user_no.png)

1. Under **Conditions** , click **If system or network error occurs**.
2. Configure how the flow should proceed if the account linking flow can't be completed because of system or network errors. For example, send an acknowledging message and redirect to scenes that provide functionality that doesn't require account linking.
3. Click **Save**.

### Access profile information in your backend

After the user authorizes your action to access their Google profile, you will receive
a Google ID token that contains the user's Google profile information in every subsequent
request to your action.

To access the user's profile information, you need to first validate and decode the token
by doing the following:

1. Use a [JWT-decoding library](https://jwt.io/) for your language to decode the token, and use Google's public keys (available in [JWK](https://www.googleapis.com/oauth2/v3/certs) or [PEM](https://www.googleapis.com/oauth2/v1/certs) format) to verify the token's signature.
2. Verify that the token's issuer (`iss` field in the decoded token) is `https://accounts.google.com` and that the audience (`aud` field in the decoded token) is the value of **Client ID issued by Google to your Actions**, which is assigned to your project in the Actions console.

The following is an example of a decoded token:

```
{
  "sub": 1234567890,        // The unique ID of the user's Google Account
  "iss": "https://accounts.google.com",        // The token's issuer
  "aud": "123-abc.apps.googleusercontent.com", // Client ID assigned to your Actions project
  "iat": 233366400,         // Unix timestamp of the token's creation time
  "exp": 233370000,         // Unix timestamp of the token's expiration time
  "name": "Jan Jansen",
  "given_name": "Jan",
  "family_name": "Jansen",
  "email": "jan@gmail.com", // If present, the user's email address
  "locale": "en_US"
}
```

If you use the [Actions on Google Fulfillment library for Node.js](https://github.com/actions-on-google/assistant-conversation-nodejs),
it takes care of validating and decoding the token for you, and gives you access to
the profile content, as shown in the following code snippets.

```
...
const app = conversation({
  // REPLACE THE PLACEHOLDER WITH THE CLIENT_ID OF YOUR ACTIONS PROJECT
  clientId: CLIENT_ID,
});
...
// Invoked on successful completion of account linking flow, check if we need to
// create a Firebase user.
app.handle('linkAccount', async conv => {
  let payload = conv.headers.authorization;
  if (payload) {
  // Get UID for Firebase auth user using the email of the user
    const email = payload.email;
    if (!conv.user.params.uid && email) {
      try {
        conv.user.params.uid = (await auth.getUserByEmail(email)).uid;
      } catch (e) {
        if (e.code !== 'auth/user-not-found') {
          throw e;
        }
        // If the user is not found, create a new Firebase auth user
        // using the email obtained from Google Assistant
        conv.user.params.uid = (await auth.createUser({email})).uid;
      }
    }
  }
});
```

### Handle data access requests

To handle data access request, just verify that the user asserted by the Google ID
token is already present in your database. The following snippet of code shows
an example of how to check if orders for a user already exist in a Firestore database:

```
...
app.handle('Place_Order', async conv => {
  const order = conv.session.params.order;
  const userDoc = dbs.user.doc(conv.user.params.uid);
  const orderHistory = userDoc.collection("orderHistory");
  if (orderHistory) {
    // Order history exists, so the user already placed an order.
    // Update counter for order type.
    await orderHistory.doc(order).update({ count: admin.firestore.FieldValue.increment(1)});
  } else {
    // First order they place
    await orderHistory.doc(order).set({ option: order, count: 1});
    options.forEach(opt => {
      if (opt != order) {
        orderHistory.doc(opt).set({ option: opt, count: 0});
      }
    });
  }
  return conv.add(`Your ${order} has been placed. ` +
      'Thanks for using Boba Bonanza, see you soon!');
});
```

<br />