Aller au contenu principal

Jetons de tuiles signés

Pourquoi​

Une clé API embarquée dans une application mobile peut toujours être extraite du binaire ou interceptée sur le réseau, et elle n'expire jamais. Les jetons de tuiles signés résolvent ce problème : votre backend détient un secret de signature et émet des jetons à courte durée de vie pour votre application ; votre application récupère les tuiles avec ?token= au lieu de ?api_key=.

  • Un jeton qui fuite expire de lui-même (durée de vie recommandée : 24 h, maximum strict : 7 jours).
  • Le secret de signature ne quitte jamais vos serveurs, et vous pouvez le révoquer depuis le tableau de bord à tout moment ; chaque jeton en circulation meurt instantanément.
  • Le trafic par jeton puise dans le même quota de tuiles et les mêmes limites de débit que votre plan ; rien de nouveau à gérer côté facturation.
Your app ──(your existing auth)──► Your backend
◄──── signed token (JWT, exp ≤ 7 d) ─────┘
│
└──► https://tiles.geocodeme.net/streets/{z}/{x}/{y}.png?token=eyJ...
└─► geocodeme verifies the signature, expiry & your plan limits

1. Créer un secret de signature​

Tableau de bord → Clés API → Secrets de signature des tuiles → Générer un secret de signature.

Vous obtenez deux valeurs :

ValeurExempleRôle
Identifiant de clé (kid)tsk_9f27ab31c04dIdentifiant public, placé dans le header du JWT.
Secretgm_tss_...Clé de signature HMAC-SHA256. Affichée une seule fois : stockez-la dans le gestionnaire de secrets de votre backend, jamais dans une application.

Jusqu'à deux secrets peuvent être actifs en même temps, ce qui permet une rotation sans interruption : générez le nouveau secret, déployez votre backend avec, puis révoquez l'ancien. Les applications récupèrent automatiquement de nouveaux jetons (voir l'étape 3), la rotation ne nécessite donc aucune nouvelle version de l'application.

2. Émettre des jetons dans votre backend​

Un jeton est un JWT (HS256) standard avec votre kid dans le header :

PartieChampValeur
HeaderalgHS256 (seul algorithme accepté)
HeaderkidVotre identifiant de clé (tsk_...), requis
Claimsscope"tiles", requis
ClaimsexpExpiration Unix, requise, au plus 7 jours dans le futur
ClaimsiatDate d'émission, recommandée
ClaimssubRéférence opaque optionnelle (par ex. l'identifiant de votre utilisateur) pour votre propre traçabilité
import os
import time
import jwt # pip install pyjwt

TILE_KID = os.environ["GEOCODEME_TILE_KID"] # tsk_... (public id)
TILE_SECRET = os.environ["GEOCODEME_TILE_SIGNING_SECRET"] # gm_tss_...

def mint_tile_token(lifetime_seconds: int = 86_400) -> str:
now = int(time.time())
return jwt.encode(
{"scope": "tiles", "iat": now, "exp": now + lifetime_seconds},
TILE_SECRET,
algorithm="HS256",
headers={"kid": TILE_KID},
)

Exposez le jeton via un endpoint authentifié de votre API, par ex. :

GET /map/tile-token → { "token": "eyJ...", "expires_at": 1789300000 }
Jetons compatibles CDN

Le CDN de tuiles met en cache par URL complète : un jeton différent par utilisateur fragmente donc le cache edge. Émettez un jeton partagé par jour (mémoïsez-le côté serveur et distribuez le même jeton à chaque utilisateur authentifié) : vous conservez le modèle de sécurité à courte durée de vie et un cache CDN chaud.

3. Utiliser les jetons dans votre application​

Récupérez un jeton au démarrage de la carte, et récupérez-en un nouveau quand une requête de tuile renvoie 401 (jeton expiré) :

// 1. Récupérez un jeton depuis VOTRE backend (appel authentifié)
final tileToken = await api.getTileToken();

// 2. Utilisez-le dans l'URL de tuile
TileLayer(
urlTemplate:
'https://tiles.geocodeme.net/streets/{z}/{x}/{y}{r}.png?token=$tileToken',
retinaMode: RetinaMode.isHighDensity(context),
userAgentPackageName: 'com.example.app',
),
RichAttributionWidget(
attributions: [TextSourceAttribution('© OpenMapTiles © OpenStreetMap contributors')],
),

// 3. Sur 401 (jeton expiré) : récupérez un nouveau jeton et reconstruisez le TileLayer
// (p. ex. gardez le jeton dans un state notifier dont dépend le TileLayer).

Erreurs​

StatutCauseQue faire
401Jeton manquant/expiré, signature incorrecte, mauvais scope, kid inconnu ou révoqué, exp à plus de 7 jours dans le futurRécupérez un nouveau jeton depuis votre backend. Si le problème persiste, vérifiez la paire secret/kid.
429Limite de débit de tuiles ou quota mensuel de tuiles de votre plan dépasséRalentissez ; consultez Tuiles de carte pour les limites par plan.

Le modèle de sécurité, en toute honnêteté​

Les jetons sont des identifiants au porteur (bearer) : quelqu'un qui extrait le jeton courant de son propre appareil peut récupérer des tuiles avec jusqu'à son expiration. Ce que la conception garantit, c'est que les dégâts sont bornés (par la durée de vie du jeton, par le débit/quota de tuiles de votre plan et par des limites par IP à notre edge) et que la récupération est instantanée : révoquez le secret dans le tableau de bord et chaque jeton signé avec lui cesse de fonctionner immédiatement. C'est le même modèle que les jetons temporaires des grands fournisseurs de cartes, sans renoncer à la rotation en autonomie.