Securing and scaling chatbots for production (part 2)

This article is part 2 of a multi-part series of tutorials that show you how to build, secure, and scale a chatbot by using Dialogflow on Google Cloud.

This series consists of these parts:

In the first tutorial, you implemented a chatbot by using Dialogflow. In this second tutorial, you build a secure webhook so that only authorized callers can access your chatbot's fulfillment backend. You also port the webhook to App Engine so that it is "always on" and scalable. Lastly, you build a custom chatbot UI that you can secure, brand, and deploy to a customer's environment.

This tutorial assumes that you are familiar with Cloud Shell, Datastore, Datalab, the Cloud Natural Language API API, and Linux. This tutorial also assumes that you completed part 1 of this series and built a chatbot.

Objectives

  • Secure a Python API for Dialogflow.
  • Convert Datalab code into Python code to deploy to App Engine.
  • Connect a custom chatbot user interface to the Dialogflow API.
  • Integrate with Google Assistant.

Costs

This tutorial uses the following billable components of Google Cloud:

To generate a cost estimate based on your projected usage, use the pricing calculator. New Google Cloud users might be eligible for a free trial.

When you finish this tutorial, you can avoid continued billing by deleting the resources you created. For more information, see Cleaning up.

Before you begin

  1. Complete part 1 of the series.
  2. Create a second Google Cloud project.

    GO TO THE MANAGE RESOURCES PAGE

Securing the webhook

In this section, you add HTTP basic authentication to your webhook to prevent unauthorized access to your chatbot. This ensures that unauthorized callers cannot call your webhook. You use the Datalab instance from the previous tutorial.

  1. In Datalab, go to datalab > notebooks > webhook.ipynb.
  2. In the import block of Python code, add the following line under the Flask import line (from flask import Flask, request, jsonify, make_response) to import the @wraps decorator:

    from functools import wraps
    
  3. In the third cell of the notebook, insert the following code in between the app = Flask(__name__) line and the handle() method, replace: @app.route('/webhook/', methods=['POST']). Replace [USERNAME] and [PASSWORD] with credentials you want to use.

    def requires_auth(f):
        @wraps(f)
        def decorated(*args, **kwards):
            auth = request.authorization
            if not auth or not check_auth(auth.username, auth.password):
                return authenticate()
            return f(*args, **kwards)
        return decorated
    <br>
    def check_auth(username, password):
        """This function is called to check if a username /
        password combination is valid.
        """       uname="[USERNAME]"
        pwd="[PASSWORD]"
           return username == uname and password == pwd
    <br>
    def authenticate():
        """Sends a 401 response that enables basic auth"""
        logging.info("inside authenticate")
        return Response(
        'Could not verify your access level for that URL.\n'
        'You have to login with proper credentials', 401,
        {'WWW-Authenticate': 'Basic realm="Login Required"'})
    

    The following methods implement Flask's security framework for HTTP basic authentication:

    • The requires_auth() method requires authentication to access the app.
    • The check_auth() method validates the submitted username and password. Make a note of your [USERNAME] and [PASSWORD] as they are used later in this tutorial.
    • The authenticate() method sends a 401 response if authentication fails.
  4. Add the @requires_auth decorator in the line before the def handle() method declaration.

  5. To run your webhook again, click the Down arrow next to Clear, and then click Clear all Cells. To stop your old ngrok process, under Reset Session, click Interrupt Execution. Run the second and third notebook cells again. Enter SHIFT + ENTER in both cells.

    The following output at the bottom of the notebook indicates that the secure API is running on port 5000 of your local VM.

    *  Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
    
  6. In Datalab, go to Datalab > Notebooks > ngrok.ipynb.

  7. Click the Down arrow next to Clear, and then click Clear all Cells. To stop your old ngrok process, under Reset Session, click Interrupt Execution.

  8. Run the third cell, the cell with the ngrok command in it. Enter SHIFT + ENTER.

    The following output is displayed at the bottom of the notebook:

    Output at the bottom of the notebook

  9. Copy the https://[NAME].ngrok.io URL from the output. This is your webhook's public URL where [NAME] represents a name randomly generated by ngrok.

  10. In the Dialogflow Console, click Fulfillment. In the URL field, enter your ngrok URL and then add /webhook/. For example, https://bc123456.ngrok.io/webhook/.

  11. In the Basic Auth section, enter the [USERNAME] and [Password] that you added to the webhook.ipynb notebook.

  12. Click Save.

  13. Test your chatbot with the Dialogflow test console. Your calls to your webhook are now encrypted and authenticated.

Porting the webhook to App Engine

The webhook in Datalab is only available for the chatbot to call while the Datalab VM is running. This is fine for development and testing, but for production environments you want your webhook to always be on and able to scale if your chatbot is popular. You also want your webhook to be available over HTTPS, to protect your data and credentials in transit.

In this section, you deploy the Python code you started in Datalab to App Engine, which provides a scalable, secure, and always-on presence for your webhook.

  1. In Datalab, go to Datalab > Notebooks > webhook.ipynb.
  2. In the Notebook list, click Convert to Python.

    This opens a new tab with the contents of the webhook notebook converted to a single Python file that you can use to deploy to App Engine.

  3. In the Cloud Console, go to a Cloud Shell terminal window from part 1 of this series. To open a new tab, click + Add Cloud Shell Session. Change into the webhook subdirectory you cloned from GitHub.

    git clone https://github.com/GoogleCloudPlatform/dialogflow-chatbot.git
    cd dialogflow-chatbot/webhook
    
  4. In Cloud Shell, install all required libraries into a lib directory that you use to deploy your app to App Engine:

    pip install -t lib -r requirements.txt
    
  5. Deploy your Dialogflow webhook service to App Engine:

    gcloud app deploy
    
  6. When prompted to continue, enter Y.

  7. Retrieve the URL for the deployed app:

    gcloud app browse
    

    Make a note of the Dialogflow service URL as it is needed later. It is in the format of https://[PROJECT_ID].appspot.com, where [PROJECT_ID] represents your Google Cloud project ID.

  8. In the Dialogflow console, click Fulfillment. In the field, enter https://[PROJECT_ID].appspot.com/webhook/.

  9. Enter the [USERNAME] and [PASSWORD] that you previously configured.

  10. Save your webhook configuration, by clicking Save.

  11. Test your chatbot.

Building a custom chatbot user interface

The web demo integration built in to Dialogflow is fine for demonstrating what a chatbot user interface would look like, but it is only intended for demo purposes. You cannot customize the branding, and more importantly, you cannot secure it. Anyone who has your web demo URL can interact with the user interface.

You build your own user interface to run in your second Google Cloud project. A second project is required to implement user-based security because you want that security to apply only to the UI project and not to the first project with the chatbot.

To implement user-based security, your webhook needs to continue to run as a backend service, without user-based authentication, while your UI runs as a user-facing app, with user-based authentication.

Initialize App Engine for your second Google Cloud project

In this section, you initialize App Engine for your second project. All remaining steps in this tutorial are performed in this second project.

  1. In the Cloud Console, go to the Manage Resources page.

    GO TO THE MANAGE RESOURCES PAGE

  2. Click the name of your second Google Cloud project.

  3. Click Activate Cloud Shell.

  4. Create a Datalab VM:

    gcloud app create
    
  5. When prompted, select us-central1 as the region in which you want this app created.

Configure the environment.ts file

  1. In Cloud Shell, change directories to where you downloaded the code earlier in the tutorial:

    cd ~/dialogflow-chatbot/angular-ui/src/environments
    
  2. Edit the environment.ts and environment.prod.ts files to include your client access token from your Dialogflow agent.

    1. Click Settings next to your agent name.
    2. On the General tab, copy the Client access token listed in the API Keys (V1) section.

    3. In Cloud Shell, click Launch code editor :

    4. In the directory, go to dialogflow-chatbot > angular-ui= > src > environments > environment.ts.

      Directory with `environment.ts` file

    5. In the environment.ts file, in the angularBot:[YOUR_DIALOGFLOW_CLIENT_ACCESS_TOKEN] line replace [YOUR_DIALOGFLOW_CLIENT_ACCESS_TOKEN] with your client access code.

    6. To save the file, go to File, and then click Save.

    7. Go to dialogflow-chatbot > angular-ui > src > environments > environment.prod.ts to replace the [YOUR_DIALOGFLOW_CLIENT_ACCESS_TOKEN] as well.

  3. In Cloud Shell, return to the angular-ui subdirectory then run the command for npm:

    cd ~/dialogflow-chatbot/angular-ui
    npm install
    

    This installs all of the necessary node_modules listed in the package.json file for your project.

  4. Install the Angular CLI globally:

    npm install -g @angular/cli@6.0.8
    
  5. Compile the app into an output directory, called thedist/ folder, where the build artifacts are stored:

    ng build --prod
    

    To review the contents of the angular-ui subdirectory, enter ls.

    This subdirectory contains all of the frontend AngularJS code and the app.yaml file that you use to deploy your Python backend app and your Angular frontend app to App Engine.

    In the Code Editor tab, expand the dialogflow-chatbot/angular-ui/src/app/chat directory, then look at the chat.service.ts file. This file instantiates an ApiAiClient object (Dialogflow was formerly named Api.AI), which validates the client access token that you configured in the environment.ts file. The ApiAiClient object fetches the fulfillment.speech data from your Dialogflow agent to populate the Angular UI.

Deploy your app to the App Engine standard environment

  1. In Cloud Shell, go to the angular-ui subdirectory.

    cd ~/dialogflow-chatbot/angular-ui
    
  2. Redeploy your Angular frontend as the default service:

    echo "Y" | gcloud app deploy
    
  3. Retrieve the URL of the app you deployed. Make a note of this URL because it is used later in the tutorial.

    gcloud app browse
    
  4. To test your chatbot, go to http://[YOUR_PROJECT_ID].appspot.com and enter Tell me about annual salary.

Enabling Identity-Aware Proxy

Identity-Aware Proxy (IAP) brings Google's BeyondCorp security architecture to your App Engine app. By enabling and configuring IAP, your web UI requires authentication and authorization to access—thereby helping to secure your app.

Turn on IAP

  1. In the Cloud Console, go to Identity-Aware-Proxy.

    GO TO IDENTITY-AWARE-PROXY PAGE

  2. In the Resource column, find the app you want to restrict access to. The Published column shows the URL of the app. To turn on IAP for the app, in the IAP column, click the toggle.

    Toggle to enable IAM

  3. In the Turn on IAP dialog, verify that the automatically added domain matches the https://[PROJECT_ID].appspot.com domain where you expect to serve your app.

    Turn on IAM

  4. To confirm that you want to secure the app with IAP, click Turn On.

    IAP requires credentials for all connections to your app, and only accounts with the IAP-Secured Web App User role on this second Google Cloud project are given access.

  5. To test that you cannot access the App Engine website, click https://[PROJECT_ID].appspot.com in the Published section of the Cloud IAP page.

Add a user to IAP and test access

  1. In the Cloud Console, go to the Identity-Aware-Proxy page

    GO TO IDENTITY-AWARE-PROXY PAGE

  2. Select the checkbox of your App Engine app,.

  3. In the Add Member dialog, add a user under the New Member textbox, and then add Cloud IAP > IAP-Secured Web App User role for your account.

  4. Click Save.

  5. On the Identity-Aware-Proxy page, click the toggle to turn off IAP for the app. Click it again, to turn it back on.

  6. Test that you can now access the App Engine site with the existing logged in user. Go to https://[PROJECT_ID].appspot.com. You now have access to the website.

Building voice chat with Actions for Google

Integrate voice chat for your chatbot with Google Home or the Google Assistant app on iOS or Android by using the Actions with Google integration. For more information, learn how to setup and develop actions.

  1. In the Dialogflow console, click Intents.

  2. Click Default Welcome Intent.

  3. If Google Assistant Welcome isn't listed under Events, add it by typing Google Assistant Welcome in the Events field, and then click Save.

    Adding Google Assistant Welcome Events

  4. At the bottom of the page, review the expressions in the Text Response table. These are randomly selected by Google Assistant when your app starts. Add a few welcome statements of your own, and then click Save.

  5. Click Integrations and under Google Assistance, click Integration Settings.

  6. Confirm that the Explicit invocation is set to Default Welcome Intent, and then set the Implicit invocation to Topic.

    Setting implicit invocation to topic

  7. Click Test.

    This opens your project agent's page in Actions on Google. If you accept the Google terms, click Accept.

  8. Click Setup > Invocation.

  9. For Display name, type [YOUR_NAME] HR Manual, and then click Save.

    Display name for HR manual

  10. To test your Google Assistant–enabled chatbot, click Microphone and say the following phrases:

    • To direct the chatbot to your HR manual, say "Talk to [YOUR_NAME] HR Manual". For example, say, "Talk to Liz HR Manual."
    • To hear information about a particular topic, ask about a topic in the HR manual. For example, say, "Tell me about sick leave".
  11. Optional: Download Google Assistant on your iPhone or Android device. Log in to the app with your Google Account. Repeat the previous step.

Cleaning up

To avoid incurring charges to your Google Cloud account for the resources used in this tutorial, delete both Google Cloud projects.

Delete the project

  1. In the Cloud Console, go to the Manage resources page.

    Go to the Manage resources page

  2. In the project list, select the project that you want to delete and then click Delete .
  3. In the dialog, type the project ID and then click Shut down to delete the project.

What's next