My goal is to create an HTML page with JavaScript that runs this Microsoft Bot Framework v4 Web Chat Control
https://github.com/Microsoft/BotFramework-WebChat
As described in the comments for this StackOverflow question
Microsoft Bot Framework image size in adaptive card
I tried to follow the sample code here
https://github.com/compulim/BotFramework-MockBot
specifically
BotFramework-WebChat-master\samples\01.a.getting-started-full-bundle
but could not get it working. In the other question linked above, I was told by Microsoft support to authenticate another way:
You need to make a POST request to https://directline.botframework.com/v3/directline/tokens/generate with Authorization: Bearer in the header. Alternatively, you can use const token = directly, instead
However, in the sample code noted above, it says
To talk to your bot, you should use the token exchanged using your Direct Line secret. You should never put the Direct Line secret in the browser or client app.
If the code suggested above is JavaScript included in an HTML file, it is visible from View Source by anyone who loads the page.
Using the DirectLine secret seems to violate the rule to not expose this secret, which I've read could provide access to all conversations, not only the current one.
If the JS code in plain view uses the DirectLine secret to get a token, then uses the token to authenticate, using the token doesn't seem to accomplish anything, as the DL secret is exposed. Why not just use DL secret?
What is the Microsoft-recommended, simplest way to authenticate to the web chat control linked to above?
Thanks!
Why not just use DL secret?
As you said, this would allow access to all conversations with the bot.
If the JS code in plain view uses the DirectLine secret to get a token, then uses the token to authenticate, using the token doesn't seem to accomplish anything, as the DL secret is exposed.
Correct again. To keep your secret hidden, you'd need to set up your own token server. We don't have an official, ready-to-go sample of how how to set this up, but this sample by the Web Chat author should get you started.
If you want to write your own, the flow would basically be:
- Have your WebChat client send a request for a token to your token server
- Your token server can store the secret in a variable, so long as you don't make the code public. Have your token server reach out to
https://directline.botframework.com/v3/directline/tokens/generate
with a POST request and the header,Authorization: Bearer <YourSecret>
- Return the token that results from that request back to the WebChat client
- Your WebChat client will now have a token without ever needing to know the secret because it used your token server middleware
What is the Microsoft-recommended, simplest way to authenticate to the web chat control linked to above?
Unfortunately, there is no method that is both "simple" and "recommended". The simplest is to just use your secret, directly. This is fine if you don't care that user conversations can be exposed. The recommended way, though, is to implement your own token server.
Additional Reading on Exposing the Secret
From this GitHub issue
For purposes of this discussion, we're going to treat secrets and tokens to be the same thing. We can go into detail on those later if you want. I'll refer to them as "secret/token" for now.
To access a conversation, you need the secret/token and a conversation ID. These values are sometimes glued together, and are sometimes in separate variables. Sometimes they're in the URL, and sometimes they're stored in JavaScript in memory. These are similar to a user token, stored in a user's cookie.
In all cases, these values are accessible to a user sitting at their own computer. They can read their own URLs, they can read their own JavaScript variable state, and they can read their own cookies.
If they send any of this information to someone else, that person can impersonate them. If my bank emails me a password reset link, and I share that with someone else, that person can reset my account password and log in to my account.
Our iFrame uses URLs to pass these parameters, as that's an adequate level of security in many cases. (Have you ever visited a website, manually extracted the URL to an iFrame, sent it to someone else, and expected your session to remain private? Probably not.)
If you want additional security, you can skip the iFrame and send your own secret/token inside JS or a cookie. Your JS can extract that and send it to the Web Chat JS object. Once Web Chat has the secret/token, is exclusively uses HTTP Authorization headers to send those values to the Direct Line service.
So, leaving your secret exposed isn't a big deal, per se. However, it does allow a nefarious user to impersonate any other user.
This is default behavior because Directline needs some way to figure out who it is authenticated to talk to. The secret verifies that the client (Web Chat) is okay. But what verifies that the user is? A user id? But then any user could set their own user id and impersonate somebody else. The only way to really secure this is to implement something on your own end that uses the secret to get a Directline token, then passes that back to the Web Chat client.
Also, to get conversation data, somebody would need both the secret and the conversation id. The likelihood of figuring out the conversation id is pretty small.
Generally speaking though, this security is only a concern if you're trying to persist user data. If your users would start a new conversation each time they open the bot, you can just generate a unique user id and not worry if the secret is exposed.
来源:https://stackoverflow.com/questions/56331507/what-is-the-correct-way-to-authenticate-from-javascript-in-an-html-file-to-the-m