CORS, OAuth, Headers vs Parameters, and Preflighting

273 views
Skip to first unread message

Chris Mullins

unread,
Jan 27, 2015, 2:16:33 PM1/27/15
to api-...@googlegroups.com
Hi Guys,

As part of enabling CORS on some of our APIs, we're faced with a dilemma:

  1. We're OAuth based, and we typically pass the token around in headers. 
  2. With CORS, if we pass the OAuth tokens in the headers, that means pre-flight requests. 
  3. If we pass OAuth tokens in URL Parameters (to avoid pre-flighting) there are security implications. 
As Google points out on one of their OAuth pages:
 
After an application obtains an access token, it sends the token to a Google API in an HTTP authorization header. It is possible to send tokens as URI query-string parameters, but we don't recommend it, because URI parameters can end up in log files that are not completely secure.

Is there a way to have my cake and eat it too? That is how to avoid the pre-flight requests AND keep the OAuth Token out of the URL Parameters?

Cheers,
Chris

Kijana Woodard

unread,
Jan 27, 2015, 2:28:16 PM1/27/15
to api-...@googlegroups.com
Why do you want to avoid the pre-flight requests?

--
You received this message because you are subscribed to the Google Groups "API Craft" group.
To unsubscribe from this group and stop receiving emails from it, send an email to api-craft+...@googlegroups.com.
Visit this group at http://groups.google.com/group/api-craft.
For more options, visit https://groups.google.com/d/optout.

Chris Mullins

unread,
Jan 27, 2015, 7:25:11 PM1/27/15
to api-...@googlegroups.com
Hi Kijana, 

Pre-flight requests will immediately impose a 2x latency hit. That's brutal. 

The pre-flight cache is also different on every browser, meaning that we'll have inconsistent performance with high variance across browser platforms, which is a non-ideal solution. It's my belief that building a responsive application that works in a consistent way across platforms means aggressively limiting pre-flighting.  

Cheers,
Chris

Johan Groenen

unread,
Jan 28, 2015, 10:41:01 AM1/28/15
to api-...@googlegroups.com
Well, you can use a proxy server, but that will also introduce latency and extra complexity. If you use the GET parameters, even over https, they might popup in server logs, which is something you might want to avoid. So that leaves doing preflights and hope the browsers cache them. I don't know what kind of application you are building, but usually the preflights only cost about 50 to 100 ms on a normal connection and responsive server, so the responsiveness of the application is usually more in the way you handle your rendering of new view elements (during the call instead of after).

Op woensdag 28 januari 2015 01:25:11 UTC+1 schreef Chris Mullins:

Johan Groenen

unread,
Jan 28, 2015, 10:45:37 AM1/28/15
to api-...@googlegroups.com
Also you can try to do the GET requests before they are really needed, for example on mouseover instead of on click or just on the load of some other stuff. Make sure to cache all information that is not updated realtime, so you can ommit the request. Of course maybe you have done this already, but I notice that most of the time the optimizations that you are now looking for aren't quite as effective as moving around the request triggers, caching, piggybacking, server sent events, etc.

Op woensdag 28 januari 2015 16:41:01 UTC+1 schreef Johan Groenen:

Chris Mullins

unread,
Jan 28, 2015, 3:44:47 PM1/28/15
to api-...@googlegroups.com
Hi Johan,

There are certainly any number of UI Tricks that can be used to improve the overall user experience. The problem with these tricks is that I'm building the API Layer, and it's big, and it's going to last for years. People I don't know and will likely never meet will be calling those API's, building UI's, and (hopefully!) providing unforeseen customer experiences atop them. I consider it my job in building the platform to make the job of the UI developer as simple as possible. The more I can do to shape the APIs and prevent the need for "UI Tricks" the more likely high quality UI's will result.  

Pushing the preflighting to unknown developers and making them deal with preflight caching in Random Browser XYZ seems quite a bit to ask.

At this point, my preference is to pass the OAuth token as a parameter, and then (somehow) make sure the log files are properly scrubbed for security at the edge. Everything will be HTTPS, so at least the (potentially many) hops between the browser and my edge won't have access to see anything. 


Cheers,
Chris

Jørn Wildt

unread,
Jan 28, 2015, 4:02:02 PM1/28/15
to api-...@googlegroups.com
Just a historical side note ...

> At this point, my preference is to pass the OAuth token as a parameter, and then (somehow) make sure the log files are properly scrubbed for security at the edge

I believe this is the core problem with OAuth2 compared to OAuth1 - simplicity was preferred over security. It would not have been an issue with OAuth1.

OAuth2 (or rather "bearer tokens") is way simpler than OAuth1, but it does have its drawback.

If anyone is interested then check Eran Hammer's "Good bye" rant on http://hueniverse.com/2012/07/26/oauth-2-0-and-the-road-to-hell/

/Jørn

Chris Mullins

unread,
Jan 28, 2015, 4:19:19 PM1/28/15
to api-...@googlegroups.com
I've read that rant before. :-) 

Rather than getting into OAuth issues, I lean more towards "This seems a problem with the CORS standard, which should be updated to allow OAuth tokens to be passed in a secure way without requiring a preflight check." Increasingly I'm seeing services want to say, "I allow callers from *, but require a valid OAuth Token." That scenario doesn't appear to be dealt with effectively by the existing CORS standard.  

(Note: I do not know the history behind the CORS standard, and there may well be very good reasons this scenario was excluded. One of these days I need to dig into that...)

Cheers,
Chris
Reply all
Reply to author
Forward
0 new messages