Over the last few weeks I’ve gotten a ton of questions for applications that need to support cross-site script access in relation to West Wind Web Connection. This typically a requirement for service applications that are accessed from mobile devices or other devices that don’t load the actual site content from the origin Web site. Typically this means you are building a HTTP or REST service that communicates with the client via JSON.
Web Connection 5.70 and later has introduced a host of new features – including the powerful and easy to use wwRestProcess Process class – to make it super easy to create HTTP based JSON services, and it looks like quite a number of users are taking advantage of these new features to integrate their Web Connection backends with various mobile device applications.
So not surprising that these requests for Access-Control-Allow-Origin header questions are coming up more frequently now. When you’re building mobile or distributed services that are called from multiple origin sites or devices you will have to address the CORS issues to enable the cross-domain Web service access.
Luckily making that happen is pretty easy.
What is CORS?
By default Web browsers (and Web browser controls) allow access of data retrieved via AJAX/XHR requests only to come from the same origin server as the originating request. This means that if I’m running on http://west-wind.com/ all of my HTTP requests using XHR have to come from the same west-wind.com domain.
The reason for this restrictive behavior is to prevent cross-site scripting attacks – if your site’s has user input that can be corrupted to include <script> tags that execute it’s possible for an attacker to potentially send sensitive information, like cookie data or anything else contained on a page to another server. The XHR restrictions are in place to supposedly prevent this.
CORS is a simple protocol allows a way to get around this by a server specifying an Access-Control-Allow-Origin header on the server to specify which domains (or all domains) that are allowed access to the site.
Setting the Access-Control-Allow-Origin Header in Web Connection
It’s easy to set this header in Web Connection:
on any request that happens. Here I’m allowing any source domain to access the site. You can also specify specific domains as a comma delimited list in the format of http://west-wind.com,http://weblog.west-wind.com for example.
Alternately you can also add this globally for an entire process class by setting the value in the OnProcessInit() method:
FUNCTION OnProcessInit Response.GzipCompression = .T. Request.lUtf8Encoding = .T. Response.AppendHeader("Access-Control-Allow-Origin","*") RETURN .T.
Finally you can also use IIS to set this header globally for the entire site assuming your using IIS 7 or later:
<system.webServer> <httpProtocol> <customHeaders> <clear/> <add name="Access-Control-Allow-Origin" value="*" /> </customHeaders> </httpProtocol> </system.webServer> </configuration>
And voila that’s all it should take to make your site able to serve remote requests from mobile devices or from pages served off a remote domain.
Things that make you go Hmmm.
Alas, I’ve never really understood the value of this CORS implementation. Cross site scripting is a big problem no doubt, but I don’t really see how CORS helps this if the *server* can specify the domain it wants to allow. If somebody is attacking your site and trying to steal information and they want to use XHR to post the data somewhere it’s trivial for the user to set up a server that adds the above header. Nothing’s been prevented at that point. This just seems like yet another useless security protocol that makes things a little bit more inconvenient for developers, but adds very little of security safeguards. Just like JSONP and hidden iFrames have been able to get around XHR cross-site limitations for years, CORS doesn’t really provide anything that prevents that.
The point of CORS is more to let the server decide of whether it wants to serve content to the client, but CORS is often billed as cross site scripting prevention which it really isn’t.