Archive for September, 2007
9/23 JSONRequest amendment (0)
JSONRequest was born from Crockford’s head more than a year ago, but only this month has it really gotten interesting. Collin Jackson has released a Firefox extension implementing the JSONRequest spec. I was naturally compelled to play with it.
JSONRequest is a proposed new standard that could replace XMLHttpRequest and shed the crippling “same domain policy” that makes it a pain to consume outside APIs in Javascript. It’s secure enough for cross-site-scripting for a couple of reasons. I’m lazy, so here are Crockford’s words:
JSONRequestdoes not send or receive cookies or passwords in HTTP headers. This avoids false authorization situations. Knowing the name of a site does not grant the ability to use its browser credentials.JSONRequestworks only with JSON text. TheJSONRequestcannot be used to access legacy data or documents or scripts. This avoids attacks on internal websites which assume that access is sufficient authorization. A request will fail if the response is not perfectly UTF-8 encoded. Suboptimal aliases and surrogates will fail. A request will fail if the response is not strictly in JSON format. A request will fail if the server does not respond toPOSTwith a JSON payload.- Reponses will be rejected unless they contain a
JSONRequestcontent type. This makes it impossible to use JSONRequest to obtain data from insecure legacy servers. JSONRequestreveals very little error information. In some cases, the goal of a miscreant is to access the information that can be obtained from an error message.JSONRequestdoes not return this information to the requesting script. It may provide the information to the user through a log or other mechanism, but not in a form that the script can ordinarily access.JSONRequestaccumulates random delays before acting on new requests when previous requests have failed. This is to frustrate timing analysis attacks and denial of service attacks.
From this list, #1 and #3 make the most difference. Without sending cookies, it will be very difficult to send requests impersonating a logged-in user. By requiring the application/jsonrequest content type on the response, the standard requires that the API provider take action to allow JSONRequests. This leaves no excuse for lazy API providers who don’t make their API secure.
As for other security holes, I’ve been poking around a bit against the Flickr API. I had to steal an API key, the shared secret for that key and a user’s token that came from that API key before I could do anything nasty. Now, since getting these three pieces of information gives you free reign even without JSONRequest, I don’t see much of a threat here.
As a bit of an aside, OAuth seems to work very much like the Flickr API and so JSONRequest will be equally innocuous for OAuth users.
OK, finally the amendment part
Requiring that all POST requests be sent as well-formed JSON data severely limits JSONRequest’s ability to take web apps to the next level. The inability to send traditional POST payloads isn’t such a big deal, but the inability to send multipart POSTs for file uploads is tragic.
Of course, it isn’t as easy as just lifting the JSON-only restriction on POST payloads. As Mike pointed out to me last night, old sites using GET variables to handle authentication (PHPSESSID anyone?) are pretty much sitting ducks. But there’s always another way.
Allowing traditional or multipart POSTs without some prior setup can be hazardous. Although these will always return an error to the caller, on the server side they may be successful which could really muck up your databases. The solution is simply to require a successful JSON POST immediately prior to accepting the multipart request as a way for the server to say “yes, I want that multipart POST.” In pseudocode, something like this:
JSONRequest.post_multipart = function(url, send, done, timeout) {
JSONRequest.post(url, {'multipart': 1}, function(requestNumber, value, exception) {
if (value) {
// Here we would take params passed to post_multipart and actually
// send the multipart request. The result of that would be passed
// to the function the called passed in the done param. The
// intermediate JSON POST is essentially invisible.
} else {
console.log(exception.message);
}
}
};
With this we will finally have hack-free file uploads in addition to safe cross site scripting. Even Microsoft can’t say no to implementing that.
9/16 Help me decide what C code to write (2)
The majority of my (awesomest ever) day job at Flickr is written in Javascript. I do write some C++ code for some of the trickier parts, but wc tells me more that only about a tenth of my code is C++.
That tenth doesn’t really do it for me, though. It isn’t dirty and dangerous. Because of the Netscape Portable Runtime, it’s actually rather tame. See, I spent college SEGFAULTing at least once a day. In my nearly three months at Flickr, I’ve managed to do so only twice.
Fear not — I have a way to get my fix. I’m intrigued by FUSE and started to think about the design of a Flickr filesystem. About 14 seconds after that I discovered Manish Rai Jain’s flickrfs project. It is more complicated than I would have designed, but because of that it’s incredibly powerful. Flickr isn’t out as a possible project for a FUSE filesystem but I’d rather not step on his toes. Onward.
The problem is, I’m short on imagination right now. I think the most powerful aspect of making non-filesystem data available as a filesystem is the huge set of possibilities that open up when you start chaining standard UNIX commands.
Do any C-shy webdev types want anything else out of their filesystem?
9/13 Friend buckets through XFN (1)
Social network portability will be great but managing the particulars will be a nightmare with the tools currently available. Some think XFN will tame the madness, but they’re crazy. It isn’t flexible enough. XFN doesn’t cover the entire spectrum of relations that people can have — having hardcoded values pretty much destroys any hope there.
We need something like rel="tag:drunkenfratparty" that differentiates college friends from code-monkey friends (rel="tag:nerdery"). Your bestest friends would be rel="tag:*". But rel="friend met" is just too vague.
Most obviously, this is a way to get at information like Facebook’s Friend Details. More importantly, this is how we prevent our excessive friend list on one network from polluting something more intimate. The Facebook Friend Details options, being controlled by the company rather than the users, will ultimately act like hardcoded values that everyone knows and recognizes (rel="tag:we_hooked_up" anyone?). But if I could tag friends “danville” or “cyclist” or “musician” then I could maybe get someone useful.
The goal here of course is to enter information once and have it propagate as more social sites crop up. When I’m joining the hot new social network for drummers I can include my friends elsewhere tagged “musician” and end up with exactly who I want.
9/9 New domain, but you’d never notice (0)
I recently snagged rcrowley.org when someone didn’t renew it and spent a bit of this morning transitioning everything into place. The site itself was easy. I just setup a new domain on TextDrive and copied all of the code to this new domain. The database is shared, so no mysqldump‘ing was necessary. Then I replaced the .htaccess file at richarddcrowley.org to forward traffic to the new domain before deleting the code part of the site from that domain.
The RSS feed is handled by FeedBurner, so changing the source there was no big deal. However, I’d like to transition over to feeds.feedburner.com/rcrowley instead of feeds.feedburner.com/richarddcrowley. I have both going right now and have changed all my links to the new one. If you would be a kind soul and change your RSS reader to point to feeds.feedburner.com/rcrowley, I’d be nearly eternally greatful.
9/6 Enough with web desktops (6)
For reference, here’s what sent me over the edge: Ext 2.0: Scrolling Tabs, Anchor Layout, the Web Desktop, and more (Ajaxian)
I might break up with the Internet if I keep seeing so much misguided effort spent on making a website behave like a whole operating system. Because I think I’m dealing with some rather thick skulls, I’ll put this simply: stop. Now.
An arguably great feature of web apps is that they’re more two-dimensional than three-dimensional. It promotes focus. It discourages repeated seizure-inducing Exposé usage. While I’m on the topic, I can’t wait for someone to do Exposé in Javascript. That’s exactly what we need. (It’ll give me something to write about, at least.)
I’d like to propose a couple of rules that will kill stupid stuff like web desktops, all the while promoting smart use of Javascript wizardry.
- If any two things can partially overlap, you’re fired.
- If any drag & drop events don’t result in database writes, get out.
- If your website looks like Microsoft Windows, you’ve stepped over the line.
9/3 XUL and XHTML run together (0)
I have been spending an inordinate amount of time these days with XULRunner, Mozilla’s awesome cross-platform SDK used to build Firefox and Thunderbird. XULRunner is bit of an oddity, more akin to a web browser than the Java Virtual Machine or the Ruby interpreter. While it is most definitely focused on the development of desktop applications, it feels too similar to developing websites in many cases.
XUL is a specific subset of XML that is understood by XULRunner and is used to visually layout desktop applications. Interaction with a XUL app is handled by Javascript in much the same way that Javascript handles interactions with websites today. You can even include the XHTML namespace in your XUL app to really start to blur the lines between the desktop and the browser:
<window id="main" title="&title;" width="750" height="500" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml">
But let’s stop right there. XUL is not XHTML. They do not work the same way and any attempts to make them do so will result in only frustration. This is where my biggest criticism of XUL comes. Visually, the code looks like a website but functionally the code works much more like Java Swing/AWT or Visual C++ resources. Websites work in blocks while XUL works in boxes.
Here’s a bit of a crash course in boxes. There are two basic types of boxes, vertical and horizontal. A vertical box will stack its child elements vertically, expanding them to fill the entire width available. A horizontal box will do just the opposite. Vertical boxes will by default only use as much vertical space as necessary, but with the flex="1" attribute they can be made to fill all available vertical space, too. Horizontal boxes similarly can be made to take all available horizontal space.
Throw all your old CSS techniques out the window now. What I found to be most helpful to me while laying out a XUL app was actually to turn CSS off. In contrast to the semantically pristine XHTML 1.1 we’ve all been writing lately, XUL layouts very much depend on the markup. This is both a blessing and a curse — our typical CSS kung fu doesn’t really matter but now we don’t have to worry about graceful degradation since we control the runtime used with our app.
The takeaway here is to throw semantics out the window for XUL apps. Focusing on building what you want and keeping your code maintainable are two big enough challenges.