2

I'm trying to integrate my bot too the Hangouts Chat API. I migrated from C# to node.js in order to be able to take advantage of the HangoutsAdapter: https://botkit.ai/docs/v4/platforms/hangouts.html

The problem is that the HangoutsAdapter expects a google token and when I go to the Hangouts Chat API configuration tab, I select Bot URL under Connection Settings section, but the only thing I get is a field to enter my bot's url endpoint. Nothing about the Verification Token I'm supposed to pass to the Hangouts Adapter.

Is there any other way to validate the connection to that API with HangoutsAdapter? Should I use something else rather than HangoutsAdapter? Or maybe I should use it in a different way?

Martín La Rosa
  • 790
  • 4
  • 17
  • Apparently the secret token was replaced with what the example propose. The problem is that the node.js google client API doesn't seem to support the same thing the examples in Java and Python show – Martín La Rosa Jun 25 '19 at 20:00
  • Can you post your code, please? Remove any secrets / keys in your code, too. – Steven Kanberg Jun 25 '19 at 21:32
  • Also, are you using v4 BotFramework? – Steven Kanberg Jun 25 '19 at 21:33
  • I am using v4, the problem is in the HangoutsAdapter for BotBuilder or for BotKit: https://botkit.ai/docs/v4/platforms/hangouts.html The code I need to correct is here in its repo: https://github.com/howdyai/botkit/blob/master/packages/botbuilder-adapter-hangouts/src/hangouts_adapter.ts Basically it expects a token in order to compare it to the token gotten from the hangouts chat api. But given that the token is not provided anymore I need to implement this: https://developers.google.com/hangouts/chat/how-tos/bots-develop#verifying_bot_authenticity. – Martín La Rosa Jun 25 '19 at 21:39

2 Answers2

1

Technically, this is an alternative solution (I think). In order to create Google Hangouts credentials a GSuite account is required, which I don't have. The Interface HangoutsAdapterOptions docs state the "Shared secret token [is] used" for validation and is found under the Configuration tab. As the fields are locked down, I can't test this.

However, the alternative is to use the built-in OAuth feature of the Bot Framework. I use this in my bot without a hitch. I did navigate to the Google Hangouts web site and it recognized me immediately. By using the OAuth login, a token is returned which you can use to pass into the Hangouts adapter.

I should add that the below implementation produces a sign-in magic code which some people don't like (it doesn't bother me). There may be a SSO option, but I haven't researched that.


First, you need to setup Google credentials which will provide you with a "Client id" and "Client secret". General instructions can be found here. Credentials can be created here. You can ignore any coding references as they aren't necessary (thanks to the BF OAuth feature).

From the Credentials Page, click on "Credentials" in the left menu. There are two areas you need to configure, once there: "OAuth consent screen" and "Credentials".

enter image description here

For OAuth consent screen, provide an app name. This doesn't need to match the associated requesting app and is just for reference when visiting the Credentials Page. Enter a support email, the scopes you will be using (email, profile, and openid). There may be other required scopes, but this worked for me when I visited the Hangouts web site. Lastly, enter in the Authorized Domains. The botframework.com domain is required. Others, if any, you will have to experiment with. Save and return to the Credentials Page.

Click the "Create Credentials" button and complete the form. Give your credentials a name (again, not referenced anywhere else for this project), enter any authorized origins, and enter https://token.botframework.com/.auth/web/redirect as the authorized redirect URI. Save the settings, copy the "Client id" and "Client secret" somewhere, and navigate to Azure and into your bot's settings page.

Here, you need to create your bot's OAuth connection. This is done in the Settings blade. At the bottom of the blade is the "OAuth Connection Settings" section. Click the "Add Setting" button to get started.

Once in, give your connection a name. This name will be referenced by your bot in the next step, so save the name somewhere. Then, select Google from the list of Service Providers and paste the "Client id" and "Client secret", that you saved earlier, into the respective fields. In "Scopes", you will want to enter the same scope values you selected in your Google credentials app ("email profile openid"). Be sure they are space-separated when you enter them.

enter image description here

enter image description here

Lastly, you will want to model your OAuth login off of sample 18.bot-authentication from the Botbuilder-Samples repo. This builds in the functionality you need for enabling a user to log in via your bot.

Add the connection name you assigned to your Google connection setting for your bot into a .env file as a variable, like this: connectionName=<CONNECTION_NAME>.

When setting up the OAuth prompt, you will pass this variable in:

this.addDialog(new OAuthPrompt(OAUTH_PROMPT, {
  connectionName: process.env.connectionName,
  text: 'Please Sign In',
  title: 'Sign In',
  timeout: 300000
}));

At this point, your bot and login process should be good to go. Assuming the flow is setup correctly, a user should be able to login via the OAuth prompt, by use of a magic code. A token is returned back to the bot which will be accessible via the context on the next step. The token can then be saved to state and passed to the adapter for use. In the below bit, I'm using a simple waterfall with an oauthPrompt step and a loginResults step. The token is captured in the second step where I console log it.

async oauthPrompt(step) {
    return await step.prompt(OAUTH_PROMPT, {
        prompt: {
            inputHint: 'ExpectingInput'
        }
    });
}

async loginResults(step) {
  let tokenResponse = step.result;
  console.log('TOKEN: ', tokenResponse);

  if (tokenResponse != null) {
    await step.context.sendActivity('You are now logged in.');
    return await step.prompt(CONFIRM_PROMPT, 'Do you want to view your token?', ['yes', 'no']);
  }

  // Something went wrong, inform the user they were not logged in
  await step.context.sendActivity('Login was not successful please try again');
  return await step.endDialog();
}

enter image description here

Hope of help!

Steven Kanberg
  • 6,078
  • 2
  • 16
  • 35
1

I created an issue on https://github.com/howdyai/botkit/issues/1722

Basically hangouts adapter expects a token in order to compare it to the token gotten from the hangouts chat api. But given that the token is not provided anymore by google, the authentication mechanism needs to change

Martín La Rosa
  • 790
  • 4
  • 17