3

We have recently finished creating an e-learning course for a client, and are planning on deploying it to production soon. They have their own web-server with their own domain, but would like us to do the hosting of the course on our Rails-powered LMS running on our server.

The course is quite long, so it requires registration in order to pause and resume at any time.

Now, they would also like for the users to visit their domain, foo.com, navigate around, and launch the course. The course launcher page then embeds our page in an iframe, from app.bar.com.

This of course causes some issues with the session, because of third-party cookies and so on. I've investigated and found tons of different hacks and solutions, but nothing so far has worked.

  1. The P3P-header, as I understand it, is not really in use any more, but I've added a dummy header, similar to Facebook and Google. (P3P: CP="This site does not have a p3p policy.")

  2. I've also looked into CORS, with the Access-Control-Allow-Credentials: true which sounded promising, but did nothing. I might have misconfigured it, but would like to know if it is at all possible before investing too much time.

  3. Some sites mention that it works if the browser has communicated with app.bar.com previously, so I tried loading an image from app.bar.com before the iframe, but that was either not enough, or yet another hack that has later been fixed.

I understand that blocking third-party cookies is usually a good thing for preventing tracking of users. The people who are meant to take the course comes from all over the world, and explaining how to disable third-party cookie blocking for each of those is not an option.

Another thing I considered was getting a subdomain from the client pointing to our server, course.foo.com or something similar, and an iframe requesting data from there would work. I would like to know if it would work first, before trying to get that request through.

There's no need for any kind of communication between the domains, as most of the other JavaScript solutions seem to assume, other than making sure the cookies are set and sent to our LMS.

I have full control of our server and can change mostly everything there, if needed. For the client server I only have limited access to the HTML.

EDIT: Just noticed that in IE9 at least, it works fine with the P3P-header.

PerfectlyNormal
  • 4,182
  • 2
  • 35
  • 47
  • I have similar issue. If I'm able to trap the POST without a cookie and share a link to display the form in a window directly on my site, then that would work for me... (http://stackoverflow.com/questions/29311728/show-error-message-after-form-post-if-client-browser-doesnt-send-cookie) – user1322092 Apr 03 '15 at 21:43

2 Answers2

4

The safest way is indeed to run your app on a subdomain of your customers' domain, ie. course.foo.com.

P3P has never gained much acceptance; the "communicate with the site first"-part you allude to in 3) probably refers to a Safari loophole that has since been closed.

CORS does not apply in your case. It would be relevant if you wanted to interact from the customers parent frame with the course site, eg. make AJAX requests or load resources such as fonts.

So, if you wish user agents to treat the cookies as first-party cookies,

  1. host the site on course.foo.com
  2. change the settings in config/initializers/session_store.rb to

    Rails.application.config.session_store :cookie_store, 
                                           key: '_course_session',
                                           domain: 'foo.com'
    

By default, Rails would set the cookie domain to course.foo.com, which is a different origin than foo.com. But the reverse works — by setting the cookie domain to just foo.com, it is accessible to and the same origin as every subdomain, such as www.foo.com or course.foo.com.

There is one potential security consideration to this, though: your course app cookies are now available to your customers' existing site as well, so a security issue there can now compromise your apps session cookies as well.

Community
  • 1
  • 1
janfoeh
  • 10,243
  • 2
  • 31
  • 56
  • 1
    I believe you would actually want to set the domain to `".foo.com"`. Otherwise, it should be treated as a fully qualified name and the cookie should not be sent. – David Hoelzer Mar 24 '15 at 14:49
  • 1
    @DavidHoelzer that was revised with [RFC 6295](http://tools.ietf.org/html/rfc6265#section-4.1.2.3): _Note that a leading %x2E (“.”), if present, is ignored even though that character is not permitted_. Domains without leading dot apply to subdomains — pretty much the way IE has handled it since the beginning. – janfoeh Mar 24 '15 at 16:23
  • Thank you! I missed that change! – David Hoelzer Mar 24 '15 at 19:26
0

Did you add the following headers on the other domain:

'Access-Control-Allow-Origin:*'

or idealy only set the domain of the source. If you read my comment, it seems that you want to pass variables stored in cookies, so why not use encryption based on a unique key of the user and pass the data via GET:

<iframe src="http://mywebsite.com?user_id=[id]&user_data=[encrypted_data_goeshere]">

Of course you have think of security and not allow people to manipulate this url to exploit your program.

Neo
  • 11,078
  • 2
  • 68
  • 79
  • Which side should that be added to? I don't have the ability to alter the headers the client sends out, only on our side… – PerfectlyNormal Mar 30 '15 at 18:25
  • This should be your website server's header when it's being loaded in your clients iframe, and also in any Ajax/JS requests. But forget about this, you're going about this all wrong. Explain to me what exactly needs to be passed between the domains, the session cookie on his site has no meaning on your server, so you're trying to pass a variable that is stored in the sessions? This has nothing to do with same-origin policy. The session is stored on the server side and there is only a cookie that acts as an Unique ID to look it up. The actual data is not stored in the cookies! – Neo Mar 30 '15 at 21:26
  • There's not really anything that needs to be passed between the domains. The containing page (hosted by the client) is just a dumb static HTML container, and the contents of the iframe (hosted by us) contains the course launcher and the sign-in bit. The problem is that if visitors fill out the sign in form in the iframe, our server sends the header to set the cookie with the session ID, but the visiting browser refuses to send it back when loading new pages in the iframe, so staying signed in does not work. – PerfectlyNormal Mar 31 '15 at 08:24
  • I think if you load the page outside the iframe and try to sign in you will have the same issue. Let me know If I'm wrong, did you try that? You are posting a form in an iframe from and to the same exact domain/subdomain? – Neo Apr 01 '15 at 02:44
  • If I try to sign in in the iframe, and then visit the page outside the iframe, I'm still signed out. If I visit the page outside the iframe, then sign in, it works as it should. The page in the iframe is posting from and to the same exact domain, – PerfectlyNormal Apr 01 '15 at 07:19
  • Do either of these use HTTPS? Also can you verify that the cookie sessions are set or not? It should be fairly simple to figure out if the issue is client side or server side. Also make sure you don't use the sandbox attribute in the iframe html tag. What does your for look like? Does it have a target attribute. Can you show example code? – Neo Apr 01 '15 at 08:23