Krátkodobé tokeny
Možnost zabezpečení komunikace pomocí krátkodobých tokenů.
Princip
- Mapy.com API – náš server s mapovými službami (
api.mapy.com), - Váš server – backend, který provozujete vy,
- Vaše aplikace – klientská aplikace u uživatele (web, mobilní nebo desktopová aplikace).
Místo trvalého API klíče dostane Vaše aplikace token platný 15 minut. Token jí předá Váš server, který si ho vyžádá od Mapy.com API pomocí secretu. Secret Váš server nikdy neopustí. Zkopírovaný token tak jde zneužít nanejvýš 15 minut a nový si útočník sám nevydá.
| Údaj | Kde je | Tajný? |
|---|---|---|
| Secret projektu | jen na Vašem serveru | ano |
| API klíč | jen na Vašem serveru | ano |
| Token (15 min) | ve Vaší aplikaci | ne, uvidí ho kdokoli |
Token dědí omezení svého API klíče (služby, doména, IP, User-Agent) a spotřeba se počítá pod tento klíč.
Vaše aplikace ──GET /api/mapy-token──► Váš server ──POST /v1/auth/token (secret)──► Mapy.com API
Vaše aplikace ◄──{token, expiresAt}─── Váš server ◄──{token, expiresAt}──────────
Vaše aplikace ──dlaždice, suggest… ?token=… ────────────────────────────────────► Mapy.com API
Nastavení v API portálu
1. Vytvořte secret projektu. V administraci API projektu, v sekci se secrety:
- Celá hodnota secretu se zobrazí jen jednou. Hned ji uložte do konfigurace Vašeho serveru.
- Volitelně omezte secret na IP adresy Vašeho serveru.
- Jeden secret slouží pro všechny API klíče projektu.
- Při úniku secret zneplatněte. Už vydané tokeny doběhnou do konce platnosti.
2. Nastavte API klíč, pro který chcete tokeny vydávat:
| Nastavení klíče | Chování |
|---|---|
| přístup přes token vypnutý (výchozí) | funguje jen klíč; token pro něj vydat nejde |
| „Povolit přístup přes token“ | funguje klíč i token; vhodné pro přechodné období |
| + „Vyžadovat token“ | funguje jen token, samotný klíč Mapy.com API odmítne (403) |
Teprve s nastavením „Vyžadovat token“ přestane mít zkopírovaný API klíč cenu. Dokud je zapnuté jen „Povolit“, jde Mapy.com API dál volat samotným klíčem.
Váš server: jeden sdílený token z cache
/v1/auth/token na Mapy.com API má rate limit (429). Váš server proto všem uživatelům Vaší aplikace rozdává stejný token z cache a nový si vyžádá až 2 minuty před expirací, tedy zhruba jednou za 13 minut.
Kde to běží: na Vašem serveru (příklad je Node.js s Expressem; v jiném jazyce je postup stejný).
Jak to funguje:
- Endpoint
/api/mapy-tokenje adresa, kterou volá Vaše aplikace. - Funkce
getToken()vrátí token z paměti, pokud do jeho expirace zbývají víc než 2 minuty. - Jinak si od Mapy.com API vyžádá nový token. Pošle secret v hlavičce a API klíč v těle požadavku.
- Když o token požádá víc uživatelů najednou, všichni počkají na jedno společné vydání (proměnná
issuing). Na Mapy.com API tak odejde jen jeden požadavek.
// SECRET a API_KEY načtěte z konfigurace Vašeho serveru (např. proměnné prostředí)
let cached; // poslední token { token, expiresAt }
let issuing; // právě probíhající žádost o nový token
async function getToken() {
// Token v paměti ještě platí aspoň 2 minuty → vrátíme ho
if (cached && Date.now() < Date.parse(cached.expiresAt) - 120_000) return cached;
// Jinak vyžádáme nový; souběžné žádosti sdílí tentýž požadavek
issuing ??= fetch('https://api.mapy.com/v1/auth/token', {
method: 'POST',
headers: { 'X-MAPY-API-SECRET': SECRET, 'Content-Type': 'application/json' },
body: JSON.stringify({ apiKey: API_KEY }),
})
.then(r => (r.ok ? r.json() : Promise.reject(new Error(`Mapy.com API vrátilo ${r.status}`))))
.finally(() => (issuing = null));
return (cached = await issuing);
}
// overPristup = Vaše kontrola, kdo smí token dostat (přihlášení, rate limit…)
app.get('/api/mapy-token', overPristup, async (req, res) => {
res.set('Cache-Control', 'no-store'); // odpověď s tokenem se nemá ukládat do cache
res.json(await getToken()); // { token, expiresAt }
});
Vaše aplikace: použití a obnova tokenu
Kde to běží: ve Vaší aplikaci u uživatele. Příklad je webová mapa v Leafletu; v mobilní nebo desktopové aplikaci je postup stejný.
Jak to funguje:
- Vaše aplikace si token vyžádá od Vašeho serveru, nikdy přímo od Mapy.com API. Secret nezná.
- S tokenem pak volá přímo Mapy.com API: mapové dlaždice i další funkce.
- Podle
expiresAtsi naplánuje další obnovu 2 minuty před vypršením. Tím vznikne smyčka, která token obnovuje, dokud aplikace běží. - Při výměně tokenu se mapa nepřekreslí. Nové dlaždice se jen začnou načítat s novým tokenem.
let token; // aktuální token
let layer; // vrstva mapových dlaždic
async function refresh() {
// 1. Nový token od Vašeho serveru
const res = await fetch('/api/mapy-token');
const data = await res.json(); // { token, expiresAt }
token = data.token;
// 2. Token do URL mapových dlaždic (true = bez překreslení mapy)
const url = `https://api.mapy.com/v1/maptiles/basic/256/{z}/{x}/{y}?token=${token}`;
layer ? layer.setUrl(url, true) : (layer = L.tileLayer(url).addTo(map));
// 3. Další obnova 2 minuty před vypršením
setTimeout(refresh, Date.parse(data.expiresAt) - Date.now() - 120_000);
}
await refresh();
// Ostatní funkce Mapy.com API: token v parametru `token` nebo v hlavičce X-MAPY-API-TOKEN
const suggest = await fetch('https://api.mapy.com/v1/suggest?query=Praha', {
headers: { 'X-MAPY-API-TOKEN': token },
});
Co ukázka pro stručnost vynechává, ale Vaše aplikace by mít měla:
- Při odpovědi 401/403 si vyžádat nový token a požadavek jednou zopakovat.
- Při výpadku sítě zkusit obnovu znovu za chvíli (např. za 30 s), ne hned v cyklu.
- Po návratu z pozadí zkontrolovat, jestli token ještě platí. Na pozadí se časovače zpomalují nebo zastavují.
Čemu to brání a čemu ne
Brání:
- trvalému zneužití zkopírovaného přístupu, protože token po 15 minutách přestane platit,
- úniku secretu a API klíče, protože se do Vaší aplikace nedostanou,
- dalšímu vydávání tokenů po úniku: stačí zneplatnit secret,
- použití tokenu na cizím webu, pokud má API klíč omezení na doménu (platí jen pro web).
Nebrání:
- tomu, aby si kdokoli stáhl token z endpointu
/api/mapy-tokenna Vašem serveru (třeba skriptem každých 13 minut) nebo ho vyčetl z provozu Vaší aplikace. Token není tajemství. - použití tokenu ze skriptu, kde lze hlavičky jako
RefererneboUser-Agentpodvrhnout, - čerpání Vašich kvót tímto tokenem.
CORS se týká jen webu: zabrání tomu, aby JavaScript na cizí stránce přečetl odpověď Vašeho serveru. Mobilní a desktopové aplikace, skripty ani servery CORS neřeší, takže to není ochrana proti útočníkovi.