Posted in Web Development

Getting Around Browser’s Same Origin Policy (SOP) With Proxies, Script Injection , JSONP and CORS

If you work with Web Development or Javascript / Ajax a lot you must have come across browser’s same origin policy or SOP. Same Origin Policy or SOP is a security concept in which documents retrieved from distinct origins are isolated from each other. This is quite strictly implemented by almost all major browsers today.

An origin is defined by a host name, protocol and the port. For example a document located on http://example.com/page.html is not allowed to access the DOM of the document located on https://example.com/test.html because they are on two different protocols (http vs https).

Same restriction applies if the host name (example.com) and the port (80) are also different from each other. The same-origin policy differs between APIs, the intent is to let users visit untrusted web sites without those web sites interfering with the user’s session with honest web sites.

Why do we need SOP?

Modern web applications that extensively depend on cookies to maintain sensitive information i.e. authenticated user sessions, as servers act based on the cookie information to reveal sensitive information or take actions.

A strict separation between content provided by unrelated sites must be maintained on the client side to prevent the loss of data confidentiality or integrity. Wihtout an SOP policy strictly in place users will be exposed to Cross Site Request Forgery (CSRF) or Cross Site Scripting (XSS)

Effect on XMLHttpRequest

Standardizing of XMLHttpRequest object across major browsers was a big deal. This really kick started the wide adaption of Ajax and a zillion Ajax Applications and libraries sprung up.

XMLHttpRequest specification defines an API that provides scripted client functionality for transferring data between a client and a server.

SOP particularly is a problem for Ajax based applications. A lot of people like to separate their content like we do. In particular we like to separate our static content (images/ javascript files) from our dynamic content. Specially when our dynamic content is of different types and comes from different places.

Imagine a web page or portal which has different sections on the page i.e. news feed, head lines, weather information, stock information etc. It will be quite rare for all that information to come from same origin, unless you have a huge monolithic backend.

With browsers strictly implementing SOP , JavaScript programmers have had a big problem. If you have a very big javascript program which have multiple javascript file and html files you will be hit in two places

  1. You will be prevented from loading of all the java script pieces from a different domain
  2. Javascript making dynamic calls to remote servlets or backends across different domains will be blocked by the browsers or subject to CORS protocol.

How to get around SOP

Good news is, there are plenty of ways around it. W3C has also published an RFC addressing SOP issues which is getting more and more standard support in browsers. We have basically the following options

1. Proxy and Reverse Proxy

The first option is to play by the rules of SOP and create a proxy on your local server. You can then make HTTP calls to your local server and have it go fetch the data from the remote server. This works because the code running on your web server is not subject to SOP restrictions. Only the client-side code is.

2. Dynamically Inject the ‘src’ of a <script> tag

Another option is to dynamically load JavaScript into a <script> tag. Client-side JavaScript can manipulate <script> tags, just like any other element in the HTML Document Object Model (DOM).

Client-side code can set the src attribute of a <script> tag to automatically download and execute new JavaScript into the page. This strategy is not subject to SOP restrictions. So you can effectively use it to load JavaScript. One way to do this is to completely inject a <script> tag into your DOM like below

 var head= document.getElementsByTagName('head')[0];
 var script= document.createElement('script');
 script.type= 'text/javascript';
 script.src= 'helper.js';
 head.appendChild(script);

Other approach could be to dynamically set just the ‘src’ attribute like below

   <script id='loadarea' type='text/javascript'/>

   document.getElementById('loadarea').src= 'helper.js';

Dynamically loading the JavaScript into a script tag solves the SOP issue but introduces another.

When you use this method to load JavaScript, although the browser retrieves the code asynchronously, it doesn’t notify you when it’s finished. Instead, it simply executes the new JavaScript. However, by definition, JSON cannot contain executable code. Put the two together and you’ll realize that you can’t load plain JSON data using a ; tag.

3. JSONP (JSON with Padding)

If you use JSON in your application, you can make use of JSONP (JSON with padding). In this technique you set the src of a script tag to be a remote JSON call, which returns the JSON data which is prefixed with a function name in the current browser’s context. This in turn makes the browser execute that function and hence allows you to exchange JSON data across origins. Consider the following

 <script type="text/javascript"
    src="http://static.example.com/GetUser?UserId=1234>
 </script>

You can see the src of the above script tag is referring to a dynamic resource on another origin. Using the JSOP technique will return the following

process({"Name": "Usama", "Id" : 1234)
process is a function which needs to be defined in the current page’s context. Which will cause the browser to execute this function Similarly the server can also return any java script expression which can be interpreted into valid js code. You can see that this requires slight modification on the server side. The server needs to know which functions are available on the client side and can be returned as the padding to the json data. However this is an effective technique to get around exchanging JSON data around SOP policy

4. Cross-Origin Resource Sharing (CORS)

Thankfully you don’t have to hack your way around the SOP most of the times these days. All major browsers either completely support CORS protocol or are in the middle of supporting it. You don’t have to bang your head around proxies or script injections anymore. W3C has standardized CORS. You of course need to make sone changes to your servers to recognize the appropriate CORS headers in the request and reply to them, in -order for the user agents (browsers) to allow these cross origin request.

Here is a brief introduction of how this works. Lets say your page is located on http://www.example.com/page.html and doing requests to static.example.com

  • For simple cross origin methods like GET or POST , the browser adds an extra header to the request called “Origin”. Which includes the origin the request is originating from. i.e.
Origin : http://example.com
  • Server should recognize the “Origin” header and send another header back in the response called Access-Control-Allow-Origin
    Access-Control-Allow-Origin: http://example.com

    This tells the browser that the server (static.example.com) has allowed the request from the cross origin (example.com) , if this header is absent or the value doesn’t match , browser will disallow this request. Server can also decide to send the value ‘*’ in this header to indicate it allows ALL domains.

  • For non-simple requests (i.e. PUT or DELETE), The browser will add another header Access-Control-Request-Method
 Access-Control-Request-Method: PUT

Server can then in-response decide if it allows this method of not by replying like below

 Access-Control-Allow-Methods: PUT, DELETE, POST
  • If the request wants to make use of some special headers, the browser will append headers like Access-Control-Request-Headers and the server will respond with Access-Control-Allow-Headers , to specify which headers it does allow and as usual if the request header is not included in it the browser will block this request.
 Access-Control-Request-Headers: Content-type
 Access-Control-Allow-Headers: Content-type, X-3GPP-Identity

There are a number of other headers which you can read about in the W3C specs. If you don’t want to change your server code to support CORS header, but you use Apache, you should look into mod_headers module, which allows you to add headers to the outgoing response from the Web Server, a sample mod_headers configuration could look like this

Header set Access-Control-Allow-Origin *
Header set Access-Control-Allow-Headers x-gwt-module-base
Header add Access-Control-Allow-Headers content-type
Header add Access-Control-Allow-Headers x-gwt-permutation

Pre-Requests

In the CORS protocol , pre-requests phenomenon is important. Most of the times the browser will or can decide to send the Access-Control-* headers in a request, before it makes the real request, to find out if the server allows the headers, and methods that the actual request will use, and only if they are allowed that the real request is sent.

These requests are called pre-requests. CORS Protocol does allow the the server to add a header called Access-Control-Max-Age which will tell the browser not to make any pre-requests for a certain period of time, because the server is OK with the headers and methods till that time. When the time elapses the browser will make another pre-request to determine if the method and headers are still allowed by the server. This essentially is a caching mechanism to save network traffic or over-head of making a pre-request for each request. For example

Access-Control-Max-Age : 1800

A Note for GWT Users

In GWT 2.x onwards you can use the dynamic script injection without having to make any changes to your code. You can add some compiler options to your Module XML file to generate JS files instead of embedded js into HTML, which will do dynamic script injections as follows

 add-linker name="xs"

So there you have it. A brief introduction to SOP and the ways to get around it. Hopefully you will find this information useful

Author:

Not your average Geek!

5 thoughts on “Getting Around Browser’s Same Origin Policy (SOP) With Proxies, Script Injection , JSONP and CORS

  1. 0 is, I am fairly sure, starting to happen very quickly.
    0 technologies such as Blogs, Business Networking such as Linked In, Ryze or even Facebook,
    AJAX, RSS, Adobe Flash, CMS (Content Management Systems), Podcasting, Wikis, XHTML markup and other user-oriented architecture that helps forge a synergy between company and
    customer. This review tested Qik on a Sony Ericsson Xperia,
    and the performance on that device seems to be pretty spot-on, and the screenshots speak for themselves.

  2. A bold, clearly made video with a professional touch is likely to be one your of the
    best points. Assignment editors plan out news stories months in advance.
    You’ve probably heard about the so called “link farms”.

  3. I read a lot of interesting content here. Probably you spend a lot of time writing, i know how to save you a lot
    of work, there is an online tool that creates unique, SEO
    friendly articles in minutes, just search in google – laranitas free content source

  4. Excellent post. I am still a firm believer in proxies though. Architecturally speaking, the “issue” resides on the client (browser). Any solution that requires the server to change is IMO a hack. Servers should not be responsible for managing clients.

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 )

Google+ photo

You are commenting using your Google+ 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 )

w

Connecting to %s