40
CORS and Javascript Integration in the browser Michael Neale @michaelneale Friday, 25 October 13

Cross site calls with javascript - the right way with CORS

Embed Size (px)

DESCRIPTION

Using CORS (cross origin resource sharing) you can easily and securely to cross site scripting in webapps - less servers and more integration from apis right in the browser This was presented during Web Directions South, 2013, Sydney, Australia.

Citation preview

Page 1: Cross site calls with javascript - the right way with CORS

CORS and JavascriptIntegration in the browser

Michael Neale@michaelneale

Friday, 25 October 13

Page 2: Cross site calls with javascript - the right way with CORS

Integration in the browser

Lots of services, microservicesEverything has an APIJSON == lingua franca

Why have servers that are just text pumps:Integrate into new apps in the browser

Friday, 25 October 13

Page 3: Cross site calls with javascript - the right way with CORS

For example

Friday, 25 October 13

Page 4: Cross site calls with javascript - the right way with CORS

CI serverApp service

JSON !!111

repos

Friday, 25 October 13

Page 5: Cross site calls with javascript - the right way with CORS

but - same origin policy?

http://en.wikipedia.org/wiki/Same-origin_policy

Friday, 25 October 13

Page 6: Cross site calls with javascript - the right way with CORS

but - same origin policy?

Web security model - not bad track record.

Not going to change... so, how to work around:

Friday, 25 October 13

Page 7: Cross site calls with javascript - the right way with CORS

integration middleware?

Friday, 25 October 13

Page 8: Cross site calls with javascript - the right way with CORS

Overkill

Friday, 25 October 13

Page 9: Cross site calls with javascript - the right way with CORS

JSON-P

Add “padding”.

JSON P: take pure json, make it a function call - then eval it in the browser.

Same Origin Policy doesn’t apply to resource loading (script tags)

Friday, 25 October 13

Page 10: Cross site calls with javascript - the right way with CORS

jsonp: Most glorious hack ever

Friday, 25 October 13

Page 11: Cross site calls with javascript - the right way with CORS

JSON-P

JSON: { “foo” : 42 }

JSONP: callback({ “foo” : 42 });

Widely supported (both by servers and of course jquery & co make it transparent)

Friday, 25 October 13

Page 12: Cross site calls with javascript - the right way with CORS

direct to origin:

$.ajax({ dataType : "json" ... });

Friday, 25 October 13

Page 13: Cross site calls with javascript - the right way with CORS

JSON-P cross domain

$.ajax({ dataType : "jsonp", jsonp:'jsonp' .... });

Friday, 25 October 13

Page 14: Cross site calls with javascript - the right way with CORS

JSON-P

What it is really doing: creating script tags, and making your browser “eval” the lot. Each time, each request.

Don’t think too hard about it...

Friday, 25 October 13

Page 15: Cross site calls with javascript - the right way with CORS

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?

Friday, 25 October 13

Page 16: Cross site calls with javascript - the right way with CORS

JSON-P

Also, JSON is not Javascript

JSON can be safely read - no eval

JSON-P only eval

JSONP is GET only

Friday, 25 October 13

Page 17: Cross site calls with javascript - the right way with CORS

CORS

http://en.wikipedia.org/wiki/Cross-origin_resource_sharing

Allows servers to specify who/what can access endpoint directly

Use plain JSON, ALL HTTP Verbs: PUT, DELETE etc

Friday, 25 October 13

Page 18: Cross site calls with javascript - the right way with CORS

CORS

Friday, 25 October 13

Page 19: Cross site calls with javascript - the right way with CORS

Oy, they’re my sisters yer lookin atNOT THESE:

Friday, 25 October 13

Page 20: Cross site calls with javascript - the right way with CORS

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

Friday, 25 October 13

Page 21: Cross site calls with javascript - the right way with CORS

CORS - client side ex.

$.ajax({ dataType : "json",

xhrFields: { withCredentials: true } ...

});

Friday, 25 October 13

Page 22: Cross site calls with javascript - the right way with CORS

How it worksMost 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

Friday, 25 October 13

Page 23: Cross site calls with javascript - the right way with CORS

How it worksbrowser server

http OPTIONS (Origin: http://boo.com)

Access-Control-Allow.... etc

direct http GET /POST (as allowed by Access headers)

...

pre-flight

your app

Friday, 25 October 13

Page 24: Cross site calls with javascript - the right way with CORS

How it works“Pre flight checks”:

Performed by browser, opaque to client app. Browser enforces. You don’t see them.

Uses “OPTION” http verb.

Friday, 25 October 13

Page 25: Cross site calls with javascript - the right way with CORS

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)

Friday, 25 October 13

Page 26: Cross site calls with javascript - the right way with CORS

Common patternAccess-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.

Friday, 25 October 13

Page 27: Cross site calls with javascript - the right way with CORS

MiddlewareAll app server environments have a way to do the Right Thing with CORS headers:

Rack-cors: rubyServlet-filter: javaNode: express middlewareetc...

(it isn’t hard, just not as easy as it should be)http://stackoverflow.com/questions/7067966/how-to-allow-cors-in-express-nodejs

Friday, 25 October 13

Page 28: Cross site calls with javascript - the right way with CORS

Other CORS headersAccess-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)

Friday, 25 October 13

Page 29: Cross site calls with javascript - the right way with CORS

AuthorizationYou 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)

Friday, 25 October 13

Page 30: Cross site calls with javascript - the right way with CORS

Authorization

requests

authorization

identity/auth

pre-flight

your app

browser

Friday, 25 October 13

Page 31: Cross site calls with javascript - the right way with CORS

DebuggingPesky pre-flight checks are often opaque - may show up as “cancelled” requests without a reason.

Use chrome://net-internals/#events

Friday, 25 October 13

Page 32: Cross site calls with javascript - the right way with CORS

DebuggingFollowing 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.

Friday, 25 October 13

Page 33: Cross site calls with javascript - the right way with CORS

Friday, 25 October 13

Page 34: Cross site calls with javascript - the right way with CORS

Friday, 25 October 13

Page 35: Cross site calls with javascript - the right way with CORS

Debuggingt=1374052796709 [st=262] +URL_REQUEST_BLOCKED_ON_DELEGATE [dt=0]t=1374052796709 [st=262] CANCELLEDt=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)

Friday, 25 October 13

Page 36: Cross site calls with javascript - the right way with CORS

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!!

Friday, 25 October 13

Page 37: Cross site calls with javascript - the right way with CORS

Example (express)app.all('*', function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "X-Requested-With"); next(); });

node and express js: http://enable-cors.org/server_expressjs.html

Friday, 25 October 13

Page 38: Cross site calls with javascript - the right way with CORS

Example (rack/ruby)gem install rack-cors...in config/application.rb:

... config.middleware.use Rack::Cors do allow do origins '*'

resource '*', :headers => :any, :methods => [:get, :post, :options] end end

https://github.com/cyu/rack-cors

Friday, 25 October 13

Page 40: Cross site calls with javascript - the right way with CORS

Thank you

Michael Nealehttps://twitter.com/michaelneale

https://developer-blog.cloudbees.com

Friday, 25 October 13