Microsoft bot framework webchat hidden secret for direct line -- NODE JS

1k Views Asked by At

I need to hide the secret for direct line channel using an HTML webchat, tried this solution but keeps getting me errors while fetching. I got the secret for direct line channel in Azure portal in process.env

Index.js

const dotenv = require('dotenv');
const path = require('path');
const restify = require('restify');

const bodyParser = require('body-parser'); 
const request = require('request'); 
const corsMiddleware = require('restify-cors-middleware'); 


const { BotFrameworkAdapter, MemoryStorage, ConversationState, UserState   } = require('botbuilder');

const { EBOT } = require('./eBot');

const ENV_FILE = path.join(__dirname, '.env');
dotenv.config({ path: ENV_FILE || process.env.directLineSecret });

const cors = corsMiddleware({ 
  origins: ['*'] 
}); 

const server = restify.createServer();
server.pre(cors.preflight); 
server.use(cors.actual); 
server.use(bodyParser.json({ 
  extended: false 
})); 
server.listen(process.env.port || process.env.PORT || 3978, () => {
    console.log(`\n${ server.name } listening to ${ server.url }`);
    console.log('\nGet Bot Framework Emulator: https://aka.ms/botframework-emulator');
    console.log('\nTo talk to your bot, open the emulator select "Open Bot"');
});

// Generates a Direct Line token 
server.post('/directline/token', (req, res) => { 
  const options = { 
    method: 'POST', 
    uri: 'https://directline.botframework.com/v3/directline/tokens/generate', 
    headers: { 
      'Authorization': `Bearer ${process.env.directLineSecret}` 
    }};
  request.post(options, (error, response, body) => { 
    if (!error && response.statusCode < 300) { 
      res.send({ 
        token: body.token 
      }); 
    } else { 
      res.status(500).send('Call to retrieve token from DirectLine failed'); 
    } 
  }); 
});

server.post('/api/messages', (req, res) => {
    adapter.processActivity(req, res, async (context) => {
        await ebot.run(context);
    });
});

And webchat.html:

<script src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
<script>
            (async function () {
            const res = await fetch('https://directline.botframework.com/v3/directline/tokens/generate', { method: 'POST' });
            const webChatToken = await res.json();
    
              window.WebChat.renderWebChat({
                directLine: window.WebChat.createDirectLine({ token: webChatToken })
              }, document.getElementById('webchat'));
    
              document.querySelector('#webchat > *').focus();
            })().catch(err => console.error(err));
    
</script>

/// UPDATE

The errors:

** Failed to load resource: the server responded with a status of 403 ()

** webchat.js:2 POST https://directline.botframework.com/v3/directline/conversations 403

** webchat.js:2 Uncaught t {message: "ajax error 403", xhr: XMLHttpRequest, request: {…}, status: 403, responseType: "json", …}

What's the way then ?, what am I missing ?

2

There are 2 best solutions below

0
jsanchezs On BEST ANSWER

Solved it, the problem was the way the api token function was made, this is the one that worked in order to retrieve the json response from index.js :

server.post('/directline/token', async function(req, res) {
        const result = await fetch('https://directline.botframework.com/v3/directline/tokens/generate', {
            method: 'POST',
            headers: {
                Authorization: 'Bearer ' +  process.env.DirectLineSecret
            }
        });
        const token = await result.json();
        res.send(token);
});

The one I posted in questions was not sending the token response but a huge request ibject instead. Hope it helps !

3
Steven Kanberg On

The issue with your particular implementation is, while you have set up an API for generating and serving a token back to Web Chat, you are failing to actually call that endpoint. Instead of

const res = await fetch('https://directline.botframework.com/v3/directline/tokens/generate', { method: 'POST' });

you should have

const res = await fetch('http://localhost:3978/directline/token', { method: 'POST' });

It is this that will make the call to exchange the Direct Line secret for a token and, in turn, will return the token back to your Web Chat instance.