Wednesday, July 22, 2015

Problem with X-Frame-Options: SAMEORIGIN in Yammer embedded feed

When you add Yammer embed feed to your Sharepoint Online site you may have the following problem: if user didn’t complete Yammer signup then instead of the feed he or she will see empty box inside iframe. To be more precise you may face with this problem if your site is running on any other platform or technology, but as I faced with it on Sharepoint Online, I decided to mentioned it here.

Let’s see it in more details. Embedded feed is loaded using the following code:

   1: <script src="https://c64.assets-yammer.com/assets/platform_embed.js"
   2: type="text/javascript"></script>
   1:  
   2: <div id="embedded-feed" style="height:800px;"></div>
   3: <script type="text/javascript">
   4:     yam.connect.embedFeed({ container: '#embedded-feed', network: 'example.com'});
</script>

When user has active Yammer profile it shows the Yammer feed in iframe which is added into div with specified identifier. However when user doesn’t have profile yet, empty page will be shown. The reason of this problem is the following: when user didn’t complete Yammer signup and iframe loads feed page which URL looks like this:

https://www.yammer.com/platform_embed/feed?container=%23embedded-feed&network=example.com&network_permalink=example.com&bust=…

(instead of example.com you will have your domain here and bust will have identifier which corresponds to the current user), it redirects user to the following page:

https://www.yammer.com/example.com/signup/complete_signup?activation_code=…&user_id=…

One of the HTTP headers returned in response for this page is the following:

X-Frame-Options: SAMEORIGIN

This header tells to the browser that remote site can’t be loaded in iframe if parent page belongs to different domain (different from yammer.com).

In order to tell user about that he or she should complete signup first the following script may be used:

   1:  
   2: var g_YammerCompleteSignup_CompletePolling = false;
   3: function YammerCompleteSignup(){
   4:     if (jQuery("iframe#embed-feed").length) {
   5:         try {
   6:             var url = jQuery("iframe#embed-feed").attr("src");
   7: jQuery("#embedded-feed").prepend("<span style='background: url(/_layouts/images/info16by16.gif) " +
   8:     "no-repeat; display: inline-block; background-size: 16px 16px; height: 16px; " +
   9:     "padding-left: 18px;'><span style='font-size: 12px; height: 16px; display: table-cell; " +
  10:     "vertical-align: middle;'>Yammer feed will be empty if you don't have Yammer account yet. " +
  11:     "Click <a href='" + url + "' target='_blank'>here</a> in order to complete signup and then " +
  12:     "refresh this page.</span></span>");
  13:         } finally {
  14:             g_YammerCompleteSignup_CompletePolling= true;
  15:         }
  16:     }
  17:     
  18:     if (g_YammerCompleteSignup_CompletePolling) {
  19:         return;
  20:     }
  21:  
  22:     setTimeout(YammerCompleteSignup, 2000);
  23: }

It starts polling the DOM and when iframe is added by yam.connect.embedFeed() call, it reads its src and uses it when add informational notice above the iframe, which looks like this:

image

The drawback of this approach is that this text will be shown both for users which already completed signup and for users which didn’t do that.

No comments:

Post a Comment