microsoft / botframework-sdk

Bot Framework provides the most comprehensive experience for building conversation applications.
MIT License
7.51k stars 2.45k forks source link

Issues authenticating OAuth with Azure bot Service #4885

Closed thejasondt closed 6 years ago

thejasondt commented 6 years ago

The Microsoft Bot Framework team prefers that "How To" questions be submitted on Stack Overflow. The official Bot Framework GitHub repository  is the preferred platform for submitting bug fixes and feature requests.

Bot Info

Issue Description

I am trying to set up a new OAuth connection setting for Instagram on Azure as described on this tutorial (https://channel9.msdn.com/Shows/AI-Show/Conversational-AI-and-Authentication) at time 2:30 to OAuth with a Card in Skype

The issue seems to be with the redirect url when coming back to https://token.botframework.com/.auth/web/redirect

I am currently trying to use OAuthCard in my Skype Bot using

https://github.com/Microsoft/BotBuilder/blob/master/Node/examples/basics-oauth/app.js

Though I have replaced "var builder = require('../../core/');" with "var builder = require('botbuilder');"

I am using this OAuthCard in Skype - I click it and it redirects, asks for approval to my account/sign in - I give it and it then redirects and give a blank white screen with "Bad request"

The redirect url returns: https://token.botframework.com/.auth/web/redirect?code=xyz&state=abc

N.B. If I go to my Instagram account I can see that I have given my app access, so it is not an issue there.

N.N.B I have tried to "Test Connection" using the Twitter OAuth connection setting and that also returns bad request but before reaching Twitter to Authenticate.

Code Example

/*-----------------------------------------------------------------------------
A simple OAuthCard bot for the Microsoft Bot Framework. 
-----------------------------------------------------------------------------*/

var restify = require('restify');
var builder = require('botbuilder');

// Setup Restify Server
var server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 4000, function () {
   console.log('%s listening to %s', server.name, server.url); 
});

// Bot Storage: Here we register the state storage for your bot. 
// Default store: volatile in-memory store - Only for prototyping!
// We provide adapters for Azure Table, CosmosDb, SQL Azure, or you can implement your own!
// For samples and documentation, see: https://github.com/Microsoft/BotBuilder-Azure
var inMemoryStorage = new builder.MemoryBotStorage();

// Create chat connector for communicating with the Bot Framework Service
var connector = new builder.ChatConnector({
    appId: process.env.MicrosoftAppId,
    appPassword: process.env.MicrosoftAppPassword,
});

var connectionName = process.env.CONNECTION_NAME;

// Listen for messages from users 
server.post('/api/messages', connector.listen());

// Create your bot with a function to receive messages from the user
var bot = new builder.UniversalBot(connector, function (session) {
    if (session.message.text == 'signout') {
        // It is important to have a SignOut intent
        connector.signOutUser(session.message.address, connectionName,  (err, result) => {
            if (!err) {
                session.send('You are signed out.');
            } else {
                session.send('There was a problem signing you out.');                
            }
        });
    } else {
        // First check whether the Azure Bot Service already has a token for this user
        connector.getUserToken(session.message.address, connectionName, undefined, (err, result) => {
            if (result) {
                // If there is already a token, the bot can use it directly
                session.send('You are already signed in with token: ' + result.token);
            } else {
                // If there not is already a token, the bot can send an OAuthCard to have the user log in
                if (!session.userData.activeSignIn) {
                    session.send("Hello! Let's get you signed in!");
                    builder.OAuthCard.create(connector, session, connectionName, "Please sign in", "Sign in", (createSignInErr, signInMessage) =>
                    {
                        if (signInMessage) {
                            session.send(signInMessage);
                            session.userData.activeSignIn = true;
                        } else {
                            session.send("Something went wrong trying to sign you in.");
                        }     
                    });
                } else {
                    // Some clients require a 6 digit code validation so we can check that here
                    session.send("Let's see if that code works...");
                    connector.getUserToken(session.message.address, connectionName, session.message.text, (err2, tokenResponse) => {
                        if (tokenResponse) {
                            session.send('It worked! You are now signed in with token: ' + tokenResponse.token);
                            session.userData.activeSignIn = false;
                        } else {
                            session.send("Hmm, that code wasn't right");
                        }
                    });
                }
            }
        });
    }
})
.set('storage', inMemoryStorage) // Register in memory storage
.on("event", (event) => {         // Handle 'event' activities
    if (event.name == 'tokens/response') {
        // received a TokenResponse, which is how the Azure Bot Service responds with the user token after an OAuthCard
        bot.loadSession(event.address, (err, session) => {
            let tokenResponse = event.value;
            session.send('You are now signed in with token: ' + tokenResponse.token);
            session.userData.activeSignIn = false;
        });
    }
});

connector.onInvoke((event, cb) => {
    if (event.name == 'signin/verifyState') {
        // received a MS Team's code verification Invoke Activity
        bot.loadSession(event.address, (err, session) => {
            let verificationCode = event.value.state;
            // Get the user token using the verification code sent by MS Teams
            connector.getUserToken(session.message.address, connectionName, verificationCode, (err, result) => {
                session.send('You are now signed in with token: ' + result.token);
                session.userData.activeSignIn = false;
                cb(undefined, {}, 200);
            });
        });
    } else {
        cb(undefined, {}, 200);
    }
});

Reproduction Steps

  1. Use bot code https://github.com/Microsoft/BotBuilder/blob/master/Node/examples/basics-oauth/app.js
  2. Replaced "var builder = require('../../core/');" with "var builder = require('botbuilder');"
  3. In Azure Bot Service Settings, set up a new connection OAuth Connection Setting for Instagram and input the client id and client secret from you Instagram (sandbox) app.
  4. Input "public_content" in "scopes"
  5. Set "https://token.botframework.com/.auth/web/redirect" as verified redirect url in Instagram App
  6. Talk to Bot in Skype and click the Sign in Card (Or Test Connection in Azure Bot Service)
  7. Authorize app to your Instagram account

Expected Behavior

I am expecting it to return to the Skype chat and continue the dialog

Actual Results

I get a blank white page with "bad request" and the url is https://token.botframework.com/.auth/web/redirect?code=xyz&state=abc

JasonSowers commented 6 years ago

For reference, this was cross-posted from a Stack Overflow question for better tracking.

To answer your question from your Stack overflow comment. The app I was testing with is also in sandbox mode, so I don't think that is the issue. I assume the answer is yes, but I might as well ask if you are trying to sign into your app with the same account you created the app with?

This line:

Though I have replaced "var builder = require('../../core/');" with "var builder = require('botbuilder');"

Is correctly changed and should not be an issue at all.

Can you try on another channel like the emulator? Keep in mind the "test in webchat" tab in Azure will not render the sign in card so it would have to be another channel. I suspect this will also not work because you are getting "bad request" in the test connection. Let me take a look at the video you linked from channel 9 and see if there are any discrepancies in the instructions. Chances are this is just a setting that is off, so we just need to hunt it down.

thejasondt commented 6 years ago

I have also tried using embedded webchat - https://github.com/Microsoft/BotFramework-WebChat

Edit - I have now also tried it with Facebook Messenger with the same outcome. Edit - and yes I am trying to sign into the app with the same account that created it.

Even without testing in a channel, it should be able to work via the Test Connection button, so I don't think it'd be a channel issue.

thejasondt commented 6 years ago

Could it be an issue with var inMemoryStorage = new builder.MemoryBotStorage(); Or something regarding the changeover in March?

JasonSowers commented 6 years ago

In memory storage is most likely not affecting this as I was using it for my testing as well.

thejasondt commented 6 years ago

Hmm ok - still struggling

When I try Twitter "Test Connection" it does not even reach Twitter - could it be linked and highlight the issue?

JasonSowers commented 6 years ago

My assumption is that they would be related. Let me confirm that I can get Twitter working first as I have not tried with twitter yet.

JasonSowers commented 6 years ago

Are you just getting bad request with twitter?

thejasondt commented 6 years ago

Yes - I do not even reach Twitter - but when I do Instagram, I reach them and then a bad request on the redirect

JasonSowers commented 6 years ago

@thejasondt can you send me an email with your IG account name so I can try adding you to my sandbox app to see if my app works for you?

thejasondt commented 6 years ago

Sent

JasonSowers commented 6 years ago

Added

JasonSowers commented 6 years ago

Let me know how that works out, and check out my settings and see if they align to yours.

thejasondt commented 6 years ago

Ok, accepted invite - awaiting for it to appear in "manage clients" then will test

JasonSowers commented 6 years ago

I do not think the issue with twitter is on your end so hang tight on that one. I need to speak with someone further about twitter.

thejasondt commented 6 years ago

Ok - regarding IG, I have accepted the invite but yet to see your app in "manage clients" is there action required by you to allow access to it?

JasonSowers commented 6 years ago

I'm going to be out for a while, but let me know your results.

thejasondt commented 6 years ago

I cannot reach your client, so will have to wait for your return

JasonSowers commented 6 years ago

Are you getting the same results as you were with your application?

thejasondt commented 6 years ago

I cannot access your app - if I am on IG and go to manage clients, your app does not appear, so I cannot test EDIT - so there may be actions your end to allow me to access the app?

JasonSowers commented 6 years ago

@thejasondt check your email i gave you the inputs to try my app

thejasondt commented 6 years ago

@jasonsowers it works - does this mean it is an issue then with my IG setup? I also tested FB and that worked but TW does not

thejasondt commented 6 years ago

Solved - And it was down to a simple issue. Copy and pasting the secret from IG added an additional blank space at the end of the secret, though the client id did not. Apologies. The issue still occurs with Twitter however

JasonSowers commented 6 years ago

Great!, I am going to continue looking into to twitter

JasonSowers commented 6 years ago

@thejasondt we will have to reach out to another team to look into the issue with Twitter. I will let you know when I have more information on this.

thejasondt commented 6 years ago

Interesting that despite the blank space I could Authenticate the app but the issue seemed to be with the redirect

JasonSowers commented 6 years ago

@thejasondt I would guess the reason you were able to do it with the blank space was most likely because the space was removed or ignored somewhere along the line.

Are you still seeing any issues, or are we good to close this issue? I am going to make a new issue for Twitter. We are tracking it internally already, but I want a GitHub issue so people know we are already aware of it.