Cross-Origin Techniques
The same-origin policy restricts how a document or script loaded from one origin can interact with a resource from another origin. Here are some methods for working with cross origin requests.
Join the DZone community and get the full member experience.
Join For FreeTo 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.
The following URLs:
- https://dzone.com
- https://dzone.com/web-development-programming-tutorials-tools-news
- https://dzone.com/articles/design-patterns-in-expressjs
- https://dzone.com:443/articles/understanding-middleware-pattern-in-expressjs
have the same origin: https://dzone.com.
And, following URLs have different origins:
URL | Origin |
---|---|
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.
And, we can define that a request is a same-origin request when client origin and server origin are exactly the same.
Otherwise, the request is a cross-origin request.
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 so restrictive that it 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.
Below 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 tags. So, 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 used for sharing public data.
Cross-origin messaging
HTML5’s postMessage method allows documents from different origins to communicate with each other.
The page wanting to 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 an abstraction layer and providing high-level messaging semantics on top of postMessage. There are such libraries as:
- jschannel (https://github.com/mozilla/jschannel)
- easyXDM (http://github.com/oyvindkinsey/easyXDM)
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.
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 of this technique involves server configuration.
Below is a CORS flow with a preflight request:
CORS headers are 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. A large part of CORS involves server configuration. Almost all browsers support CORS.
- The first 3 techniques follow the same pattern: using a proxy object that receives the request from the client and sends it to the server
- The first 3 techniques require custom code. This leads to additional maintenance cost.
Published at DZone with permission of Can Ho, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Trending
-
Redefining DevOps: The Transformative Power of Containerization
-
Best Practices for Securing Infrastructure as Code (Iac) In the DevOps SDLC
-
Auto-Scaling Kinesis Data Streams Applications on Kubernetes
-
Generics in Java and Their Implementation
Comments