Skip to content

Commit 9fa9d0c

Browse files
Merge pull request #1 from pnp/master
Sync
2 parents 0fc8f5a + b54bd23 commit 9fa9d0c

File tree

90 files changed

+55376
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+55376
-0
lines changed
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
# SharePoint extension sample with bot framework
2+
3+
## Summary
4+
5+
[Extensions](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/extensions/overview-extensions) is a special kind of SharePoint controls that can be supported by the [Bot Framework](https://dev.botframework.com). This sample will show you how to embed a Bot Framework bot into a SharePoint web site with security consideration.
6+
7+
There are two parts included in this sample:
8+
9+
1. An echo bot sample
10+
1. An extension sample
11+
12+
The extension sample embeds the echo bot by using a webchat. As extension code is running on client side, [web chat security](https://blog.botframework.com/2018/09/01/using-webchat-with-azure-bot-services-authentication/) needs to be taken into consideration. This sample shows how to secure your conversation including:
13+
14+
- Use Direct Line token instead of Direct Line secret
15+
- Tamper-proof user: for user id, generate it inside client side and detect if the client has changed the user ID and reject the change.
16+
17+
This demo does not include any threat models and is designed for educational purposes only. When you design a production system, threat-modelling is an important task to make sure your system is secure and provide a way to quickly identify potential source of data breaches. IETF [RFC 6819](https://tools.ietf.org/html/rfc6819) and [OAuth 2.0 for Browser-Based Apps](https://tools.ietf.org/html/draft-ietf-oauth-browser-based-apps-01#section-9) is a good starting point for threat-modelling when using OAuth 2.0.
18+
19+
![demo](assets/sp-ex-secure.gif)
20+
21+
## Used SharePoint Framework Version
22+
23+
![1.0](https://img.shields.io/badge/version-1.0-green.svg)
24+
25+
## Applies to
26+
27+
* [SharePoint Framework](https://docs.microsoft.com/sharepoint/dev/spfx/sharepoint-framework-overview)
28+
* [Office 365 tenant](https://docs.microsoft.com/sharepoint/dev/spfx/set-up-your-development-environment)
29+
* [Microsoft Bot Framework](http://dev.botframework.com)
30+
31+
## Prerequisites
32+
33+
- [Node.js](https://nodejs.org) version 10.19 (Node.js v9.x, v11.x, and v12.x are not currently supported with SharePoint Framework development)
34+
35+
```bash
36+
# determine node version
37+
node --version
38+
```
39+
40+
## Solution
41+
42+
Solution|Author(s)
43+
--------|---------
44+
webpart | STCA BF Channel and ABS ([email protected]) <br/> Stephan Bisser (@stephanbisser, bisser.io)
45+
bot | STCA BF Channel and ABS ([email protected])
46+
47+
## Version history
48+
49+
Version|Date|Comments
50+
-------|----|--------
51+
1.0|Nov 10, 2020|Initial release
52+
53+
## Disclaimer
54+
55+
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
56+
57+
---
58+
59+
## Minimal Path to Awesome
60+
61+
### Enlist
62+
63+
- Clone the repository
64+
65+
```bash
66+
git clone [Placeholder]
67+
```
68+
69+
- In a terminal, navigate to `[Placeholder]`
70+
71+
```bash
72+
cd [Placeholder]
73+
```
74+
75+
### [Setup bot](./bot/README.md)
76+
77+
- Install modules
78+
79+
```bash
80+
npm install
81+
```
82+
83+
- Register Connections. You can get it done by [deploy your bot to Azure](https://aka.ms/azuredeployment). Save your bot service endpoint like: "https://YOUR_BOT.azurewebsites.net". Save your AAD Id as YOUR_APP_ID and secret as YOUR_APP_PSW.
84+
85+
- [Connect to direct line](https://docs.microsoft.com/en-us/azure/bot-service/bot-service-channel-connect-directline?view=azure-bot-service-4.0), copy one of the Secret Key values as YOUR_DIRECT_LINE_SECRET and store this for later usage. This is your ‘Direct Line Secret’.
86+
87+
- Add ‘Direct Line Secret’ to an .env config file under ./bot
88+
89+
```bash
90+
MicrosoftAppId=YOUR_APP_ID
91+
MicrosoftAppPassword=YOUR_APP_PSW
92+
DirectLineSecret=YOUR_DIRECT_LINE_SECRET
93+
```
94+
95+
- Republish your bot with new config.
96+
97+
### [Setup extension](./extension/README.md)
98+
99+
- Install modules
100+
101+
```bash
102+
npm install
103+
```
104+
105+
- Edit "BotFrameworkChatPopupApplicationChat.tsx" file to set your bot endpoint (`props.botEndpoint`) directly like `https://YOUR_BOT.azurewebsites.net` for testing purpose (instead of setting it in the Tenant Wide Extensions list):
106+
107+
```ts
108+
generateToken(props.botEndpoint, md5(userId)).then((token: string) => { //change props.botEndpoint to the endpoint directly if you want to test it
109+
if (token) {
110+
setDirectLine(createDirectLine({ token }));
111+
}
112+
});
113+
```
114+
115+
- Config CORS \
116+
[CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) must be set on bot app service to enable SharePoint client to get resource from bot service. Follow these steps to add your workbench to bot app service CORS configration:
117+
118+
1. Go to your azure portal
119+
1. Navigate to your bot app service, search for CORS settings
120+
1. Add https://localhost:4321 and https://<YOUR_SITE>.sharepoint.com to CORS origins
121+
122+
- In the command line run
123+
124+
```bash
125+
cd ../extension
126+
npm install
127+
gulp serve --nobrowser
128+
```
129+
130+
- Open up a SharePoint modern page and add the following string to your URL:
131+
132+
```url
133+
?loadSPFX=true&debugManifestsFile=https://localhost:4321/temp/manifests.js&customActions={"f50b07b5-76a5-4e80-9cab-b4ee9a591bf6":{"location":"ClientSideExtension.ApplicationCustomizer"}}
134+
```
135+
136+
If you want to deploy it follow the steps [here](./extension/README.md#deploy).
137+
138+
## Features
139+
140+
**Web Chat integration with security consideration**
141+
142+
The SharePoint component will integrate bot with react Web Chat component.
143+
144+
```tsx
145+
public render(): React.ReactElement<IBotFrameworkChatv4Props> {
146+
return (
147+
<div className={styles.botFrameworkChatv4} style={{ height: 700 }}>
148+
<ReactWebChat directLine={directLine} styleOptions={styleSetOptions} />
149+
</div>
150+
);
151+
}
152+
```
153+
154+
Inside Web Chat, direct line will be used to connect to Bot Service. On Bot Service side, one more endpoint "directline/token" will be added besides "api/messages", which will accept userId passed from client side and return back direct line token.
155+
156+
For production, this endpoint should also verify if the incoming request is authroized.
157+
158+
```tsx
159+
server.post('/directline/token', (req, res) => {
160+
const secret = settings.parsed.DirectLineSecret;
161+
const authorization = `Bearer ${secret}`;
162+
163+
const userId = 'dl_' + GetUserId((req.body || {}).user);
164+
const options = {
165+
method: 'POST',
166+
uri: 'https://directline.botframework.com/v3/directline/tokens/generate',
167+
body: JSON.stringify({ user: { id: userId} }),
168+
headers: { 'Authorization': authorization, 'Content-Type': 'application/json'}
169+
};+
170+
171+
request.post(options, (error, response, body) => {
172+
if (!error && response.statusCode < 300) {
173+
res.status(response.statusCode);
174+
if (body) { res.send(JSON.parse(body)) }
175+
} else {
176+
res.status(500);
177+
res.send('Call to retrieve token from DirectLine failed');
178+
}
179+
res.end();
180+
});
181+
});
182+
```
183+
184+
On extension side, it will fetch direct line token from bot service side with SharePoint userId then build up the web chat component. The UserId should be encrypted so it won't be easy to get other user's token by bot endpoint.
185+
186+
```tsx
187+
useEffect(() => {
188+
const userId = props.context.pageContext.user.loginName;
189+
generateToken(props.botEndpoint, md5(userId)).then((token: string) => {
190+
if (token) {
191+
setDirectLine(createDirectLine({ token }));
192+
}
193+
});
194+
}, []);
195+
```
196+
197+
And enable "Enhanced authentication options" can help detect client user Id change then reject the change:
198+
![bot framework client enhanced auth](./assets/EnhancedAuth.png)\
199+
For how to find this option, please refer [connect to direct line](https://docs.microsoft.com/en-us/azure/bot-service/bot-service-channel-connect-directline?view=azure-bot-service-4.0).
200+
201+
## Further reading
202+
203+
- [SharePoint Extension Development Basics](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/extensions/overview-extensions)
204+
- [Bot Framework Documentation](https://docs.botframework.com)
205+
- [Bot Basics](https://docs.microsoft.com/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0)
206+
- [Azure Bot Service Introduction](https://docs.microsoft.com/azure/bot-service/bot-service-overview-introduction?view=azure-bot-service-4.0)
207+
- [Azure Bot Service Documentation](https://docs.microsoft.com/azure/bot-service/?view=azure-bot-service-4.0)
208+
- [Channels and Bot Connector Service](https://docs.microsoft.com/en-us/azure/bot-service/bot-concepts?view=azure-bot-service-4.0)
209+
- [Restify](https://www.npmjs.com/package/restify)
210+
- [Using WebChat with Azure Bot Service’s Authentication](https://blog.botframework.com/2018/09/01/using-webchat-with-azure-bot-services-authentication/)
211+
212+
## Debug URL for testing
213+
214+
Here's a debug URL for testing around this sample.
215+
216+
```url
217+
?loadSPFX=true&debugManifestsFile=https://localhost:4321/temp/manifests.js&customActions={"f50b07b5-76a5-4e80-9cab-b4ee9a591bf6":{"location":"ClientSideExtension.ApplicationCustomizer"}}
218+
```
219+
220+
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-extensions/samples/react-bot-framework-secure" />
105 KB
Loading
199 KB
Loading
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
6+
# Dependency directories
7+
node_modules
8+
9+
# Build generated files
10+
dist
11+
lib
12+
solution
13+
temp
14+
*.sppkg
15+
16+
# Coverage directory used by tools like istanbul
17+
coverage
18+
19+
# OSX
20+
.DS_Store
21+
22+
# Visual Studio files
23+
.ntvs_analysis.dat
24+
.vs
25+
.vscode
26+
bin
27+
obj
28+
29+
# Resx Generated Code
30+
*.resx.ts
31+
32+
# Styles Generated Code
33+
*.scss.ts
34+
35+
packages/
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# Echo bot
2+
3+
## Summary
4+
5+
This bot has been created using [Bot Framework](https://dev.botframework.com). It shows how to create a simple bot that accepts input from the user and echoes it back.
6+
7+
## Prerequisites
8+
9+
- [Node.js](https://nodejs.org) version 10.14.1 or higher
10+
11+
```bash
12+
# determine node version
13+
node --version
14+
```
15+
16+
## To try this sample locally
17+
18+
- Clone the repository
19+
20+
```bash
21+
git clone [Placeholder]
22+
```
23+
24+
- In a console, navigate to [Placeholder]
25+
26+
```bash
27+
cd [Placeholder]
28+
```
29+
30+
- Install modules
31+
32+
```bash
33+
npm install
34+
```
35+
36+
- Start the bot
37+
38+
```bash
39+
npm start
40+
```
41+
42+
## Testing the bot using Bot Framework Emulator
43+
44+
[Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
45+
46+
- Install the Bot Framework Emulator version 4.3.0 or greater from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
47+
48+
### Connect to the bot using Bot Framework Emulator
49+
50+
- Launch Bot Framework Emulator
51+
- File -> Open Bot
52+
- Enter a Bot URL of `http://localhost:3978/api/messages`
53+
54+
## (Opt.) Deploy the bot to Azure
55+
56+
To learn more about deploying a bot to Azure, see [Deploy your bot to Azure](https://aka.ms/azuredeployment) for a complete list of deployment instructions.
57+
58+
## (Opt.) Testing Direct Line token generation
59+
60+
- [Connect to Direct Line](https://docs.microsoft.com/en-us/azure/bot-service/bot-service-channel-connect-directline?view=azure-bot-service-4.0)
61+
62+
- Add ‘Direct Line Secret’ to `.env`
63+
64+
```bash
65+
DirectLineSecret=YOUR_DIRECT_LINE_SECRET
66+
```
67+
68+
- Start the bot
69+
70+
```bash
71+
npm start
72+
```
73+
74+
- Open [PostMan](https://www.postman.com/) and setup a post request to http://localhost:3978/directline/token
75+
with the following json request body:
76+
77+
```json
78+
{
79+
"user": "USER_ID"
80+
}
81+
```
82+
83+
Then you can see the Direct Line token generated with YOUR_DIRECT_LINE_SECRET and USER_ID:
84+
85+
```json
86+
{
87+
"conversationId": "XXXXX",
88+
"token": "XXXXX",
89+
"expires_in": 3600
90+
}
91+
```
92+
93+
## Further reading
94+
95+
- [Bot Framework Documentation](https://docs.botframework.com)
96+
- [Bot Basics](https://docs.microsoft.com/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0)
97+
- [Activity processing](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-activity-processing?view=azure-bot-service-4.0)
98+
- [Azure Bot Service Introduction](https://docs.microsoft.com/azure/bot-service/bot-service-overview-introduction?view=azure-bot-service-4.0)
99+
- [Azure Bot Service Documentation](https://docs.microsoft.com/azure/bot-service/?view=azure-bot-service-4.0)
100+
- [Azure CLI](https://docs.microsoft.com/cli/azure/?view=azure-cli-latest)
101+
- [Azure Portal](https://portal.azure.com)
102+
- [Language Understanding using LUIS](https://docs.microsoft.com/en-us/azure/cognitive-services/luis/)
103+
- [Channels and Bot Connector Service](https://docs.microsoft.com/en-us/azure/bot-service/bot-concepts?view=azure-bot-service-4.0)
104+
- [TypeScript](https://www.typescriptlang.org)
105+
- [Restify](https://www.npmjs.com/package/restify)
106+
- [dotenv](https://www.npmjs.com/package/dotenv)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
// DO NOT MODIFY THIS CODE
5+
// This script is run as part of the Post Deploy step when
6+
// deploying the bot to Azure. It ensures the Azure Web App
7+
// is configured correctly to host a TypeScript authored bot.
8+
const fs = require('fs');
9+
const path = require('path');
10+
const replace = require('replace');
11+
const WEB_CONFIG_FILE = './web.config';
12+
13+
if (fs.existsSync(path.resolve(WEB_CONFIG_FILE))) {
14+
replace({
15+
regex: "url=\"index.js\"",
16+
replacement: "url=\"lib/index.js\"",
17+
paths: ['./web.config'],
18+
recursive: false,
19+
silent: true,
20+
})
21+
}

0 commit comments

Comments
 (0)