Trick to SSO an on-prem page with Office 365 and ADFS

Hi,

As you might have noticed, if your company has a 365 environment, you’re unlikely having an SSO with it. Most of the times, when you enter the URL of your SharePoint Online landing page, say : https://contoso.sharepoint.com/, you are prompted to enter your e-mail address. If you use the same e-mail address for a Microsoft Account and an Organizational Account, you’ll get a second prompt invite to choose the type of account you want to sign in with.

If you need to integrate with 365 from an on-prem page and don’t want your users to be prompted, there is a means, providing you’re in a federated environment. The purpose of the initial login prompt is to inform 365 about the target domain you want to visit. By giving your e-mail address, the part behind the @ informs 365 about it, and 365 checks whether or not you have established a federation. In such case, you’re redirected to the login page of your ADFS.

All this little dance can be avoided by using SmartLinks. SmartLinks allow you to specify ithe target domain n the URL, and a reply page. So, in JavaScript, one can inject a hidden iframe into the page, make it point to 365 with a SmartLink and start doing something once the transparent authentication has been done via this iframe.

Here is a code example demonstrating this, with a Yammer Embed integration:

<!DOCTYPE html>
<html>
<body>
<div id="embedded-feed" style="height:800px;width:500px;"></div>
<script src="https://code.jquery.com/jquery-3.0.0.min.js" integrity="sha256-JmvOoLtYsmqlsWxa7mDSLMwa6dZ9rrIdtrrVYRnDRH0=" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://c64.assets-yammer.com/assets/platform_embed.js"></script>
<script type="text/javascript">
if (document.cookie.indexOf('embedPreauthDone') == -1) {
//perform pre-auth with an iframe that targets SPO
//we use a smartlink to indicate our ADFS server to 365.
try {
var frame = document.createElement("frame");
if (frame.attachEvent) {
frame.attachEvent("onload", function () {
doEmbed();
});
}
else {
frame.addEventListener("load", function () {
doEmbed();
});
}
frame.setAttribute('src', 'https://login.microsoftonline.com/login.srf?wa=wsignin1.0&whr=contoso.com
&wreply=https%3A%2F%2Fcontoso.sharepoint.com');
document.body.appendChild(frame);
}
catch (err) {
console.log('error');
doEmbed(); //if SSO doesn't work, fallback to embed
}
}
else {
doEmbed();
}

//we create the cookie whether or not SSO worked.
document.cookie = "embedPreauthDone=1";
//Actual embed
function doEmbed(){
$("#embedded-feed").empty();
yam.connect.embedFeed({
"feedType": "open-graph",
"config": {
"use_sso": true,
"showOpenGraphPreview": false,
"defaultToCanonical": false,
"hideNetworkName": false
},
"objectProperties": {
"url": "https://urlofyouronprempage",
"type": "page",
"fetch": true,
"private": false,
"ignore_canonical_url": false
},
"container": "#embedded-feed"
});
}
</script>
</body>
</html>

In this example, I start by checking the presence of a cookie. The goal is to avoid injecting the iframe at every page refresh or for every page belonging to the same domain. By the way, this injection should be done from a master page for instance so that it is available for all the pages. If the cookie doesn’t exist yet, inject the iframe and notice the smartilnk where I specify consoto.com and the reply url. We also attach an onload event which is supposed to trigger once the iframe finishes loading. We call the doEmbed() function from that event handler. Of course, here you could call whatever you need to do with 365, embed is just an example.
Beware that the onload event might be triggered multiple times by the browser…including before the iframe has finished loading, which in that case would trigger your post-authenticatin code to fail as the authentication isn’t performed yet…So the post-authentication code should be robust enough to execute multiple times. Last time it will be triggered will be the right one for sure. In this case, that’s why I added $(“#embedded-feed”).empty() in order to clear the DIV.
Admittedly, it’s not the nicest way of getting a transparent login but it works providing you use a browser that supports integrated authentication with ADFS.

How to test?

Clear all your cookies, close your browser and navigate to your page. The embed control should automatically target your Yammer network without asking to login.

Happy Coding!

Advertisements

About Stephane Eyskens

Office 365, Azure PaaS and SharePoint platform expert
This entry was posted in Office 365 and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s