With iD, you can securely log in to OpenStreetMap, make changes, and save them to the OpenStreetMap.org database. This is made possible by iD’s implementation of the OAuth specification, a standard system for applications to authenticate and interact. We’ve developed a tiny library called ohauth which provides the basic components of the process, and includes a trusted implementation of sha1 written by Paul Johnston.

iD is an unusual and interesting implementation of OAuth because it’s a purely browser-based Javascript application: as opposed to conventional implementations, there’s no server application in between it and the OSM API.

To make this work, we needed to write much of the fundamental code for authenticating: while JOSM and Potlatch 2 use libraries for Java and Actionscript, respectively, and TileMill uses a node.js OAuth implementation, there’s no established implementation for OAuth 1.0 in purely client-side applications. OAuth 2.0 supports a simplified client-side flow and thus has a well-written Javascript library, but is not supported on OpenStreetMap.org.

The OpenStreetMap website is powered by a Ruby on Rails application called the Rails Port, which luckily uses a well-tested oauth-plugin for its side of the authentication exchange.

Cross Origin Resource Sharing

The biggest challenge for this implementation is the same origin policy that applies to browser Javascript which uses AJAX across domains. iD is built to be hostable anywhere, with implementations on geowiki.com and elsewhere, which can all access the OSM API. So we can’t guarantee that requests for resources, like authentication calls, will be on the same domain.

In the past, we’ve used JSONP in this case: a hack that allows one to request JSON resources across domains. JSONP has many known flaws: potential security flaws, an inability to read and set headers, no support for methods other than GET, and the response body format is traditionally limited to JSON (though you can stringify XML in JSONP).

Thus cross-domain OAuth can’t be done with JSONP, and requires actual cross-domain requests with CORS. Luckily, OpenStreetMap supports the standard, which provides a simple way to jump across the border.

The downside is that support for CORS in Internet Explorer is nearly non-existent: only in IE10 is it supported in standard form. iD does not support IE before version 10 at the moment (with a distant possibility of IE9 support in the future).

Javascript Implementations

As mentioned, OAuth.org links to a javascript library for OAuth 1.

That library unfortunately leaves much to be desired, both in terms of style and design, and isn’t immediately usable in a project like iD. We do, however, use the same implementation of SHA1 by Paul Johnston.

Thus iD uses a somewhat fixed-up SHA1 library and a very simple library titled ohauth, which inherits most strategy from the official implementation. This basic functionality is then wrapped with UI elements and logic in iD.

The Authorize Step

Besides a range of AJAX requests, the OAuth specification requires a step in which users are directed towards the ‘provider’ and choose what permissions they want to give iD. For instance, they can prevent iD from having the ability to view or edit their user profile.

iD initially tried to redirect the entire page to OSM’s /oauth/authorize page, which required a cookie with the value of the request_token so that it can be reused for the access_token step. This isn’t just hackish, but it has a very bad failure case: if that request fails, the user is stranded on a broken page.

The second technique is to use an <iframe> to do authorization. This works much better with the flow of authentication, but interacts poorly with browser security controls: Safari doesn’t permit cookie access in iframes, and all browsers will complain about the necessary step of extracting the iframe’s URL for OAuth: when the iframe is on openstreetmap.org instead of localhost:3000 (or the other domain name/port of your testing page), trying to access its location is against your browser’s rules.

iframe.onload = function() {
    if (iframe.contentWindow.location.search) {

Thus, iD now uses a popup window in order to execute the authorize step of OAuth. This has quite a few advantages: it works in Safari, users are able to easily see what site they’re authenticating against, and bailing on the process is easy: they can simply close the window.

However, this includes yet another wrinkle: the Javascript API for opening windows, window.open, has been abused and overused by many advertising sites, so many browsers limit its use: the only reliable way to open a popup in WebKit-based browsers is to call window.open within the scope of an event handler that is responding to a user interaction like a mouse click. This is a viable approach even if it’s easy to lose that scope like shown in the example below.

a.onclick = function() {
    window.open('foo.html'); // this window will open

b.onclick = function() {
    window.setTimeout(function() {
        window.open('foo.html'); // this window will not open
    }, 100);

Devlogging work on the OpenStreetMap project by the MapBox team.

Much of this work is currently focused on improvements to OpenStreetMap funded by the Knight Foundation

Follow our work here on this blog or subscribe to our Twitter feed. You can subscribe to this blog’s feed or follow us at