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

Cross site calls with javascript - the right way with CORS

Jan 15, 2015

Download

Technology

Michael Neale

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.
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
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