
Stripe moves to JSONP; adds CORS support - stevencorona
https://stripe.com/blog/stripejs-and-jsonp
======
bitsweet
TL;DR; JSONP is the only hack that is IE proof

 _IE6, as usual, doesn’t support postMessage._

 _IE6 and IE7 both lack CORS support, while IE8 and IE9 have broken
implementations_

Oh what mankind could have achieved by now if we weren't so occupied making
our websites work in IEx.

~~~
RKearney
Well people need to stop writing code specifically for IE and just stick to
web standards. If Google/Facebook/PayPal/All Banks stopped coding hacks to get
their sites to work in IE, the users that use IE would have no other choice
but to switch to a standards compliant web browser.

~~~
prodigal_erik
IE users should get the standard-compliant pure-HTML version which is sure to
work on every browser. Only developers who neglected to start there have a
problem.

~~~
esrauch
I dont buy it. Some features just aren't reasonable to do without js and the
number of people without js is tending towards vanishingly small, and you can
have a nondegraded experience for a very significant percentage of traffic by
not just dismissing all versions of IE. Not that you should support all
versions, but if you are sending a separate no-js version to IE10 then you are
doing it wrong.

In my experience it is totally absurd to think that you can just write
"standards compliant HTML" and expect it to be rendered correctly on IE6 or 7
in any meaningful way anyway, you will always need to change your HTML and CSS
to specifically support those browsers and realistically any browser that you
want to support, the standards just are not uniformly implemented.

------
jashkenas
I'm curious about how this change handles cross-domain security. Is there
never any sensitive data in Stripe.js' JSONP responses? Or do y'all have a
mechanism for preventing a malicious 3rd party site from loading a script
pointing at one of your JSONP urls?

~~~
cheald
It shouldn't be any different than the existing functionality. stripe.js is
solely responsible for turning credit card information into one-use tokens, so
that CC information never hits your servers. That token is then used to
communicate with Stripe using a private shared key (kept serverside, never
exposed on the client) to create a Customer record, which is then used to
conduct the actual money parts of the transaction.

So, a malicious party could create tokens with CC information, but without the
private key they'd have no way to use them.

~~~
pc
Yeah, that's right. It's also worth emphasizing that the Stripe API doesn't
support sessions, and so isn't vulnerable to standard CSRF attacks.

------
gkoberger
Interesting they choose JSONP (which is GET only, and can't return proper
error codes) for such a POST-heavy library. It doesn't _really_ matter, since
they abstract it away. However, it's interesting they're completely ignoring
so many basic REST principles.

Edit: I don't disagree with their decision, I just imagine it wasn't an easy
one.

~~~
jonknee
It's not interesting, if you read the post you would know that they did it
because of IE lacking support for CORS.

> Unfortunately, that’s not quite enough for Stripe.js. IE6 and IE7 both lack
> CORS support, while IE8 and IE9 have broken implementations. IE10 is the
> only version with a non-buggy CORS implementation. Obviously, compatibility
> is paramount for Stripe.js — we want to support all major browsers, right
> down to IE6—and so we needed to look elsewhere.

~~~
bceagle
FYI, it is true that the implementation is broken in IE8 and IE9, but there is
a fairly straightforward fix. [http://mcox.tumblr.com/post/22791023337/ie-
cors-support-in-j...](http://mcox.tumblr.com/post/22791023337/ie-cors-support-
in-jquery)

------
JoshTriplett
This seems like a step backward. The iframe-based communication, as hackish as
it seems, allows cross-domain communication without resorting to completely
unsandboxed script tags referencing a remote server. Meanwhile, JSONP uses a
script tag, and nothing forces the response to actually conform to JSONP (JSON
wrapped in a specific function call) rather than running arbitrary Javascript
code.

~~~
lucasgonze
The only new exploit I can think of is domain hijacking, so that an attacker
replaces the real Stripe response with their own. If they can do domain
hijacking, though, whether or not they choose to insert the replaced content
into a third party page via JSON is a less damaging hack than just swiping
your credit card info sent to Stripe.

~~~
JoshTriplett
Domain hijacking doesn't seem like an issue here, given HTTPS; if someone can
MITM that they can do the same to my own site.

However, just because I trust a service to process payments or do any other
specific business-critical task doesn't mean I trust that service to run
arbitrary Javascript code in the context of my site. Customers may have
significantly more sensitive data than just payment information, and third-
party Javascript represents a major issue. I need the ability to confidently
say to customers that no third-party service has access to their private data.

Given this new approach, I'd have to sandbox payment code off on a separate
domain that has no access to other user data.

~~~
cheald
> However, just because I trust a service to process payments or do any other
> specific business-critical task doesn't mean I trust that service to run
> arbitrary Javascript code in the context of my site.

You...include their Javascript on your site to even be able to make the JSONP
calls in the first place. Their "arbitrary Javascript" is on your domain
already.

You certainly could audit it, locally mirror it, and then do that every time
they publish an update, but are you actually going to do that?

~~~
JoshTriplett
> You certainly could audit it, locally mirror it, and then do that every time
> they publish an update, but are you actually going to do that?

Yes, absolutely. For any third-party Javascript, I'd either mirror it locally
and review it for safety, or sandbox it on a separate untrusted domain that
has no access to customer data.

~~~
cheald
I think the separate domain is a great solution in that case, but my point is
that if you're worried about the use of JSONP as the transport being the
insecure link, you're too late.

------
mmahemoff
Hopefully they add a "pay" Web Intent next.

(The Web Intent polyfill is implemented with the same postMessage hack they
were originally using, so technically they could just use the web intent and
nothing else. Though in practice, it probably doesn't handle cross-domain
iFrame messaging for the old browsers that don't support postMessage.)

------
smarx
What's broken about CORS in IE8 and IE9?

~~~
abraham
_Supported somewhat in IE8 and IE9 using the XDomainRequest object_

<http://caniuse.com/#search=cors>

------
dos1
Are there any security concerns with this? Is the URL of a GET request over
SSL encrypted as well as the payload? I assume it must be if they are sending
credit card information that way?

~~~
dan15
SSL/TLS is at a lower level than HTTP. The whole connection is secure as all
the encryption is set up before the HTTP request is even sent. This is why SSL
used to always require a dedicated IP address - The server didn't even know
what domain you were going to while the connection was being set up (as the
host name is in the HTTP headers) so you could only have one SSL certificate
per IP address.

Server Name Indication (<http://en.wikipedia.org/wiki/Server_Name_Indication>)
works around this by sending the host name during the TLS handshake, so that
multiple domains can use SSL on the same IP address. In this case, only the
host name is sent in the clear. The whole HTTP request and response are still
encrypted.

~~~
kelnos
If only all browsers supported SNI. The Android 1.x/2.x browser annoyingly
doesn't (it's actually the fault of the Java Apache HttpClient). And ~75% of
Android users are stuck on it.

------
taskstrike
This is big, it's another functionality that used to be server only moving to
the clientside.

------
jader201
Sorry for the off-topic comment, but I couldn't help but notice (and comment
on) the noticeably slow-loading picture of Alex at the top, only to realize
it's a 378KB 500x500 image[1] resized at render-time to 68x68.

I'm just surprised that a tech company like Stripe w/ such a polished site and
attention to UX would not find a way to optimize this.

[1] <https://stripe.com/img/about/team/alex.png>

~~~
blaines
MB?! I saw about 300KB.

------
dreamdu5t
Ewwww JSONP. Keep it RESTful with useful response codes. People accepting
credit card payments online should have the ability to do things server-side
instead of use JS.

~~~
cheald
You might want to read up on how Stripe works before commenting.

