How to Build a Geofenced Web App in JavaScript
In cybersecurity, we often focus entirely on cryptographic boundaries—passwords, encryption keys, and tokens. But sometimes, the strongest security layer is a physical one. What if you want to share a WiFi password, but only with someone physically standing inside your office?
By implementing a Geofence, we can restrict access to web content based on the user's GPS coordinates. In this tutorial, we will use the native navigator.geolocation API and the Haversine formula to build a client-side location lock in Vanilla JavaScript.
Step 1: Fetching the User's Coordinates
Before we can verify if a user is inside a permitted area, we need to ask their browser for their current location. Modern browsers require the site to be served over HTTPS to access this API, and it will trigger a permission prompt for the user.
function getUserLocation() {
return new Promise((resolve, reject) => {
if (!navigator.geolocation) {
reject("Geolocation is not supported by your browser.");
} else {
navigator.geolocation.getCurrentPosition(
(position) => {
resolve({
lat: position.coords.latitude,
lng: position.coords.longitude
});
},
(error) => {
reject("Location access denied or unavailable.");
},
{ enableHighAccuracy: true, timeout: 10000 }
);
}
});
}
Step 2: The Math (The Haversine Formula)
The Earth is not flat. If you have two sets of GPS coordinates (the target location and the user's current location), you cannot simply use the Pythagorean theorem to find the distance between them.
Instead, we must use the Haversine formula, which calculates the shortest distance over the earth's surface, giving an "as-the-crow-flies" distance. Here is the highly optimized JavaScript implementation of that formula:
function getDistanceInMeters(lat1, lon1, lat2, lon2) {
const R = 6371e3; // Earth's radius in meters
const rad = Math.PI / 180; // Conversion factor to radians
// Convert latitudes to radians
const phi1 = lat1 * rad;
const phi2 = lat2 * rad;
// Calculate differences in radians
const deltaPhi = (lat2 - lat1) * rad;
const deltaLambda = (lon2 - lon1) * rad;
// Haversine core math
const a = Math.sin(deltaPhi / 2) * Math.sin(deltaPhi / 2) +
Math.cos(phi1) * Math.cos(phi2) *
Math.sin(deltaLambda / 2) * Math.sin(deltaLambda / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
// Return the final distance in meters
return R * c;
}
Step 3: Creating the Geofence Logic
Now we combine our two functions. Let's say we have an encrypted document, and the sender locked it to a specific coffee shop's coordinates. We only want to decrypt the document if the person opening the link is within 50 meters of that coffee shop.
async function verifyGeofence(targetLat, targetLng, maxRadiusInMeters) {
try {
console.log("Requesting GPS coordinates...");
const userLocation = await getUserLocation();
const distance = getDistanceInMeters(
targetLat, targetLng,
userLocation.lat, userLocation.lng
);
if (distance <= maxRadiusInMeters) {
console.log(`Success! You are ${Math.round(distance)}m away.`);
return true; // Proceed with decryption/access
} else {
console.error(`Access Denied: Out of bounds by ${Math.round(distance)}m.`);
return false; // Lock the app or destroy the payload
}
} catch (error) {
console.error("Geofence check failed:", error);
return false;
}
}
Security Considerations
It is important to understand that client-side GPS coordinates can be spoofed by advanced users using developer tools or VPNs with location spoofing. Therefore, a geofence should never be your *only* layer of security. It should be used as a "defense-in-depth" measure alongside strong encryption and authentication.
See Geofencing in Production
We implemented this exact Haversine formula inside ZeroKey, allowing users to lock their encrypted payloads to their current physical location.
If the recipient attempts to open the link outside of a 50-meter radius, the system detects the boundary breach, triggers a UI lockout, and immediately purges the payload from the server.
Conclusion
By combining the Geolocation API with some basic trigonometry, you can add a powerful physical security layer to your web applications. Whether you are building a secure check-in system, a localized file drop, or a burn-after-reading vault, geofencing is an excellent tool to have in your frontend architecture toolkit.