|
| 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 | + |
| 20 | + |
| 21 | +## Used SharePoint Framework Version |
| 22 | + |
| 23 | + |
| 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 | +\ |
| 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" /> |
0 commit comments