1. CORS and Javascript
Integration in the browser
Michael Neale
@michaelneale
developer.cloudbees.com
http://en.wikipedia.org/wiki/Cross-
origin_resource_sharing
Thursday, 12 September 13
2. Integration in the browser
Lots of services, microservices
Everything has an API
JSON == lingua franca
Why have servers that are just text pumps:
Integrate into new apps in the browser
Thursday, 12 September 13
10. JSON-P
All JSON world - add “padding”.
JSON P: take pure json, make it a function call - then
eval it.
Single Origin policy doesn’t apply to resource
loading
Thursday, 12 September 13
12. JSON-P
JSON: { “foo” : 42 }
JSONP: callback({ “foo” : 42 });
Widely supported (both by servers and of course
jquery makes it transparent)
Thursday, 12 September 13
13. JSON-P
What it is really doing: creating script tags, and
making your browser “eval” the lot. Each time.
Don’t think too hard about it...
Thursday, 12 September 13
14. JSON-P
Really misses the “spirit” of same-origin.
Security holes: any script you bring in has access to
your data/dom/private parts.
How secure is server serving up json-p?
Thursday, 12 September 13
15. JSON-P
Also, JSON is not Javascript
JSON can be safely read - no eval
JSON-P only eval
JSONP is GET only
Thursday, 12 September 13
18. Oy, they’re my sisters yer lookin atNOT THESE:
Thursday, 12 September 13
19. CORS
Trivial to consume: plain web calls, direct.
Complexity: on the server/config side.
Browser support: complete(ish):
http://enable-cors.org/
All verbs, all data types
Thursday, 12 September 13
20. How it works
Most work is between browser and server, via http
headers.
“Pre flight checks”:
Browser passes Origin header to server:
Origin: http://www.example-social-network.com
Server responds (header) saying what is allowed:
Access-Control-Allow-Origin: http://www.example-social-network.com
Thursday, 12 September 13
21. How it works
browser server
http OPTIONS (Origin: http://boo.com)
Access-Control-Allow.... etc
direct http GET (as allowed by Access headers)
...
pre-
flight
your
app
Thursday, 12 September 13
22. How it works
“Pre flight checks”:
Performed by browser, opaque to client app.
Browser enforces. You don’t see them.
Uses “OPTION” http verb.
Thursday, 12 September 13
23. Security Theatre?
“Pre flight checks”:
Can be just an annoyance.
Access-Control-Allow-Origin: *
Downside: allows any script with right creds to pull
data from you (do you want this? Think, as always)
Thursday, 12 September 13
24. Common pattern
Access-Control-Allow-Origin: $origin-from-request
The returned value is really echoing back what Origin
was - checked off against a whitelist:
Server needs to know whitelist, how to check, return
value dynamically.
Not a static web server config. SAD FACE.
Thursday, 12 September 13
25. Middleware
All app server environments have a way to do the
Right Thing with CORS headers:
Rack-cors: ruby
Servlet-filter: java
Node: express middleware
etc...
(it isn’t hard, just not as easy as it should be)
http://stackoverflow.com/questions/7067966/how-to-allow-
cors-in-express-nodejs
Thursday, 12 September 13
26. Other CORS headers
Access-Control-Allow-Headers (headers to be
included in requests)
Access-Control-Allow-Methods: GET, PUT, POST,
DELETE etc
Access-Control-Allow-Credentials: boolean
(lists always comma separated)
Thursday, 12 September 13
27. Authorization
You can use per request tokens, eg OAuth
OpenID and OAuth based sessions will work
(browser has done redirect “dance” - Access-
Control-Allow-Credentials: true -- needed to ensure
cookies/auth info flows with requests)
Thursday, 12 September 13
29. Debugging
Pesky pre-flight checks are often opaque - may
show up as “cancelled” requests without a reason.
Use chrome://net-internals/#events
Thursday, 12 September 13
30. Debugging
Following screen cap shows it working...
note the match between Origin and Access-control -
if you don’t see those headers in response -
something is wrong.
Thursday, 12 September 13
33. Debugging
t=1374052796709 [st=262] +URL_REQUEST_BLOCKED_ON_DELEGATE [dt=0]
t=1374052796709 [st=262] CANCELLED
t=1374052796709 [st=262] -URL_REQUEST_START_JOB
--> net_error = -3 (ERR_ABORTED)
This is it failing: look for “cancelled”.
Could be due to incorrect headers returned, or
perhaps Authorization failures (cookies, session etc)
Thursday, 12 September 13
34. My Minimal Setup
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: $ORIGIN
$ORIGIN = if (inWhitelist(requestOriginHeader) return
requestOriginHeader
INCLUDE PORTS IN Access-Control-Allow-Origin!!
Thursday, 12 September 13