Hi,
I am trying to connect SSO in PVA on the Sharepoint website. I see the below error on the chrome console.
I see a syntax error from the below line of code. I am following the SSO configuration by the doc provided below: "https://docs.microsoft.com/en-us/power-virtual-agents/configure-sso"
The below code is from the doc.
var userID = clientApplication.account?.accountIdentifier != null ? ("Your-customized-prefix-max-20-characters" + clientApplication.account.accountIdentifier).substr(0,64) : (Math.random().toString() + Date.now().toString().substr(0,64)
I had posted by query before as well but no luck.. https://powerusers.microsoft.com/t5/General/How-to-configure-Single-Sign-On-in-PVA-with-Sharepoint-a...
Can anyone please help me out here?
Regards,
Hemanth
Hi @HemanthN ,
Try to change the phrase "your prefix...".
var userID = clientApplication.account?.accountIdentifier != null ? ("mypva" + clientApplication.account.accountIdentifier).substr(0,64) : (Math.random().toString() + Date.now().toString().substr(0,64)
Did you change the variables e codes that contain ClientId and BotId?
Like
var BOT_ID = "<BOT ID>";
Hi @renatoromao ,
I have added the bot id,client id of the canvas app and the tenant id/Directory ID were it is required as per the code.
And also we have created 2 app registrations on the Azure AD one for Authentication and the other for SSO.
On adding the below code as you have suggested. I still see the same syntax error.
Regards,
Hemanth
Hi Hemanth,
I think it is because there is a missing close bracket in the code sample in SSO document. Thank you for raising that issue out. You can change the line of code to below to fix the issue.
var userId = clientApplication.account?.accountIdentifier != null ?
("You-customized-prefix" + clientApplication.account.accountIdentifier).substr(0, 64)
: (Math.random().toString() + Date.now().toString()).substr(0,64);
see the hightlighted close bracket after Date.Now().toString().
Best Regards
Bo
Hi @BoLi ,
Thank you for your response. I have tried added the closed bracket but i still see the same error. Kindly have a look at the attached snapshot for your reference.
Regards,
Hemanth
Hi Hemanth,
sorry that there are some issue in the document and our doc writer is updating that. Meanwhile you can use the sample sso code on github to unblock you.
Thanks
Bo
@HemanthN we also updated our documentation example. Let us know if these solved the issue for you.
https://docs.microsoft.com/en-us/power-virtual-agents/configure-sso
Thanks
Hi @CleberM / @BoLi / @renatoromao ,
I am still not able to configure SSO. I am try to achieve this on a Sharepoint Webpage. I have posted the issue through multiple thread but no luck.
I am still being asked to pass the token id.
Can you please help me out with this? Any help is much appreciated.
https://powerusers.microsoft.com/t5/General/PVA-SSO-Configuration/td-p/650994/jump-to/first-unread-m...
Below is the code that i am using. I have added a button on the Sharepoint site so the chat bot come up in clicking on it. The same Home page URL were the button is added is the redirect URL that is added on Azure AD App registration.
<!DOCTYPE html>
<html>
<head>
<title>Contoso Sample Web Chat</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<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>
body {
font-family: Arial, Helvetica, sans-serif;
}
/* The Modal (background) */
.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 */
.modal-content {
background-color: #fefefe;
margin: auto;
padding: 10px;
border: 1px solid #888;
width: 500px;
height: 575px;
}
/* The Close Button */
.close {
color: black;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #000;
text-decoration: none;
cursor: pointer;
}
html, body {
height: 100%;
}
body {
margin: 0;
}
div[role="form"] {
background-color: #3392FF;
}
#webchat {
position: center;
height: 530px;
width: 100%;
top: 60px;
overflow: hidden;
}
.heading{
padding-bottom: 5px;
}
.span{
font-weight: bold;
}
</style>
</head>
<body>
<!--Button and ChatBot View-->
<button id="myBtn" type="button" >Power Virtual Agent</button>
<div id="myModal" class="modal">
<!-- Modal content -->
<div class="modal-content" style=" background-color: #FFD933">
<span class="close">×</span>
<div class="chat">
<div class="heading">
<!-- Change the h1 text to change the bot name -->
<img src="heading image added here" width="42" height="30" alt="logo">
<span class="span"><strong>Heading</strong></span>
</div>
<div id="webchat" role="main"></div><br>
</div>
</div>
</div>
<!--Button code begins here-->
<script>
// Get the modal
var modal = document.getElementById("myModal");
// Get the button that opens the modal
var btn = document.getElementById("myBtn");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
// When the user clicks the button, open the modal
btn.onclick = function () {
modal.style.display = "block";
}
// When the user clicks on <span> (x), close the modal
span.onclick = function () {
modal.style.display = "none";
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function (event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
</script>
<!--Button code ends here-->
<!--SSO Code is added here-->
<script>
function getOAuthCardResourceUri(activity)
{
//alert("activity var inside getOAuthCardResourceUri: " + JSON.stringify(activity));
if (activity && activity.attachments && activity.attachments[0] && activity.attachments[0].contentType === 'application/vnd.microsoft.card.oauth' && activity.attachments[0].content.tokenExchangeResource)
{
// asking for token exchange with AAD
//alert("Inside if condition of activity: " + JSON.stringify(activity.attachments[0].content.tokenExchangeResource.uri));
return activity.attachments[0].content.tokenExchangeResource.uri;
}
}
function exchangeTokenAsync(resourceUri)
{
let user = clientApplication.getAccount();
//alert("user value inside exchangeTokenAsync: " + JSON.stringify(user));
debugger;
if (user)
{
let requestObj =
{
scopes: [resourceUri]
};
//alert("requestObj inside exchangeTokenAsync: " + JSON.stringify(requestObj));
return clientApplication.acquireTokenSilent(requestObj)
.then(function (tokenResponse)
{
return tokenResponse.accessToken;
})
.catch(function (error)
{
console.log(error);
});
}
else
{
return Promise.resolve(null);
}
}
async function fetchJSON(url, options = {})
{
//alert("url inside fetchJSON: " + JSON.stringify(url));
const res = await fetch(url, {
...options,
headers:
{
...options.headers,
accept: 'application/json'
}
});
//alert("res inside fetchJSON: " + JSON.stringify(res));
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: '<Client Id of canvas>',
authority: 'https://login.microsoftonline.com/<Directory ID>'
},
cache:
{
cacheLocation: 'localStorage',
storeAuthStateInCookie: false
}
};
if (!clientApplication)
{
//alert("msalConfig: " + JSON.stringify(msalConfig));
clientApplication = new Msal.UserAgentApplication(msalConfig);
//alert("clientApplication inside if: " + JSON.stringify(clientApplication));
}
}());
(async function main() {
// Add your BOT ID below
var BOT_ID = "ABC";
var theURL = "https://powerva.microsoft.com/api/botmanagement/v1/directline/directlinetoken?botId=" + BOT_ID;
const styleOptions = {
botAvatarImage: "BOT image",
userAvatarImage: "user image",
hideUploadButton: true
};
const { token } = await fetchJSON(theURL);
const directLine = window.WebChat.createDirectLine({ token });
var userID = clientApplication.account?.accountIdentifier != null ?
("mypva" + clientApplication.account.accountIdentifier).substr(0, 64)
: (Math.random().toString() + Date.now().toString()).substr(0,64);
//alert("userID inside async function is " + userID);
//alert("Token:" + JSON.stringify(token));
const store = window.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))) {
//alert("Inside if DIRECT_LINE/INCOMING_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 => {
if (id === 'retry') {
// bot was not able to handle the invoke, so display the oauthCard
return next(action);
}
// else: tokenexchange successful and we do not display the oauthCard
},
error => {
// an error occurred to display the oauthCard
return next(action);
}
);
return;
} else
return next(action);
});
} else
return next(action);
} else
return next(action);
});
window.WebChat.renderWebChat({
directLine: directLine,
store,
userID: userID,
styleOptions
},
document.getElementById('webchat')
);
})().catch(err => console.error("An error occurred: " + err));
</script>
<!--SSO Code ends here-->
</body>
</html>
Regards,
Hemanth
Thank you Hemanth, it is required to pass a token to PVA for exchange in order for SSO to work. Are you able to do SSO use the sample file on github?
Suggest process to debug the issue
1. try to talk to your bot in PVA demo website and check if it can login successfully without SSO.
2. If #1 works, config the token exchange url field based on the SSO document.
3. Download the sample SSO test file on github and check if SSO works. If it does not work, you need to debug the code and see which steps failed the calls. Usually how SSO works is like this. When some user loggined to customer canvas, AAD will issue a login token and the client will call AAD to get an On-behalf-of token based on the login token. This On-behalf-of token will then be passed to PVA service and they will exchange this for a user access token. If you failed any steps above, the call will fail.
So you need to debug more into the code and tell what steps failed the call and what the error is so that we can help you
Join digitally, March 2–4, 2021 to explore new tech that's ready to implement. Experience the keynote in mixed reality through AltspaceVR!
Congratulations to our Season 1 2021 Super User Crew!
View articles posted by fellow community members on the Power Virtual Agents Community Blog!
User | Count |
---|---|
4 | |
3 | |
2 | |
1 | |
1 |