microsoft / botframework-sdk

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

Problems when testing the AADv2 Auth Sample #4874

Closed rjgmail88 closed 5 years ago

rjgmail88 commented 6 years ago

Bot Info

SDK Platform: Nodejs SDK Version: 3.13.1 Active Channels: Teams Deployment Environment: Azure Bot Service

Issue Description

Err
Error: GET to 'https://api.botframework.com/api/usertoken/GetToken?userId=default-user&connectionName=TestAuth' failed: [404] Not Found
message:"GET to 'https://api.botframework.com/api/usertoken/GetToken?userId=default-user&connectionName=TestAuth' failed: [404] Not Found"
stack:"Error: GET to 'https://api.botframework.com/api/usertoken/GetToken?userId=default-user&connectionName=TestAuth' failed: [404] Not Found\n    at Request._callback 

OAuth Connection Settings:-

Name-TestAuth Service provider- AAD v2 Client id - ID of an app created on http://apps.dev.microsoft.com/ secret- from http://apps.dev.microsoft.com/ tenant id - from o365 tenant scope - openid profile

Code Example

I have Setup AzureADv2 integration using botservice docs https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-tutorial-authentication?view=azure-bot-service-3.0

my code is same as : https://github.com/Microsoft/BotBuilder/blob/master/Node/examples/basics-oauth/app.js

Expected Behavior

I should be able to see sign-in card and when clicked > signed in , magic number should get me authenticated.

Actual Results

Error in connector.getUserToken() method.

there is one place holder in code var connectionName = process.env.CONNECTION_NAME;

I am not sure if CONNECTION_NAME should match with OAuth Connection Settings name.

rjgmail88 commented 6 years ago

image

ravensorb commented 6 years ago

@rjgmail88 you are correct the connection name needs to match the name used in the OAuth Connection Settings in Azure. Have you tried that?

Note: If it helps, I have a AADv2 Auth bot up and running so I can confirm that it works at least in the Bot Emulator (not sure about the "Test in Web Chat" though as it seems like not many cards are supported in that view)

rjgmail88 commented 6 years ago

Hi, I can confirm that I am using same connection name is matching to azure oAuth settings. I still see following error

Error: GET to 'https://api.botframework.com/api/usertoken/GetToken?userId=default-user&connectionName=TestAuth' failed: [404] Not Found

I tried hosting bot by ngrok and setting up url like https://55096rrr.ngrok.io/api/messages in azure bots message endpoint. So I could confirm I'm hitting same bot. But, it didn't help.

stevkan commented 6 years ago

Hi @rjgmail88, Jason and I are trying to reproduce your issues but we've been unable to. Can you tell us where you are getting the 404 error from?

The connectionName variable either needs to be explicitly named as a string (e.g. var connectionName = "myOAuth") or the value be stored in the bots application settings so the process.env.CONNECTION_NAME has a value to retrieve.

Please upgrade your NPM BotBuilder package to the latest. There have been several improvements/changes effecting OAuth flow and the SDK since v3.13.1 was released.

Side note, the 'Test in Webchat' feature doesn't support OAuth cards, at this time. You would be better served testing in the emulator.

ravensorb commented 6 years ago

Can you provide screenshots of how you configured your Azure OAuth settings

rjgmail88 commented 6 years ago

I deleted and oAuth created new one with name gina and see same error again

Error: GET to 'https://api.botframework.com/api/usertoken/GetToken?userId=default-user&connectionName=gina' failed: [404] Not Found

Thank you for helping on this. Here is my code and screenshots

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

var restify = require('restify');
var builder = require('botbuilder');
var azure = require('azure');
var botbuilder_azure = require("botbuilder-azure");
// var middleware = require('./middleware.js')
// var conf = require('./config.json')

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

// Create chat connector for communicating with the Bot Framework Service
var connector = new builder.ChatConnector({
    appId: 'ABC',
    appPassword: 'XYZ'
});

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

//Set BOT state storage to CosmosDB
// var documentDbOptions = {
//     host: 'https://serivice-desk-store.documents.azure.com', 
//     masterKey: conf.docdb_master_key, 
//     database: 'euc-personal-assistant',   
//     collection: 'botdata'
// };

// var docDbClient = new botbuilder_azure.DocumentDbClient(documentDbOptions);
// var cosmosStorage = new botbuilder_azure.AzureBotStorage({ gzipData: false }, docDbClient)

// Create your bot with a function to receive messages from the user
var connectionName = "gina"
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, "gina",  (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, "gina", 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, "gina", "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, "gina", 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");
                        }
                    });
                }
            }
        });
    }
})
// bot.set('storage', cosmosStorage);

//create servicebus connection
// var sb_connection = conf.service_bus
// var serviceBusService = azure.createServiceBusService(sb_connection);
// serviceBusService.createQueueIfNotExists('send-to-bot', function(error){
//     if(error){
//         console.log("exitted")
//         process.exit(1)
//     }
// });

// LUIS Setup

var LUIS_URL = "LUIS App url here"
var recognizer = new builder.LuisRecognizer(LUIS_URL);
bot.recognizer(recognizer);

// Intercept trigger event (ActivityTypes.Trigger)
bot.on('trigger', function (message) {
    // handle message from trigger function
    var queuedMessage = message.value;
    var reply = new builder.Message()
        .address(queuedMessage.address)
        .text('This is coming from the trigger: ' + queuedMessage.text);
    bot.send(reply);
});

bot.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);
    }
});

image

image

rjgmail88 commented 6 years ago

@stevkan , I was using "botbuilder": "^3.15.0" so I guess that should be fine it oAuth was added after v3.13.1

jignesh84 commented 6 years ago

has anyone solved this 404 error?

stevkan commented 6 years ago

Hi @rjgmail88, please check the following

- You already defined the connection (like below). Next, you call that variable in the dialog, not the value (in this example, the name is "connectionName"):

var connectionName = "oauthconnection";

...
        } else {
            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 {
...

- The delegated permissions and scope for the OAuth connection you created should have these values: email Mail.Read openid profile User.Read

image

- The Client id in the OAuth connection is your bot's AppId, the Client secret is your bot's password, and the Tenant ID is the bot's domain.

premaarya commented 6 years ago

I am trying the run the ADD V2 sample code with the latest .NET SDK 3.15.3. Followed the V2 configuration provided here the setting provided here succeeds the Test Connection : image

When doing a test in WebChat getting Post error - { "error": { "code": "BadArgument", "message": "Missing token or secret" } }

And emulator error : image

Is this a known issue? How to resolve?

stevkan commented 6 years ago

@premaarya, can you please post your question as a new issue? It is unrelated to the current thread.

premaarya commented 6 years ago

created #4908

rjgmail88 commented 6 years ago

@stevkan I tried what you suggested, Still same issue.

stevkan commented 6 years ago

@rjgmail88 Apologies for the delay. Are you getting the same error even after the changes?

rjgmail88 commented 6 years ago

Yes, I am still getting same error even after keeping same delegated permissions.

rjgmail88 commented 6 years ago

@stevkan , any update on this ?

stevengum commented 5 years ago

Thank you for opening an issue against the Bot Framework SDK v3. As part of the Bot Framework v4 release, we’ve moved all v3 work to a new repo located at https://github.com/microsoft/botbuilder-v3. We will continue to support and offer maintenance updates to v3 via this new repo.

From now on, https://github.com/microsoft/botbuilder repo will be used as hub, with pointers to all the different SDK languages, tools and samples repos.

As part of this restructuring, we are closing all tickets in this repo.

For defects or feature requests, please create a new issue in the new Bot Framework v3 repo found here: https://github.com/microsoft/botbuilder-v3/issues

For Azure Bot Service Channel specific defects or feature requests (e.g. Facebook, Twilio, Teams, Slack, etc.), please create a new issue in the new Bot Framework Channel repo found here: https://github.com/microsoft/botframework-services/issues

For product behavior, how-to, or general understanding questions, please use Stackoverflow. https://stackoverflow.com/search?q=bot+framework

Thank you.

The Bot Framework Team

carblue5757 commented 5 years ago

Was this issue ever re-opened?

stevkan commented 5 years ago

@carblue5757, are you also receiving a 404 error?

videepthMSFT commented 5 years ago

Same Error !!! Following this thread to track the fix.

Thanks

muhualing commented 5 years ago

@stevkan Thank you for your time. I am also receiving the same error SDK Platform: Nodejs SDK Version: 3.16.0 Active Channels: Teams Deployment Environment: Azure Bot Service

Error: GET to 'https://api.botframework.com/api/usertoken/GetToken?userId=29%3A1R5vQA_0_OF8C4zi2Sy5uQs77pFKXs6Jxx1-UW7fABq7XqkNQ_CrL-lstObXd3RL6MVj_UZIC1PQ3fZGh-YdNFA&connectionName=ConnectionNameV2' failed: [404] Not Found

mycode:

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");
                }
            });
        }
    }
});

The Client id in the OAuth connection is my bot's AppId, the Client secret is my bot's password, and the Tenant ID is the bot's domain. The connection name is also right image

cocsci commented 4 years ago

if still anyone ran up to this problem after deploying on Azure while everything works fine locally, just go to your Web App page in Azure protal and under "Configuration"section add a new environmental variable ConnectionName with the value of whatever your connection name is in your bot setting.