Skip to content

Commit 0487f7e

Browse files
authored
Adding SSO index.html file
1 parent 11fce9c commit 0487f7e

1 file changed

Lines changed: 278 additions & 0 deletions

File tree

  • BuildYourOwnCanvasSamples/3.single-sign-on
Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>Contoso Sample Web Chat</title>
5+
<script src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
6+
<script type="text/javascript" src="https://alcdn.msauth.net/lib/1.2.0/js/msal.js"></script>
7+
<script src="https://unpkg.com/@azure/storage-blob@10.3.0/browser/azure-storage.blob.min.js"
8+
integrity="sha384-fsfhtLyVQo3L3Bh73qgQoRR328xEeXnRGdoi53kjo1uectCfAHFfavrBBN2Nkbdf"
9+
crossorigin="anonymous"></script>
10+
<script type="text/javascript">
11+
if (typeof Msal === 'undefined') document.write(unescape("%3Cscript src='https://alcdn.msftauth.net/lib/1.2.0/js/msal.js' type='text/javascript' %3E%3C/script%3E"));
12+
</script>
13+
14+
<style>
15+
html, body {
16+
height: 100%;
17+
}
18+
19+
body {
20+
margin: 0;
21+
}
22+
23+
h1 {
24+
font-size: 16px;
25+
font-family: Segoe UI;
26+
line-height: 20px;
27+
color: whitesmoke;
28+
display: table-cell;
29+
padding: 13px 0px 0px 20px;
30+
}
31+
32+
#heading {
33+
background-color: black;
34+
height: 50px;
35+
}
36+
37+
.main {
38+
margin: 18px;
39+
border-radius: 4px;
40+
}
41+
42+
div[role="form"]{
43+
background-color: black;
44+
}
45+
46+
#webchat {
47+
position: fixed;
48+
height: calc(100% - 50px);
49+
width: 100%;
50+
top: 50px;
51+
overflow: hidden;
52+
}
53+
#heading {
54+
background-color: black;
55+
background-repeat: no-repeat;
56+
background-size: cover;
57+
background-attachment: fixed;
58+
background-position: center;
59+
height: 50px;
60+
width: 100%;
61+
overflow: hidden;
62+
position: fixed;
63+
}
64+
65+
h1 {
66+
font-size: 14px;
67+
font-family: Segoe UI;
68+
font-style: normal;
69+
font-weight: 600;
70+
font-size: 14px;
71+
line-height: 20px;
72+
color: #F3F2F1;
73+
letter-spacing: 0.005em;
74+
display: table-cell;
75+
vertical-align: middle;
76+
padding: 13px 0px 0px 20px;
77+
}
78+
79+
#chatwindow {
80+
height: 80%;
81+
width: 100%;
82+
overflow: hidden;
83+
position: fixed;
84+
}
85+
86+
#loginButton {
87+
88+
height: 100px;
89+
width: 100%;
90+
position: fixed;
91+
}
92+
</style>
93+
94+
</head>
95+
<body>
96+
<div id="chatwindow">
97+
<div id="heading">
98+
<div><span>SSO Test Bot</span></div>
99+
</div>
100+
<div style="z-index: 100;position: absolute;margin-top: 50px;width: 100%;">
101+
<div>
102+
<label id="userName" name="userName" style="width:75%;height:15px;border-color: Transparent;">Not logged in.</label>
103+
<button id="login" name="login" onclick="onSignInClick()" style="float: right;background-color: aliceblue;">Log In</button>
104+
</div>
105+
</div>
106+
<div id="webchat">
107+
</div>
108+
109+
</div>
110+
111+
<script>
112+
function onSignin(idToken) {
113+
let user = clientApplication.getAccount();
114+
document.getElementById("userName").innerHTML = "Currently logged in as " + user.name;
115+
let requestObj1 = {
116+
scopes: ["user.read", 'openid', 'profile']
117+
};
118+
}
119+
120+
function onSignInClick() {
121+
let requestObj = {
122+
scopes: ["user.read", 'openid', 'profile']
123+
};
124+
125+
clientApplication.loginPopup(requestObj).then(onSignin).catch(function (error) {console.log(error) });
126+
}
127+
128+
function getOAuthCardResourceUri(activity) {
129+
if (activity &&
130+
activity.attachments &&
131+
activity.attachments[0] &&
132+
activity.attachments[0].contentType === 'application/vnd.microsoft.card.oauth' &&
133+
activity.attachments[0].content.tokenExchangeResource) {
134+
// asking for token exchange with AAD
135+
return activity.attachments[0].content.tokenExchangeResource.uri;
136+
}
137+
}
138+
139+
function exchangeTokenAsync(resourceUri) {
140+
let user = clientApplication.getAccount();
141+
if (user) {
142+
let requestObj = {
143+
scopes: [resourceUri]
144+
};
145+
return clientApplication.acquireTokenSilent(requestObj)
146+
.then(function (tokenResponse) {
147+
return tokenResponse.accessToken;
148+
})
149+
.catch(function (error) {
150+
console.log(error);
151+
});
152+
}
153+
else {
154+
return Promise.resolve(null);
155+
}
156+
}
157+
158+
async function fetchJSON(url, options = {}) {
159+
const res = await fetch(url, {
160+
...options,
161+
headers: {
162+
...options.headers,
163+
accept: 'application/json'
164+
}
165+
});
166+
167+
if (!res.ok) {
168+
throw new Error(`Failed to fetch JSON due to ${res.status}`);
169+
}
170+
171+
return await res.json();
172+
}
173+
</script>
174+
175+
<script>
176+
var clientApplication;
177+
(function (){
178+
var msalConfig = {
179+
auth: {
180+
clientId: '<CANVAS CLIENT APP ID>',
181+
authority: 'https://login.microsoftonline.com/<TENANT ID>'
182+
},
183+
cache: {
184+
cacheLocation: 'localStorage',
185+
storeAuthStateInCookie: false
186+
}
187+
};
188+
if (!clientApplication) {
189+
clientApplication = new Msal.UserAgentApplication(msalConfig);
190+
}
191+
} ());
192+
193+
(async function main() {
194+
195+
// Add your BOT ID below
196+
var BOT_ID = "<BOT ID>";
197+
var theURL = "https://bots.ppe.customercareintelligence.net/api/botmanagement/v1/directline/directlinetoken?botId=" + BOT_ID;
198+
199+
const { token } = await fetchJSON(theURL);
200+
const directLine = window.WebChat.createDirectLine({ token });
201+
const store = WebChat.createStore({}, ({ dispatch }) => next => action => {
202+
const { type } = action;
203+
if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
204+
dispatch({
205+
type: 'WEB_CHAT/SEND_EVENT',
206+
payload: {
207+
name: 'startConversation',
208+
type: 'event',
209+
value: { text: "hello" }
210+
}
211+
});
212+
return next(action);
213+
}
214+
if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY') {
215+
const activity = action.payload.activity;
216+
let resourceUri;
217+
if (activity.from && activity.from.role === 'bot' &&
218+
(resourceUri = getOAuthCardResourceUri(activity))) {
219+
exchangeTokenAsync(resourceUri).then(function (token) {
220+
if (token) {
221+
directLine.postActivity({
222+
type: 'invoke',
223+
name: 'signin/tokenExchange',
224+
value: {
225+
id: activity.attachments[0].content.tokenExchangeResource.id,
226+
connectionName: activity.attachments[0].content.connectionName,
227+
token
228+
},
229+
"from": {
230+
id: clientApplication.account.accountIdentifier,
231+
name: clientApplication.account.name,
232+
role: "user"
233+
}
234+
}).subscribe(
235+
id => {
236+
if (id === 'retry') {
237+
// bot was not able to handle the invoke, so display the oauthCard
238+
return next(action);
239+
}
240+
// else: tokenexchange successful and we do not display the oauthCard
241+
},
242+
error => {
243+
// an error occurred to display the oauthCard
244+
return next(action);
245+
}
246+
);
247+
return;
248+
}
249+
else
250+
return next(action);
251+
});
252+
}
253+
else
254+
return next(action);
255+
}
256+
else
257+
return next(action);
258+
});
259+
260+
const styleOptions = {
261+
262+
// Add styleOptions to customize Web Chat canvas
263+
hideUploadButton: true
264+
};
265+
266+
267+
window.WebChat.renderWebChat(
268+
{
269+
directLine: directLine,
270+
store,
271+
styleOptions
272+
},
273+
document.getElementById('webchat')
274+
);
275+
})().catch(err => console.error("An error occurred: " + err));
276+
</script>
277+
</body>
278+
</html>

0 commit comments

Comments
 (0)