-
Notifications
You must be signed in to change notification settings - Fork 4.9k
/
index.js
132 lines (107 loc) · 5.62 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
const path = require('path');
// const fs = require('fs');
const dotenv = require('dotenv');
const restify = require('restify');
const msal = require('@azure/msal-node');
const { DefaultAzureCredential } = require('@azure/identity');
const { SecretClient } = require('@azure/keyvault-secrets');
const { MsalServiceClientCredentialsFactory } = require('botframework-connector');
// Import required bot configuration.
const ENV_FILE = path.join(__dirname, '.env');
dotenv.config({ path: ENV_FILE });
// Import required bot services.
// See https://aka.ms/bot-services to learn more about the different parts of a bot.
const {
CloudAdapter,
ConfigurationBotFrameworkAuthentication
} = require('botbuilder');
// This bot's main dialog.
const { AuthBot } = require('./authBot');
(async () => {
try {
// Create HTTP server.
const server = restify.createServer();
server.use(restify.plugins.bodyParser());
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"');
});
const authorityUrl = 'https://login.microsoftonline.com/botframework.com';
// ---- Authenticate using key vault to obtain the certificate values.
// Create an Azure credential to authenticate.
const credential = new DefaultAzureCredential();
const vaultName = process.env.KeyVaultName;
const keyVaultUrl = `https://${ vaultName }.vault.azure.net`;
const certificateName = process.env.CertificateName;
// Using an Azure credential object and a keyVaultUrl, let's create a SecretClient.
const secretClient = new SecretClient(keyVaultUrl, credential);
// Assuming you've already created a Key Vault certificate,
// and that certificateName contains the name of your certificate.
const certificateSecret = await secretClient.getSecret(certificateName);
// Here we can find both the private key and the public certificate, in PKCS 12 format:
const certificateKey = certificateSecret.value;
// ---- Authenticate using local certificate.
// const key = fs.readFileSync('{KeyPath}.pem', 'utf8');
// Extract x5c value from the key string to use the SNI authentication.
const x5cValue = certificateKey.split('-----BEGIN CERTIFICATE-----\n').pop().split('\n-----END CERTIFICATE-----')[0];
// Create client credentials using SNI authentication from MSAL.
const serviceClientCredentialsFactory = new MsalServiceClientCredentialsFactory(
process.env.MicrosoftAppId,
new msal.ConfidentialClientApplication({
auth: {
clientId: process.env.MicrosoftAppId,
authority: authorityUrl,
clientCertificate: {
thumbprint: process.env.CertificateThumbprint,
privateKey: certificateKey,
x5c: x5cValue
}
}
})
);
const botFrameworkAuthentication = new ConfigurationBotFrameworkAuthentication(process.env, serviceClientCredentialsFactory);
// Create adapter.
// See https://aka.ms/about-bot-adapter to learn more about how bots work.
const adapter = new CloudAdapter(botFrameworkAuthentication);
// Catch-all for errors.
const onTurnErrorHandler = async (context, error) => {
// This check writes out errors to console log .vs. app insights.
// NOTE: In production environment, you should consider logging this to Azure
// application insights. See https://aka.ms/bottelemetry for telemetry
// configuration instructions.
console.error(`\n [onTurnError] unhandled error: ${ error }`);
// Send a trace activity, which will be displayed in Bot Framework Emulator
await context.sendTraceActivity(
'OnTurnError Trace',
`${ error }`,
'https://www.botframework.com/schemas/error',
'TurnError'
);
// Send a message to the user
await context.sendActivity('The bot encountered an error or bug.');
await context.sendActivity('To continue to run this bot, please fix the bot source code.');
};
// Set the onTurnError for the singleton CloudAdapter.
adapter.onTurnError = onTurnErrorHandler;
// Create the main dialog.
const myBot = new AuthBot();
// Listen for incoming requests.
server.post('/api/messages', async (req, res) => {
// Route received a request to adapter for processing
await adapter.process(req, res, (context) => myBot.run(context));
});
// Listen for Upgrade requests for Streaming.
server.on('upgrade', async (req, socket, head) => {
// Create an adapter scoped to this WebSocket connection to allow storing session data.
const streamingAdapter = new CloudAdapter(botFrameworkAuthentication);
// Set onTurnError for the CloudAdapter created for each connection.
streamingAdapter.onTurnError = onTurnErrorHandler;
await streamingAdapter.process(req, socket, head, (context) => myBot.run(context));
});
} catch (error) {
console.log(error);
}
})();