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.
Cross Origin Resource Sharing
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).
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
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
(or the other domain name/port of your testing page), trying to access its
location is against your browser’s rules.
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.
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.
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