Hi @Anonymous
Thanks a lot for responding back..
Yes, I still face issues with SSO. Below is the code that I am using to achieve SSO. I have added the changes that was told by you to my code. I do not want to use the login button since I have already logged into my SharePoint website.
<!DOCTYPE html>
<html>
<head>
<title>Virtual Agent</title>
<script src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
<script
type="text/javascript"
src="https://alcdn.msauth.net/lib/1.2.0/js/msal.js"></script>
<script
src="https://unpkg.com/@azure/storage-blob@10.3.0/browser/azure-storage.blob.min.js"
integrity="sha384-fsfhtLyVQo3L3Bh73qgQoRR328xEeXnRGdoi53kjo1uectCfAHFfavrBBN2Nkbdf"
crossorigin="anonymous"></script>
<script type="text/javascript">
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"
)
);
</script>
<style>
html,
body {
height: 100%;
}
body {
margin: 0;
}
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
padding-top: 100px; /* Location of the box */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0, 0, 0); /* Fallback color */
background-color: rgba(0, 0, 0, 0.4); /* Black w/ opacity */
}
.modal-content {
background-color: #fefefe;
margin: auto;
padding: 10px;
border: 1px solid #888;
width: 500px;
height: 575px;
}
.close {
color: black;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #000;
text-decoration: none;
cursor: pointer;
}
.main {
margin: 18px;
border-radius: 4px;
}
div[role="form"] {
background-color: #3392ff;
}
#webchat {
position: center;
height: 530px;
width: 100%;
top: 60px;
overflow: hidden;
}
#heading {
padding-bottom: 5px;
}
h1 {
font-size: 14px;
font-family: Segoe UI;
font-style: normal;
font-weight: 600;
font-size: 14px;
line-height: 20px;
color: #f3f2f1;
letter-spacing: 0.005em;
display: table-cell;
vertical-align: middle;
padding: 13px 0px 0px 20px;
}
#login {
position: fixed;
margin-left: 150px;
}
.span {
font-weight: bold;
}
#myBtn {
position: fixed;
float: right;
outline: none;
width: 60px;
height: 80px;
margin: auto auto auto 10px;
}
button:hover {
background-color: transparent;
}
</style>
</head>
<body>
<button id="myBtn" type="button">Power Virtual Agent</button>
<button id="login" name="login" onclick="onSignInClick()" style="background-color: aliceblue">Log In</button>
<div id="myModal" class="modal">
<div class="modal-content" style="background-color: #ffd933">
<span class="close">×</span>
<div id="chatwindow">
<div id="heading">
<span class="span"><strong>Virtual Agent</strong></span>
<label id="divUser" name="divUser" style="width: 75%; height: 15px; border-color: Transparent"></label>
<label id="userName" name="userName" style="width: 75%; height: 15px; border-color: Transparent">Not logged in.</label>
</div>
<div id="webchat"></div>
</div>
</div>
</div>
<script>
var modal = document.getElementById("myModal");
var btn = document.getElementById("myBtn");
var span = document.getElementsByClassName("close")[0];
btn.onclick = function () {
modal.style.display = "block";
};
span.onclick = function () {
modal.style.display = "none";
};
window.onclick = function (event) {
if (event.target == modal) {
modal.style.display = "none";
}
};
</script>
<script>
function onSignin(idToken) {
let user = clientApplication.getAccount();
alert("User: " + JSON.stringify(user));
document.getElementById("userName").innerHTML = "Currently logged in as " + user.name;
let requestObj1 = {
scopes: ["user.read", "openid", "profile"],
};
}
function onSignInClick() {
let user = clientApplication.getAccount();
let requestObj = {
scopes: ["user.read", "openid", "profile"],
};
clientApplication.loginPopup(requestObj).then(onSignin).catch(function (error) {
console.log("error: " + error);
});
}
function getOAuthCardResourceUri(activity) {
if (
activity &&
activity.attachments &&
activity.attachments[0] &&
activity.attachments[0].contentType === "application/vnd.microsoft.card.oauth" &&
activity.attachments[0].content.tokenExchangeResource)
{
return activity.attachments[0].content.tokenExchangeResource.uri;
}
}
function exchangeTokenAsync(resourceUri) {
let user = clientApplication.getAccount();
if (user) {
console.log("User exist " + JSON.stringify(user));
let requestObj = {
scopes: [resourceUri],
};
console.log("RequestObj: " + JSON.stringify(requestObj));
return clientApplication.acquireTokenSilent(requestObj).then(function (tokenResponse) {
console.log("ExchangeTokenAsync requestObj: " + tokenResponse.accessToken);
return tokenResponse.accessToken;
})
.catch(function (error) {
console.log("ExchangeTokenAsync error: " + error);
});
} else {
return Promise.resolve(null);
}
}
async function fetchJSON(url, options = {}) {
const res = await fetch(url, {
...options,
headers: {
...options.headers,
accept: "application/json",
},
});
if (!res.ok) {
throw new Error(`Failed to fetch JSON due to ${res.status}`);
}
return await res.json();
}
</script>
<script>
var clientApplication;
(function () {
var msalConfig = {
auth: {
clientId: "<Removed Canvas Client ID>",
authority:"https://login.microsoftonline.com/<Removed Directory ID>",
},
cache: {
cacheLocation: "localStorage",
storeAuthStateInCookie: false,
},
};
if (!clientApplication) {
clientApplication = new Msal.UserAgentApplication(msalConfig);
// I get an error stating "Uncaught ReferenceError: authRedirectCallBack is not defined"
clientApplication.handleRedirectCallback(authRedirectCallBack);
//Below code will silently try to get token without popup. If there is no login already exists it will throw exception.
//As 2nd step, Login will be forced using LoginRedirect method
var newRequest = {
scopes: ["user.read", "openid", "profile"],
};
clientApplication.acquireTokenSilent(newRequest).then(function (response)
{
//Now get the user display name
let user = clientApplication.getAccount();
document.getElementById("divUser").style.display = "block";
document.getElementById("userName").innerHTML = " " + user.name;
})
.catch(function (error)
{
document.getElementById("divUser").style.display = "block";
//Now get the user display name
document.getElementById("userName").innerHTML = "Not Logged in";
$("#divPopup").modal({ backdrop: "static", keyboard: false });
setTimeout(function ()
{
//Now redirect to URI so that token will be created
clientApplication.loginRedirect(newRequest);
}, 2000);
});
}
})();
(async function main() {
var BOT_ID = "<Removed BOT ID>";
var theURL = "https://powerva.microsoft.com/api/botmanagement/v1/directline/directlinetoken?botId=" + BOT_ID;
var userId = clientApplication.account!=null && clientApplication.account.accountIdentifier != null ? clientApplication.account.accountIdentifier: (Math.random().toString() + Date.now().toString()).substr(0, 64); // Make sure this will not exceed 64 characters
console.log("Async function main userId: " + userId);
const { token } = await fetchJSON(theURL);
const directLine = window.WebChat.createDirectLine({ token });
const store = WebChat.createStore(
{},
({ dispatch }) => (next) => (action) => {
const { type } = action;
if (action.type === "DIRECT_LINE/CONNECT_FULFILLED")
{
/*dispatch({
type: "WEB_CHAT/SEND_EVENT",
payload: {
name: "startConversation",
type: "event",
value: { text: "hello" },
},
});
return next(action);*/
}
if (action.type === "DIRECT_LINE/INCOMING_ACTIVITY")
{
const activity = action.payload.activity;
let resourceUri;
if (activity.from && activity.from.role === "bot" &&(resourceUri = getOAuthCardResourceUri(activity)))
{
exchangeTokenAsync(resourceUri).then(function (token) {
if (token) {
directLine.postActivity({
type: "invoke",
name: "signin/tokenExchange",
value: {
id:activity.attachments[0].content.tokenExchangeResource.id,
connectionName:activity.attachments[0].content.connectionName,
token,
},
from: {
id: userId,
name: clientApplication.account.name,
role: "user",
},
}).subscribe((id) => {
console.log("id: " + id);
if (id === "retry")
{
console.log(`Bot was not able to handle the invoke, so display the oauthCard`);
return next(action);
}
console.log(`Else: tokenexchange successful and we do not display the oauthCard`);
},
(error) => {
console.log(`An error occurred to display the oauthCard`);
return next(action);
}
);
return;
} else return next(action);
});
} else return next(action);
} else return next(action);
}
);
const styleOptions = {
// Add styleOptions to customize Web Chat canvas
hideUploadButton: true
};
window.WebChat.renderWebChat(
{
directLine: directLine,
store,
userID: userId,
styleOptions,
},
document.getElementById("webchat")
);
})().catch((err) => console.error("An error occurred: " + err));
</script>
</body>
</html>
I am getting an error stating
"Uncaught ReferenceError: authRedirectCallBack is not defined" from the below line of code.
clientApplication.handleRedirectCallback(authRedirectCallBack);
So I just created a function
function authRedirectCallBack(error, response) {
if (error) {
console.log(error);
}
}
And I saw my name to be displayed on the label tag on the bot screen as below.
I also see the below error as well
webchat.js:2 POST https://directline.botframework.com/v3/directline/conversations/6EES0CsPuThCYcqw3AK1Cb-6/activities 502
It always entry into the id === "retry" block of code.
if (id === "retry")
{
console.log(`Bot was not able to handle the invoke, so display the oauthCard`);
return next(action);
}
I still get the login box when I start to chat with my bot.
Can you please help me solve this. Thanks.