Just this past week I was working on a project that required me to write an uploader script. Nothing new or revolutionary here. There was, however, one major fly in the ointment – the upload handling script was being hosted on a different domain to script that was submitting the upload request! This was causing the upload to fail, with NO obvious error messages and no feedback what so ever. All I got back, was a failed message and no reason why.
After several days of thrashing away on this specific bug, I decided to write a small test script to make sure the logic I was using to upload in the first place was robust. The test script worked first time, with NO problems – on the domain hosting the upload handler! Seeing the success of the test script, I moved it to the domain of origin and it failed! I immediately knew what I was dealing with and started to seek out solutions! One of the first hits I came across was an article on Cross Origin Resource Sharing, or CORS. CORS is exactly what the name implies. The ability to share resources between two points of differing origin.
Now, the reason the upload was failing was twofold:
- I was submitting an upload request from one domain to another.
- More importantly, I was using Javascript (more specifically, Ajax) to submit the upload request.
Server’s, by default, will refuse requests from differing origins for reasons of security. Over the years, many forms of malicious coding have come to the fore. In recent times, Cross Site Scripting (or XSS) and Cross Site Request Forgery (or XSRF) have been two of the more favored approaches. Both XSS and XSRF depending on pieces of Javascript being executed on a remote server, instructing it to do something malicious, either to itself, or worse yet, to other clients and servers. CORS is a form of XSS!!!
In my case, I was submitting from one subdomain to another (eg. foo.domain.com to bar.domain.com). I hadn’t anticipated that this would created any issues. However, because the default behavior of the server is to ONLY accept Ajax scripting calls from itself, subdomains, even if they’re hosted on the same machine, are not allowed to submit certain types of requests to each other.
Thankfully, server technology allows us to work around this! On the server, you can create a list of domains you are willing to accept requests from. You can also create a list of HTTP headers you are willing to accept in those requests, as well at the HTTP methods (GET, POST, PUT, DELETE, etc.) that you will accept. Essentially, what you’re doing is creating a whitelist of the domains that are “safe”, the headers those domains can send you and actions those domains are allowed to perform.
Once I figured that out, the solution was easy! I added my domain and the headers I needed to use to the whitelist and the problem literally disappeared. After 2 or 3 days of banging my head on what was a trivial problem on the surface, took less than 30 seconds to solve, once I realized what the REAL problem was!
It just goes to show you that even after nearly a decade in the industry, there is still plenty to learn!
Leave a Reply