Rate Limits
Klubero SSO implementuje rate limiting pro zajištění stability služby a prevenci zneužití.
Tabulka Rate Limits
Všechny rate limity jsou aplikovány per IP adresa.
| Endpoint | Limit | Okno | Účel |
|---|---|---|---|
/connect/token | 10 požadavků | 15 minut | Ochrana proti brute-force útokům na přihlašovací údaje |
/api/twofactor/* | 5 požadavků | 5 minut | Ochrana proti brute-force útokům na ověřovací kódy |
/api/magiclink/send | 3 požadavky | 5 minut | Prevence spamu e-mailů |
/connect/authorize | 30 požadavků | 1 minuta | Ochrana proti DoS a enumeraci redirect URI |
Odpověď při překročení limitu
Když překročíte rate limit:
HTTP/1.1 429 Too Many Requests
Retry-After: 300
{
"error": "rate_limit_exceeded",
"error_description": "Too many requests. Please retry after 300 seconds.",
"retry_after": 300
}
Zpracování Rate Limits
- Kontrolujte status odpovědi: Hledejte HTTP 429
- Čtěte Retry-After header: Udává počet sekund k čekání
- Implementujte exponential backoff: Pro automatizované systémy
- Cachujte tokeny: Opakovaně používejte access tokeny dokud nevyprší
Osvědčené postupy
Dělejte
- Cachujte a opakovaně používejte tokeny dokud nevyprší
- Používejte refresh tokeny místo opětovné autentizace
- Implementujte správné zpracování chyb s backoff
- Seskupujte operace kde je to možné
Nedělejte
- Žádat o nový token pro každé API volání
- Znovu se autentizovat pro každou relaci
- Okamžitě opakovat při selhání
- Dělat mnoho sekvenčních požadavků
Příklad: Cachování tokenů
let tokenCache = {
accessToken: null,
expiresAt: null
};
async function getAccessToken() {
// Vrátit cachovaný token pokud je stále platný (s 60s rezervou)
if (tokenCache.accessToken && tokenCache.expiresAt > Date.now() + 60000) {
return tokenCache.accessToken;
}
// Požádat o nový token
const response = await fetch('/connect/token', {
method: 'POST',
body: new URLSearchParams({
grant_type: 'client_credentials',
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET
})
});
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After') || 60;
throw new Error(`Rate limited. Zkuste znovu za ${retryAfter} sekund.`);
}
const data = await response.json();
tokenCache.accessToken = data.access_token;
tokenCache.expiresAt = Date.now() + (data.expires_in * 1000);
return tokenCache.accessToken;
}