Know Your Location — Voiding My Firefox Warranty
I have to admit ignorance that I’ve answered the `${site} wants to know your location` question many times without thinking very deeply about what it means, both in terms of privacy or how it works technically.
I’m guessing that sometime in the past 5 years you’ve seen it too, so what’s going on behind the scenes and how might you use this in developing applications?
The Geolocation API
In order to make an application user-friendly, it makes good sense to know where the location of the user is. Things like places can be made more relevant, navigation and routing can be started sooner, your “things” can be found more quickly, and you don’t have to walk up-and-down all the aisles in the store looking for your mom.
If you try to solve this problem of determining the position server-side, the best indicator is generally the public IP address often reported in the X-Forwarded-For header of the HTTP request. When you are using a virtual private network (VPN) or a proxy server, that could make it look like you are 300 miles away from where you actually are. This location may be accurate enough for localization (l10n) and internationalization (i18n) use cases of country origin, but not much more than that.
You can solve it client-side too with the Geolocation API which is much more accurate. Published as a recommendation by the World Wide Web Consortium in 2013, the API allows us to write JavaScript code to fetch a position:
navigator.geolocation.getCurrentPosition(function(position) {
console.log(position);
});
You can try this in a web console yourself and get back latitude and longitude values along with an approximate accuracy expressed as the radius in meters.
This makes sense for a mobile device that has a built-in GPS, but last time I checked I didn’t have a dongle for a GPS on my MacBook Pro. That made me curious about how browsers are implementing the spec.
Void Your Firefox Warranty
Firefox has a number of configuration settings you can modify to customize your experience. By typing “about:config” instead of a URL you can identify the settings for geo.wifi.uri
which points to a googleapis endpoint.
I wanted to see what these requests look like so started a local webserver with http-echo-server and updated the Firefox value of geo.wifi.url to point it tohttp://localhost:8000
so I could watch the traffic.
$ npm install http-echo-server
$ http-echo-server
[server] event: listening (port: 8000)
[server] event: connection (socket#1)
[socket#1] event: resume
[socket#1] event: data
--> POST / HTTP/1.1
--> Host: localhost:8000
--> User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:60.0) Gecko/20100101 Firefox/60.0
--> Accept: */*
--> Accept-Language: en-US,en;q=0.5
--> Accept-Encoding: gzip, deflate
--> Content-Type: application/json; charset=UTF-8
--> Content-Length: 1198
--> Connection: keep-alive
-->
--> {"wifiAccessPoints":[{"macAddress":"81:3a:a9:88:80:58","signalStrength":-85},{"macAddress":"4c:97:6d:79:42:bf","signalStrength":-88},{"macAddress":"74:bc:0c:7f:0b:19","signalStrength":-84},{"macAddress":"00:a7:42:be:72:7f","signalStrength":-71},{"macAddress":"4c:66:6d:79:40:df","signalStrength":-85},
...]}
As you can see, Firefox is scanning the wireless local area network (WLAN) to identify the mac addresses nearby and received signal strength indication (RSSI) values and sending it all to a web service. If I make this request myself, I might get back a location like:
{
"location": {
"lat": 20.6842849,
"lng": -88.567782
},
"accuracy": 101.0
}
This is the data that feeds back into the Geolocation API we used earlier. You can learn more about this in the Firefox docs. Chrome does the same thing but doesn’t let you choose a different provider as far as I can tell.
HERE Positioning API
If I wanted to test my web app with a specific location, I could store this static response in a file called test-location.json
and set the geo.wifi.uri to point to the file on disk instead of an http endpoint.
I’d like to see a more dynamic result though and started exploring the HERE Positioning API. The HERE Positioning API works in much the same way as the default, taking in WLAN data but it also supports other radio bands — GSM, LTE, WCDMA, Cell. The Positioning API responds with JSON that Firefox expects, but I’ll need to insert a man-in-the-middle to modify the body of the request. The following listing demonstrates how I accomplished that.
I could continue to use the HERE Positioning API with Firefox, but this was more of a learning experiment than my recommendation to stand up your own service. I have other plans for how I’d like to use the Geolocation and Positioning APIs which I’ll go into detail another time.
Until then, if you have any thoughts, questions, or pointers for more information to share reach out and let me know.