Secure latlng with scoped JWTs
Give every tracker, dashboard, and operator a token that can do exactly what it needs — and nothing else. You'll enable JWT auth, mint scoped tokens with latlng-cli, and check the boundaries.
Intermediate · about 10 minutes · tested against latlng v0.2.0
Before you start
-
latlng-serverandlatlng-clifrom a release archive, Homebrew, or Docker. - Collections named with a shared prefix, such as
fleet-hamburg.
01 Plan who needs what
A tracking system has very different clients. A tracker in a truck should only write its own fleet's positions. A dispatch dashboard reads and subscribes. An operator manages hooks. latlng expresses this with permissions scoped to collection name patterns — which is why naming fleets fleet-hamburg, fleet-berlin, and so on pays off.
02 Generate a secret and configure the server
latlng-cli can generate an HMAC secret and mint tokens for self-hosted setups. require_auth makes the server refuse to start without a verifier, and disable_bearer_token turns off the static all-powerful token.
latlng-cli token secret > .latlng-jwt-secret require_auth = true
disable_bearer_token = true
jwt_secret = "<contents of .latlng-jwt-secret>"
jwt_algorithm = "HS256"
jwt_issuer = "https://id.example.com"
jwt_audience = "latlng"
[storage]
type = "aof"
path = "./data/appendonly.aof" latlng-server --config ./latlng.toml
curl -s -o /dev/null -w "%{http_code}\n" -X POST http://127.0.0.1:7421/collections/fleet-hamburg
# 401 03 Mint tokens with presets
Presets bundle common action sets. writer can read and write objects, readonly can read and query, dashboard can query and subscribe to live events, and hooks-admin / channels-admin manage geofences. Each is limited to the collections you pass with --collection, which accepts glob patterns.
# Short-lived admin token for setup
ADMIN=$(latlng-cli token create --config ./latlng.toml --subject ops --ttl 15m --admin)
# A tracker that may only write to Hamburg-style fleets
TRACKER=$(latlng-cli token create --config ./latlng.toml \
--subject truck-17 --ttl 24h --preset writer --collection 'fleet-*')
# A dashboard that reads and subscribes, but can't write
DASHBOARD=$(latlng-cli token create --config ./latlng.toml \
--subject dispatch-ui --ttl 8h --preset dashboard --collection 'fleet-*') 04 Check what each token can do
Create two collections as admin, then try the tracker token against both. Writes inside fleet-* succeed; anything else is rejected with 403.
curl -s -X POST http://127.0.0.1:7421/collections/fleet-hamburg -H "Authorization: Bearer $ADMIN"
curl -s -X POST http://127.0.0.1:7421/collections/billing -H "Authorization: Bearer $ADMIN"
curl -s -X POST http://127.0.0.1:7421/collections/fleet-hamburg/objects/truck-17 \
-H "Authorization: Bearer $TRACKER" -H 'content-type: application/json' \
-d '{"object":{"Point":{"lat":53.55,"lon":9.99,"z":null}}}'
# {"ok":true,"stored":true}
curl -s -X POST http://127.0.0.1:7421/collections/billing/objects/x \
-H "Authorization: Bearer $TRACKER" -H 'content-type: application/json' \
-d '{"object":{"Point":{"lat":53.55,"lon":9.99,"z":null}}}'
# {"error":"forbidden"} 05 Inspect and verify tokens
token inspect decodes a token without checking its signature; token verify checks it against your config. The permissions live in the latlng_permissions claim.
{
"aud": "latlng",
"iss": "https://id.example.com",
"sub": "truck-17",
"latlng_permissions": [
{
"collections": ["fleet-*"],
"actions": [
"collections:list", "collections:inspect",
"objects:read", "objects:write", "objects:delete",
"queries:read"
]
}
]
} 06 Use tokens from the SDK
Pass the token to the client; it's sent with every HTTP request and used to authenticate WebSocket subscriptions.
import { LatLngClient } from "@latlng/sdk";
const client = new LatLngClient({
leaderUrl: "https://latlng.internal.example.com",
token: process.env.LATLNG_TOKEN,
}); latlng serves plain HTTP. In production, terminate TLS at a reverse proxy, load balancer, or ingress in front of it, so tokens never cross the network unencrypted. To use an existing identity provider instead of HMAC secrets, configure jwks_url — see authentication modes.
What you built
- A server that rejects unauthenticated requests.
- Tracker, dashboard, and admin tokens with different permissions.
- Collection-scoped access using name patterns like
fleet-*.
Organize vehicles into fleets, track live positions and status, find the nearest available vehicle, and get alerts when vehicles enter or leave depots.
Use case Asset tracking and theft alertsKeep track of trailers, containers, and equipment across sites, raise an alert when an asset leaves its yard, and detect trackers that stop reporting.