Search code examples
botframeworkweb-chat

Speech Service Authentication With 'Credentials' Via Webchat on Bot Framework V4


My bot is working fine while calling Speech Services using an authorization token + region pair.
Code snipped below.
webSpeechPonyfillFactory = await window.WebChat.createCognitiveServicesSpeechServicesPonyfillFactory({ authorizationToken, region });
However, the following warning message shows up on the browser:
botframework-webchat: "authorizationToken", "region", and "subscriptionKey" are deprecated and will be removed on or after 2020-12-17. Please use "credentials" instead.
How can migrate my authentication code to the new method?
Code samples are appreciated. Thx


Solution

  • This is the code I use. I run a server locally for calling the speech API that returns the token (and region).

    In the Web Chat code, you simply need to pass the returned token and region in to createCognitiveServicesSpeechServicesPonyfillFactory(). Your code doesn't need to match mine, specifically. It is enough to do something like:

    const webSpeechPonyfillFactory = await window.WebChat.createCognitiveServicesSpeechServicesPonyfillFactory( {
      credentials: {
        authorizationToken: authorizationToken,
        region: region
      }
    } );
    

    or, depending how you structure your credentials object,

    { credentials: credentials }


    Sample code:

    const path = require('path');
    const restify = require('restify');
    const request = require('request');
    
    const bodyParser = require('body-parser');
    const corsMiddleware = require('restify-cors-middleware');
    
    const cors = corsMiddleware({
        origins: ['*']
    });
    
    const ENV_FILE = path.join(__dirname, '.env');
    require('dotenv').config({ path: ENV_FILE });
    
    // Create HTTP server.
    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 || 3500, function() {
        console.log(`\n${ server.dl_name } listening to ${ server.url }.`);
    });
    
    server.post('/speechservices/token', async (req, res) => {
        const options = {
            method: 'POST',
            uri: `https://${ process.env.SPEECH_SERVICES_REGION }.api.cognitive.microsoft.com/sts/v1.0/issueToken`,
            headers: {
                'Ocp-Apim-Subscription-Key': process.env.SPEECH_SERVICES_SUBSCRIPTION_KEY
            }
        };
        request.post(options, (error, response, body) => {
            if (!error && response.statusCode < 300) {
                body = { region: process.env.SPEECH_SERVICES_REGION, authorizationToken: body };
                res.send({
                    authorizationToken: body.authorizationToken,
                    region: body.region
                });
                console.log(`Someone requested a speech token...(${ response.statusCode })`);
            } else if (response.statusCode >= 400 && response.statusCode < 500) {
                res.send(response.statusCode);
            } else if (response.statusCode >= 500) {
                res.status(response.statusCode);
                res.send('Call to retrieve token failed');
            }
        });
    });
    
    const getSpeechToken = async (credentials = {}) => {
      const response = await fetch( `http://localhost:3500/speechservices/token`, {
        method: 'POST',
      } );
      if ( response.status === 200 ) {
        const { authorizationToken, region } = await response.json();
        credentials['authorizationToken'] = authorizationToken;
        credentials['region'] = region;
        return credentials;
      } else {
        console.log('error')
      }
    }
    
    const webSpeechPonyfillFactory = await window.WebChat.createCognitiveServicesSpeechServicesPonyfillFactory( {
      credentials: await getSpeechToken()
    } );
    
    render(
      <div>
        <ReactWebChat
          directLine={directLine}
          selectVoice={( voices, activity ) =>
            activity.locale === 'en-US' ?
              voices.find( ( { name } ) => /KatjaNeural/iu.test( name ) )
              :
              voices.find( ( { name } ) => /KatjaNeural/iu.test( name ) )
              || voices.find( ( { name } ) => /Apollo/iu.test( name ) )}
          webSpeechPonyfillFactory={webSpeechPonyfillFactory}
        />
        </div>,
      document.getElementById( 'webchat' )
      );
    

    Hope of help!