To understand the techniques, we need to understand the problem we’re trying to solve: what are cross origin requests ?

But what is an origin first?

An origin defines where a resource lives.

Following URLs:

have the same origin: https://dzone.com

And, following URLs have different origins

URLs Origin
https://canho.me/2016/06/18/awaiting-aws-resources https://canho.me
http://canho.me http://canho.me
https://api.canho.me https://api.canho.me
https://canho.me:5000 https://canho.me:5000
file:///D:/projects/node-sample/package.json null

So, the origin is everything in the URL up until the path. In other words, the origin is a combination of the scheme, host, and port.

Same-origin vs Cross-origin

When we’re saying same-origin and cross-origin, we’re actually comparing origins of 2 objects: the client and the server. So, when an origin refers to the client making the request, it’s client origin. When an origin refers to the server receiving the request, it’s server origin.

So, we can define a request is a same-origin request when client origin and server origin are exactly the same.

Alt

Otherwise, the request is a cross-origin request.

Alt

But what is the problem anyway ? Why do I care about that ? Same-origin policy!
The same-origin policy restricts how a document or script loaded from one origin can interact with a resource from another origin. It is a critical security mechanism for isolating potentially malicious documents.

Same-origin policy is necessary but it’s too restrictive that causes some problems for servers using multiple domains and it’s hard for servers to open up its APIs to a new world of users.

Bellow are some techniques dealing with cross origin:

JSONP

JSONP – JSON with padding, is the oldest technique that is based on the fact that the browser doesn’t impose same-origin policy on script tag. And, we use the script tag to make cross-origin requests

<!DOCTYPE html>
<html>
    <head>
        function loadUsers(users) {

        };
        <script src="https://api.github.com/users?jsoncallback=loadUsers" />
    </head>
    <body>
    <div id="users">
    </div>


    </body>
</html>

The important part of script tag is the parameter jsoncallback. The value of this parameter is the name of an existing function loadUsers. When sending a response to the client, the server first pads the response with the name of the callback function, like this

loadUsers([{"id": "user1",...}, {"id": "user2"}])

When the client receives the response, it calls the callback function with the actual data returned by the server.

JSONP only supports GET requests. Ideally, this is use for sharing public data.

Cross-origin messaging

HTML5’s postMessage method allows documents from different origins to communicate with each other.

Alt

The page wanting send cross-origin requests needs to embed a document from the server via iframe and use postMessage to communicate with the iframe. As the iframe and the server are from the same origin, requests from the iframe and the server are same-origin requests.

As postMessage is a low level API, we may want a library acting as abstraction layer and providing high level messaging semantics on top of postMessage. There’re such libraries:

As postMessage is widely supported (see http://caniuse.com/#search=postmessage), this technique can be used in most cases.

Using proxy server

The same-origin policy is imposed by the browser on javascript code running in the browser. There isn’t such same-origin policy on the server. So, we can use a client’s own server acting as a proxy server receiving requests from the client and forwarding requests to the server.

Alt

Using this technique enables almost any type of cross-origin requests.

CORS

CORS – Cross-Origin Resource Sharing, is a W3C spec that allows cross-origin communication. CORS works by adding new HTTP headers that allow servers to describe a set of origins that are permitted to interact with the server. Most part of this technique involves in server configuration.

Below is cors flow with preflight request
Alt

CORS headers prefixed with Access-Control-

  • Access-Control-Allow-Origin (required): This header must be included in all valid responses. Possible values: * or a specific origin
  • Access-Control-Allow-Methods: indicates the methods allowed when accessing the resource
  • Access-Control-Allow-Headers: used in response to a preflight request to indicate which HTTP headers can be used when making the actual request
  • Access-Control-Allow-Credentials: indicates if the server allows credentials during CORS requests

A great post about CORS can be found here

CORS can be used as a modern alternative to the JSONP pattern. While JSONP supports only the GET request method, CORS also supports other types of HTTP requests. Using CORS enables a web programmer to use regular XMLHttpRequest, which supports better error handling than JSONP.(wiki)

Summary

  • CORS is the standardized mechanism for making cross-origin requests. Large part of CORS involved with server configuration. Almost all browsers supports CORS.
  • The first 3 techniques follow the same pattern: using a proxy object that receives the request from the client and send it to the server
  • The first 3 techniques require custom code. This leads to additional maintenance cost.
Advertisements

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