JWT: құрылымы мен осалдықтары
1) JWT дегеніміз не және ол қайда пайдаланылады
JWT - 'Base64Url (header) форматындағы ықшам өзін-өзі қамтамасыз ететін бекітулер контейнері (claims). Base64Url(payload). Base64Url(signature)`.
Мыналар үшін пайдаланылады:- JWS (қол қойылған белгілер - түпнұсқалық/тұтастық),
- JWE (шифрланған токендер - құпиялылық),
- access/ID токендері, сондай-ақ service-to-service аутентификациясы ретінде OIDC/OAuth2.
Артықшылықтары: дербестік, кэшталу, шағын үстеме шығыстар. Кемшіліктері: дұрыс емес валидация тәуекелі, кері қайтарып алудың күрделі жағдайлары.
2) JWT құрылымы
2. 1 Тақырып (header, JSON)
Ең аз: кілттің алгоритмі мен идентификаторы.
json
{ "alg": "ES256", "kid": "jwt-2025-10", "typ": "JWT" }
'alg': қолтаңба/шифрлау алгоритмі (RS256/ES256/PS256/HS256 және т.б.).
'kid': кілт меңзері (JWKS-ротациясы үшін).
Кілттердің опциондық көздері: 'jku', 'x5u' (осалдықты қараңыз § 6. 3).
2. 2 Пайдалы жүктеме (payload, JSON)
Стандартталған таңбалар:- `iss` (issuer), `aud` (audience), `sub` (subject)
- 'exp' (аяқталу уақыты), 'nbf' (ерте емес), 'iat' (берілген)
- 'jti' (пікір үшін жарамды токен идентификаторы)
- domain-таңбалар: 'scope/roles', 'tenant', 'kyc _ level' және т.б.
2. 3 Қолтаңба (signature)
JWS = `sign(base64url(header) + "." + base64url(payload), private_key)`
Тексеру: қатаң түрде жария кілтпен және дәл сервер күтетін алгоритммен.
3) Тексерудің базалық инварианттары
1. Алгоритм 'header' мазмұнына сенбейді, ресурс-сервердің (allow-list) конфигурациясымен тіркеледі. alg`.
2. 'iss' және 'aud' дегенді дәл сәйкестікке тексеру, 'exp/nbf' - шағын 'clock _ skew' (± 30-60s) есебімен.
3. Егер жалғыз кілт болмаса және айналмаса ғана 'kid' деп аталатын белгілерді қабылдамау; басқаша - 'kid' дегенді талап ету.
4. Нысандық деңгейде авторланбай (BOLA-first) ешқандай таңбаларға сенбеу.
5. Парсинг - крипто тексеруден кейін; декодтауға дейінгі өлшемді базалық тексеру.
4) JWS vs JWE
JWS: қол қойылған, бірақ оқимыз. Payload PII/құпияларына кірмеңіз.
JWE: payload шифрлайды; интеграция күрделірек, негізгі модель сыни.
Көптеген API жеткілікті JWS + payload сезімтал деректерге тыйым салу.
5) Токеннің өмірлік циклі
Access: қысқа мерзім (5-30 минут).
Refresh: ұзақ (7-30 күн), rotate-on-use (бір рет пайдаланылатын), «қара тізім» 'jti/sid' -ді сақтау.
Revocation: TTL-мен 'jti' тізімдері, opaque-токендер үшін интроспекция, оқиғалар кезінде 'exp' қысқарту.
Кілттерді ротациялау: JWKS (ескі + жаңа), «Кілттерді ротациялау» мақаласын қараңыз.
6) Жиі осалдықтар және оларды қалай жабу керек
6. 1 'alg = none '/алгоритмді алмастыру
Мән: сервер 'alg' өрісіне сенеді және қол қойылмаған токенді қабылдайды.
Қорғау: серверде қатты allow-list алгоритмдері; 'none' және күтпеген мәндерді қабылдамау.
6. 2 RS256 → HS256 swap (симметрияландыру)
Қорытынды: шабуыл жасаушы 'alg' HS256 ауыстырады және HMAC құпиясы ретінде жария кілтті пайдаланады.
Қорғаныс: кілтті конфигурация алгоритміне байланыстыру; симметриялы/асимметриялы провайдерлерді бір 'kid' дегенге араластыруға болмайды.
6. 3 Кілттерді инъекциялау ('kid/jku/x5u')
Сценарийлер:- 'jku' шабуылшы бақылайтын JWKS дегенді көрсетеді (өзінің кілтін қояды).
- 'x5u '/' x5c' сыртқы куәліктерді теріс пайдалану.
- 'kid' жолы/SQL ('../../privkey. pem '' немесе '' 'OR 1 = 1 --' ').
- Қашықтағы 'jku/x5u' дегенді елемеу немесе қатаң allow-list домендерін сүзу.
- 'kid' файлдық жолдарсыз/SQL конкатенацияларсыз жергілікті каталогтағы (кесте/кеш) кілт ретінде ғана қолданылады.
- JWKS сенімді URL-ден жүктеу, қысқа TTL, қолтаңба/пиннинг арнасы.
6. 4 HS256 әлсіз құпиялары (брутфорс)
Мәні: HMAC-құпия қысқа/жылыстау → қолтаңбаны ауыстыру.
Қорғау: ассиметрияны (RS/ES/PS) немесе құпия ұзындығын ≥ 256 бит, құпияларды - тек KMS-те ғана пайдалану.
6. 5 Жоқ/салидті емес таңбалар
Жоқ 'aud '/' iss '/' exp' → кросс-сервистік жарамды немесе шексіз.
Өте ұзақ 'exp' → компромисс қаупі.
Қорғау: 'exp' таңбаларының толық жиынтығын талап ету, 'nbf '/' iat' таңбаларын 'clock _ skew' деп растау.
6. 6 Replay және токенді ұрлау
Мәні: токенді ұстап алу/қайталау (логтардағы ағу, XSS, MitM TLS-сіз).
Қорғау:- TLS везде, `Secure`+`HttpOnly` cookie, SameSite=Lax/Strict.
- DPoP/PoP (токенді клиенттік кілтке байланыстыру) және/немесе серіктестерге арналған mTLS.
- Қысқа 'exp', refresh-ротация, device-binding.
6. 7 XSS/сақтау орны арқылы ағып кету
Мәні: JWT 'localStorage '/' sessionStorage' → JS қол жетімді.
Қорғау: access-токендерді HttpOnly-cookie (егер cookie-модель мүмкін болса) + қатаң CSP/Trusted Types-те сақтау.
Cookie жоқ SPA үшін - есте токенді оқшаулау, минималды өмір сүру, XSS-тен қорғау.
6. 8 CSRF
Мәні: cookie-сессиялар кезінде үшінші тараптың сайтынан сұраулар.
Қорғау: SameSite, anti-CSRF белгілер (double submit), 'Origin/Referer' тексеру, Fetch-Metadata сүзгілері.
6. 9 Oversize/өлшемді теріс пайдалану
Мәні: үлкен payload/тақырыптар, DoS парсинг.
Қорғау: тақырыптар/дене өлшемдерінің лимиттері, early-reject 431/413, таңбалардың фикс-жинағы.
6. 10 'typ '/' cty' алмастыру
Мәні: JOSE-нысандар ('typ:' JWT ') түрлерінің шатасуы.
Қорғау: қауіпсіздік үшін 'typ/cty' дегенді елемеу, бекітілген алгоритмдер мен таңбалар схемасына сүйену.
7) Токендерді сақтау және беру
7. 1 Серверлік API (machine-to-machine)
mTLS/HMAC, мүмкіндігінше JWT үшін асимметрия, арналар - mesh арқылы.
Кілттер қоймасы - KMS/HSM, кесте бойынша ротация, жабыны бар JWKS.
7. 2 Браузерлік клиенттер
HttpOnly Secure Cookie для access/refresh; қысқа TTL; жаңарту - «silent refresh» арқылы 'SameSite = None' тек HTTPS арқылы.
Қатаң CSP, Сенімді типтер, XSS қорғау; SPA үшін - мүмкіндігінше токенді дискіде сақтауға болмайды.
8) JWKS, ротация және қайтарып алу
JWKS авторизатор жариялайды; тұтынушылар 5-15 минутқа кэш жасайды.
Айналым жоспары: жаңа 'kid' қосу → онымен қол қоюды бастау → N күннен кейін ескісін JWKS → purge-ден жою.
Пікір: 'jti/sid' c TTL тізімдері; оқыс оқиға кезінде уақытша 'exp' және форс-logout (мүгедек refresh) қысқарту.
9) Multi-tenant және деректерді азайту
'tenant '/' org' дегенді тек сәулет бойынша қосу; әйтпесе PDP төлсипаттарын 'sub' бойынша тарту.
Ешқандай PII; → таңбалардың ең аз жиынтығы ағу және корелляция қаупін азайтады.
10) Практикалық валидация чек-парағы (ресурс сервері)
- Парсим қолды және базалық өлшем лимиттерін тексергеннен кейін ғана.
- конфигурациядан 'alg'; күтпеген жағдайларды қабылдамау.
- 'iss' ∧ 'aud' ∧ 'exp' ∧ 'nbf' ∧ 'iat' (c 'clock _ skew').
- Жергілікті/JWKS (қысқа TTL) каталогы бойынша 'kid' дегенді тексеру.
- Сыртқы көрсеткіштерді сүзу/қалыпқа келтіру ('jku/x5u' - тек allow-list).
- Таңбалардың ұзындығын/құрамын шектеу (схема).
- Нысанды авторизацияны ресурсқа қолдану (BOLA-first).
- 'kid', 'sub', 'aud', 'iss', 'jti', 'exp', 'tenant', 'trace _ id' (PII-сыз) логиндеу.
- Қол қою қателерінің, мерзімін өткізіп алудың, ротация аудитінің өлшемдері.
11) Қауіпсіз саясаттың мысалдары (жалған)
11. 1 Алгоритм күту конфигурациясы
yaml jwt:
expected_issuer: "https://auth. example. com"
expected_audience: ["wallet-service"]
allowed_algs: ["ES256"] # fix the jwks_url: "https ://auth. example. com/.well-known/jwks. json"
jwks_cache_ttl: 600s clock_skew: 60s required_claims: ["iss","aud","sub","exp","iat"]
11. 2 Қашықтағыдан бас тарту 'jku/x5u'
yaml reject_untrusted_key_sources: true allowed_jku_hosts: ["auth. example. com"] # if absolutely necessary
11. 3 Пікірлер тізімінің мысалы (Redis)
pseudo if redis. exists("revoke:jti:" + jti) then deny()
if now() > exp then deny()
12) Бақылау және форензия
Метрики: `jwt_verify_fail_total{reason}`, `jwt_expired_total`, `jwks_refresh_total`, доля `kid`.
Логтар (құрылымдалған): 'iss/aud/sub/kid/jti/exp/tenant/trace _ id', бас тарту себебі.
Дашбордтар: «жақын арада бітетін», валидация қателерінің көбеюі, өңірлер/клиенттер бойынша бөлу.
Алерттар: 'verify _ fail' (қолтаңба/алгоритм), JWKS қателері, мерзімі өткен токендер үлесі.
13) Антипаттерндер
'alg' токеніне сену; 'none' дегенді қолдайды.
Ұзақ өмір сүретін access-токендер және refresh-ротацияның болмауы.
HS256/құпия ENV-де KMS-сіз.
Кез келген доменнен 'jku/x5u' қабылдау; JWKS-ті allow-list-сіз динамикалық қотару.
PII/құпияларды payload JWS-ке салу.
XSS-қатерлер болған жағдайда 'localStorage' токендерін сақтау.
Валидация қателерін өшіру («soft error» арқылы 200 қайтару).
BOLA-тексерулердің болмауы және 'scope/role' -ге ғана сүйену.
14) iGaming/Қаржы ерекшелігі
Таңбалар: 'kyc _ level', 'risk _ tier', 'tenant', қатаң 'aud'.
Write-операциялары үшін қысқа TTL (депозиттер/қорытындылар), күрделі бағыттар үшін PoP/DPoP немесе mTLS.
Реттеушілік аудит: кіру/істен шығудың өзгермейтін журналдары, өңір шекарасында логтарды сақтау.
Серіктестерде/PSP - жеке кілттер/' aud ', пер-тенант кілттер және жеке JWKS.
15) Prod-дайындық чек-парағы
- Қатты allow-list алгоритмдері; 'none' тыйым салынған.
- 'iss/aud/exp/nbf/iat/jti' тексеріледі; қысқа 'exp'.
- JWKS, қысқа TTL кэш; 'kid' үлестерінің мониторингі.
- Refresh — rotate-on-use; 'jti/sid' деген TTL тізімдері; пікірлер ойнатқышы.
- Сыни бағыттардағы PoP/DPoP немесе mTLS.
- HttpOnly-cookies үшін браузер, CSP/Trusted Types vs XSS; CSRF-қорғау.
- PII-сіз payload; таңбалардың ең аз жиынтығы.
- Валидация және бас тарту бойынша метриктер/логтар; JWKS/verify_fail алерті.
- Теріс сценарий тестілері: RS → HS swap, 'kid' -инъекция, 'jku' spoofing, oversize, clock-skew.
16) TL; DR
Алгоритмді және кілттерді сервер жағына жазыңыз, 'alg' дегенге сенбеңіз, 'iss/aud/exp/nbf/iat/jti' дегенді талап етіңіз. Кілттерді JWKS арқылы жабумен ротациялаңыз, белгілерді қысқа өмір сүретін, ал refresh - бір рет пайдаланылатын күйде ұстаңыз. Токендерді қауіпсіз сақтаңыз (веб үшін HttpOnly-cookie), таңбаларды азайтыңыз, PII қоймаңыз. 'jku/x5u/kid' -векторларын жабыңыз, әлсіз құпиялармен HS256 болдырмаңыз, сыни жолдарда PoP/DPoP немесе mTLS қосыңыз және әрқашан ресурс деңгейіне BOLA тексерулерін жасаңыз.