Verifikasi JWT Harus Mengikat Algorithm, Key, dan Issuer
Token yang ditandatangani dapat valid secara kriptografis tetapi tetap tidak dapat diterima oleh service yang menerimanya. Signature menjawab pertanyaan sempit: byte token cocok dengan signature yang dibuat menggunakan cryptographic key tertentu di bawah algorithm tertentu. Authorization bergantung pada kumpulan fakta yang lebih luas, termasuk siapa yang mengendalikan key tersebut, issuer mana yang dipercaya, audience mana yang dituju token, dan algorithm mana yang memang dimaksudkan aplikasi untuk diterima.
Deployment JWT menjadi rapuh ketika keputusan tersebut disimpulkan dari token itu sendiri. Token adalah input yang dikendalikan attacker sampai verification selesai. Header-nya dapat menyebut algorithm, mengidentifikasi key, atau menunjuk ke key material, tetapi field tersebut tidak dapat menetapkan trust policy verifier. Field itu hanyalah selector yang beroperasi di dalam policy yang ditentukan di tempat lain.
Perbedaan ini memisahkan validasi token yang kuat dari kelas kegagalan authentication yang berulang. Pola berbahayanya bukan JWT sebagai format, melainkan membiarkan pesan yang tidak dipercaya menegosiasikan aturan yang digunakan untuk menetapkan authenticity-nya sendiri.
Header adalah input, bukan policy
JWT yang dilindungi JWS umumnya membawa header alg yang mengidentifikasi signature algorithm dan dapat membawa nilai kid untuk memilih key. Keduanya memiliki peran protocol yang sah. Namun, keduanya tidak boleh memperluas apa yang dipercaya verifier.
Aplikasi yang mengharapkan token bertanda tangan RS256 dapat mengonfigurasi algorithm tersebut sebagai pilihan allowlist dan menolak token yang mendeklarasikan apa pun di luar set itu. Verifier kemudian dapat menggunakan kid untuk memilih di antara key yang sudah dikaitkan dengan trusted issuer. Ini berbeda secara material dari menerima algorithm apa pun yang muncul di header lalu meminta generic library untuk membuatnya bekerja.
Kelemahan algorithm confusion historis menunjukkan biaya dari mencampurkan peran tersebut. Beberapa implementasi dapat dipaksa memperlakukan key material yang ditujukan untuk asymmetric algorithm sebagai symmetric HMAC secret ketika token memilih HMAC algorithm. Jika verifier menerima kedua interpretasi tanpa policy tetap, informasi publik dapat menjadi cukup untuk menghasilkan signature yang dianggap valid oleh aplikasi.
Library modern umumnya menyediakan API yang lebih aman dan default yang lebih kuat, tetapi application policy tetap penting. Library yang mendukung banyak algorithm tidak berarti setiap algorithm yang didukung termasuk dalam trust domain yang sama. Capability dan acceptance adalah keputusan yang terpisah.
Algorithm khusus none menunjukkan batas yang sama. Unsecured JWT didefinisikan oleh spesifikasi JOSE untuk context yang memang sengaja mengizinkannya. Authentication service yang mengharapkan signed token tidak memiliki alasan untuk menerima mode tersebut hanya karena serialization dapat merepresentasikannya.
Pemilihan key memerlukan trust domain yang terbatas
Sistem identity berskala besar merotasi signing key, sehingga verifier sering membutuhkan lebih dari satu public key yang valid pada saat yang sama. JSON Web Key Set memberi issuer representasi standar untuk memublikasikan key tersebut, sementara kid memungkinkan token menunjukkan member mana yang digunakan untuk signature-nya.
Interpretasi yang aman bersifat terbatas: pilih key bernama tersebut dari key set milik issuer yang sudah dipercaya. Masalah muncul ketika key discovery menjadi terbuka tanpa batas.
Header JOSE dapat membawa field seperti jku, yang mengidentifikasi JWK Set URL, dan jwk, yang dapat menyematkan key. Fitur ini memiliki penggunaan sah dalam protocol yang mendefinisikan bagaimana nilainya diautentikasi dan dibatasi. Verifier aplikasi umum tidak boleh memperlakukan URL arbitrer atau embedded key yang diberikan bearer token sebagai otomatis dipercaya. Melakukannya dapat mereduksi signature verification menjadi sekadar memeriksa bahwa attacker menandatangani token menggunakan key milik attacker sendiri.
Remote key retrieval juga memperkenalkan outbound network boundary. Jika service mengambil key material dari lokasi yang dikendalikan token, validasi token dapat berinteraksi dengan internal network reachability, redirect, perilaku DNS, caching, dan availability. Konfigurasi issuer-to-key-source yang tetap menjaga concern tersebut berada di bawah kendali operator.
Key identifier juga memerlukan pembatasan serupa. kid biasanya adalah opaque selector, bukan filesystem path, database expression, shell fragment, atau URL. Implementasi yang menginterpolasikannya ke subsystem lain dapat mengubah metadata field yang tidak berbahaya menjadi injection surface. Key lookup paling aman ketika identifier memilih dari bounded collection, bukan membangun resource location baru.
Signature valid tidak mengidentifikasi intended issuer
Cryptographic verification membuktikan possession atas signing key. Aplikasi masih perlu menghubungkan key tersebut dengan identity authority yang dipercaya.
Claim iss menyediakan issuer identifier, tetapi sekadar memeriksa bahwa claim tersebut ada tidaklah cukup. Verifier yang melayani satu trust domain dapat mewajibkan issuer yang diharapkan secara persis dan memperoleh key dari konfigurasi yang terkait dengan issuer tersebut. Sistem yang mendukung beberapa issuer memerlukan mapping eksplisit dari issuer identity ke validation policy dan key material-nya.
Hal ini sangat penting pada multi-tenant platform dan service yang menerima token dari beberapa identity provider. Jika key dari issuer yang tidak terkait digabungkan dan key mana pun yang cocok dapat memvalidasi token apa pun, token yang diterbitkan dalam satu trust domain dapat diterima di trust domain lain. Signature tetap genuine; trust binding-nya yang salah.
Audience validation menutup batas lain. Claim aud mengidentifikasi recipient yang dituju token. Token yang diterbitkan untuk satu API tidak boleh menjadi general credential bagi setiap service yang kebetulan mempercayai issuer dan signing key yang sama. Setiap service dapat mewajibkan expected audience-nya sendiri atau protocol-defined resource indicator lain.
Karena itu, pemeriksaan issuer dan audience melakukan pekerjaan berbeda. Issuer validation mengidentifikasi authority yang membuat pernyataan. Audience validation membatasi di mana pernyataan tersebut dimaksudkan untuk dikonsumsi. Signature verification saja tidak memberikan kedua jaminan tersebut.
Time claim adalah policy dengan batas clock
JWT umumnya menggunakan exp untuk menetapkan expiration time dan nbf untuk menunjukkan waktu sebelum token tidak boleh diterima. Claim opsional iat mencatat issuance time. Nilai ini adalah timestamp NumericDate, dinyatakan sebagai detik sejak Unix epoch menurut spesifikasi JWT.
Time validation terlihat sederhana sampai distributed system bertemu clock drift, queueing, retry, dan cached credential. Clock-skew allowance kecil dapat masuk akal secara operasional, tetapi harus disengaja dan dibatasi. Toleransi yang terlalu besar diam-diam memperpanjang masa berlaku token pada kedua ujungnya.
Expiration juga tidak menyediakan immediate revocation. Self-contained access token dapat tetap valid hingga expiry kecuali arsitektur di sekitarnya menambahkan mekanisme revocation atau introspection. Lifetime pendek mengurangi exposure tersebut tetapi meningkatkan ketergantungan pada refresh flow dan availability identity provider.
Perbedaan ini penting selama incident response. Menonaktifkan account atau merotasi application secret tidak selalu menginvalidasi setiap access token yang telah diterbitkan dan dapat diverifikasi secara independen. Operator perlu mengetahui tipe credential mana yang diperiksa terhadap live state dan mana yang terus mengandalkan signed claim hingga validity period berakhir.
Nama claim tidak menciptakan authorization semantics
JWT memudahkan pengiriman role, group, scope, tenant identifier, dan application claim lain. Format JWT tidak mendefinisikan makna authorization dari arbitrary claim.
Service yang menerima role: admin tetap membutuhkan policy yang menetapkan issuer mana yang boleh membuat assertion tersebut, untuk audience mana, di bawah token type mana, dan bagaimana nilainya dipetakan ke local privilege. Menggunakan ulang nama claim di beberapa issuer tidak membuat semantics-nya setara.
Token type confusion adalah risiko arsitektural terkait. Identity system dapat menerbitkan ID token, access token, refresh token, logout token, dan signed object lain dengan sintaks yang tumpang tindih. Komponen yang menerima JWT apa pun yang ditandatangani dengan benar dapat secara tidak sengaja mengonsumsi token yang dibuat untuk protocol role berbeda.
Validasi yang kuat mengikat token ke expected context-nya. Bergantung pada protocol, ini dapat mencakup issuer, audience, token type, authorized party, scope, nonce value, atau claim lain dengan semantics yang didefinisikan. Set persisnya bergantung pada protocol; memperlakukan setiap JWT sebagai bearer credential yang dapat dipertukarkan menghilangkan perbedaan tersebut.
Key rotation adalah bagian dari verification, bukan pengecualian
Tekanan operasional sering muncul selama signing-key rotation. Key baru harus tersedia sebelum token yang ditandatangani dengannya tiba, sementara key lama mungkin perlu tetap dipublikasikan sampai token yang membawa signature-nya kedaluwarsa. Cache memperumit transisi karena verifier mungkin tidak me-refresh key set pada saat yang sama.
Desain yang resilient menangani overlap ini tanpa mengubah kegagalan key lookup menjadi discovery tanpa batas. Nilai kid yang tidak dikenal dapat memicu controlled refresh dari configured key endpoint milik issuer, dengan rate limiting dan caching yang mencegah arbitrary token menyebabkan outbound traffic berlebihan. Kegagalan menemukan key setelah refresh tetap merupakan verification failure.
Emergency rotation memiliki constraint berbeda. Jika private signing key diduga compromised, mempertahankan public key-nya sampai ordinary token expiry menjaga availability tetapi juga mempertahankan kemampuan attacker untuk membuat token yang diterima. Menghapus key dapat langsung menginvalidasi legitimate session. Ini adalah trade-off incident response, bukan routine cache problem, dan sistem diuntungkan jika memiliki prosedur eksplisit sebelum kondisi tersebut terjadi.
Observability membantu di sini. Metric untuk unknown key identifier, signature failure, issuer mismatch, audience failure, dan key-set refresh dapat mengekspos deployment mistake maupun hostile traffic. Logging full bearer token tidak diperlukan dan dapat menciptakan credential leak; structured failure reason dan non-sensitive identifier biasanya cukup.
Verification adalah sebuah relationship, bukan sekadar cryptographic checkbox
Keamanan JWT paling kuat ketika verification dinyatakan sebagai relationship antara known issuer, bounded algorithm set, trusted key material, intended recipient, dan protocol-specific claim rule. Token menyediakan evidence di dalam relationship tersebut. Token tidak mendefinisikan relationship itu sendiri.
Framing ini juga membuat architecture review lebih konkret. Pertanyaan pentingnya adalah dari mana issuer configuration berasal, bagaimana key source dipasang ke issuer, algorithm mana yang boleh digunakan setiap issuer, bagaimana audience dipisahkan, bagaimana token type dibedakan, dan apa yang terjadi selama rotation atau compromise.
Hasil signature berwarna hijau hanyalah salah satu input bagi keputusan tersebut. Security boundary yang sebenarnya baru muncul setelah verifier menetapkan bahwa signature dibuat di bawah trust policy persis seperti yang dimaksudkan aplikasi untuk ditegakkan.