What Happens When Site Wants to Know Your Location - How I Voided My Firefox Warranty
Jayson DeLancey
Posted on November 27, 2023
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 recommended places can be made more relevant, navigation and routing can be started sooner, your items can be found more quickly, and the content you read or media you watch can be more personalized and adhere to applicable regulations (for instance gaming laws or media distribution rights).
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 to http://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.
Positioning APIs
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.
// Use Express for the server
const express = require('express');
const request = require('request');
const app = express();
// Will need to parse and modify the body of the request with middleware
const parser = require('body-parser');
app.use(parser.urlencoded({extended: true}));
app.use(parser.json());
// Handler for a POST request from Firefox
app.post('/', function(req, res) {
// Rewrite body for Positioning API request
var body = {"wlan": []};
req.body["wifiAccessPoints"].forEach(function(ssid) {
body["wlan"].push({
"mac": ssid["macAddress"],
"powrx": ssid["signalStrength"]
});
});
console.log(body);
// Get your HERE APP_ID and APP_CODE from https://developer.here.com/projects
// and set as environment variables to construct URL
var app_id = process.env.APP_ID;
var app_code = process.env.APP_CODE;
var positioning_uri = `https://pos.api.here.com/positioning/v1/locate?app_id=${app_id}&app_code=${app_code}`
console.log(positioning_uri);
// Proxy to the HERE Positioning API
request.post(positioning_uri, {json: true, body: body}, function(err, result) {
if (err) { console.log(err) } else {
console.log(result.body);
res.status(result.statusCode).send(result.body);
}
});
});
// Listen for Geolocation API requests from Firefox
var port = process.env.PORT || 8000;
app.listen(port, () => console.log(`Listening now on port ${port}`));
Next Steps
By using a positioning API to find a precise location of a user, it is only a matter of some additional math to figure out whether or not any particular user is viewing content (such as streaming media) within a particular venue or geographic region.
This can be a very important consideration for media distribution rights-holders or for activities that require adherence to local laws regarding gaming.
Posted on November 27, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 27, 2023
August 31, 2023