Bearer access token biasanya memberikan otorisasi kepada pihak mana pun yang dapat mempresentasikan nilainya ke resource server. Menyalin token karena itu dapat memindahkan otoritasnya dari client yang semula menerima token tersebut. OAuth 2.0 Demonstrating Proof of Possession, atau DPoP, mengubah sifat ini dengan mengikat token ke public key dan mewajibkan signed proof dari private key pasangannya saat token dipresentasikan.

Binding tersebut mempersempit satu failure mode penting, tetapi tidak mengubah kunci menjadi identitas client universal. DPoP adalah mekanisme sender-constraining pada application layer. Jaminannya bergantung pada token binding, validasi proof, policy replay, TLS, dan keamanan konteks eksekusi client.

Access token membawa key binding

RFC 9449 mendefinisikan DPoP proof sebagai JWT bertanda tangan yang dikirim melalui HTTP header DPoP. Saat token diterbitkan, authorization server dapat mengikat access token yang dihasilkan ke public key yang direpresentasikan oleh proof.

Untuk JWT access token, binding dapat muncul di claim cnf melalui member jkt. jkt adalah JWK Thumbprint SHA-256 dari DPoP public key yang dikodekan dengan base64url.

{
  "cnf": {
    "jkt": "public-key-thumbprint"
  }
}

Opaque token dapat membawa relasi yang sama secara tidak langsung. Resource server dapat memperoleh metadata cnf melalui token introspection dan menjalankan pemeriksaan binding secara lokal.

Properti keamanannya lebih sempit daripada kepemilikan bearer token. Memiliki nilai token saja tidak cukup ketika resource server menegakkan DPoP dengan benar; pihak yang mempresentasikan token juga memerlukan proof valid dari kunci yang terikat.

Proof terikat pada HTTP request tertentu

DPoP proof menyertakan konteks request dan bukan sekadar signature yang dapat dipakai ulang atas access token. Protected JOSE header mengidentifikasi tipe proof, signing algorithm, dan public JWK. Payload JWT memuat claim seperti jti, htm, htu, dan iat.

Untuk akses protected resource, proof juga memuat ath, yang diturunkan dari access token yang dipresentasikan.

DPoP proof
  |
  +-- htm   HTTP method
  +-- htu   target URI
  +-- iat   creation time
  +-- jti   proof identifier
  +-- ath   SHA-256 hash of access token

Resource server memverifikasi signature dan memeriksa bahwa htm cocok dengan method request serta htu cocok dengan target URI sesuai aturan RFC 9449. Server juga menghitung hash access token dan membandingkannya dengan ath, lalu memastikan bahwa proof key cocok dengan kunci yang menjadi binding token.

Pemeriksaan tersebut memiliki fungsi berbeda. htm dan htu membatasi proof pada konteks request. ath mencegah proof yang dibuat untuk satu nilai access token dipasangkan dengan token lain. Binding cnf.jkt menghubungkan token dengan proof key.

Melewatkan salah satu pemeriksaan akan mengubah properti keamanan yang dihasilkan.

Sender constraint bukan client authentication

DPoP tidak mendefinisikan client authentication. Public OAuth client dapat memakai DPoP tanpa memiliki client secret konvensional, dan confidential client dapat menggabungkan DPoP dengan metode autentikasi terpisah.

Pemisahan ini penting ketika authorization policy merujuk pada identitas aplikasi. DPoP proof yang valid membuktikan kepemilikan private key yang berpasangan dengan public key di dalam proof. Token binding kemudian membuktikan bahwa kunci tersebut adalah kunci yang diasosiasikan dengan token. Kedua pernyataan itu sendiri tidak membuktikan identitas client yang spesifik pada deployment kecuali mekanisme atau policy lain menetapkan relasi tersebut.

Pemisahan yang sama berlaku untuk identitas pengguna. DPoP key bukan pengganti subject dan semantik otorisasi yang dibawa oleh OAuth grant serta token yang dihasilkan.

Ketahanan replay bergantung pada policy server

Signed proof tetap merupakan data yang dapat disalin. RFC 9449 mewajibkan pemeriksaan freshness dan mendefinisikan jti sebagai identifier proof yang unik, tetapi penanganan replay memiliki pilihan operasional. Server dapat melacak proof identifier dalam acceptance window dan dapat mewajibkan nonce yang disediakan server.

Nonce challenge menambahkan freshness yang dipilih server:

client                       resource server
  |                                |
  | request + DPoP proof           |
  |------------------------------->|
  | 401 + DPoP-Nonce               |
  |<-------------------------------|
  | request + new proof + nonce     |
  |------------------------------->|

Nonce bersifat opaque bagi client. Setelah server mewajibkan DPoP nonce, RFC 9449 melarang penerimaan proof yang menghilangkan nonce yang diwajibkan. Ini mencegah downgrade dari validasi yang terikat nonce ke policy proof yang lebih lemah.

Nonce yang disediakan server juga menangani pre-generation proof. Tanpa kontribusi server yang tidak dapat diprediksi, kode yang menguasai client key dapat membuat proof dengan timestamp masa depan lalu memindahkan proof tersebut ke tempat lain. Server nonce yang fresh membatasi strategi itu karena proof tidak dapat disiapkan sebelum nonce tersedia.

Penggunaan nonce tidak menghapus kebutuhan pemeriksaan lain. Proof tetap memerlukan request binding, token binding, verifikasi signature, dan freshness yang dapat diterima.

Non-exportable key tidak menetralkan kode client yang hostile

Menyimpan private key di keystore yang non-exportable dapat mencegah ekstraksi langsung material kunci. Properti itu bernilai, tetapi perbedaan antara mengekstrak kunci dan menggunakan kunci sangat penting.

Jika kode hostile berjalan di dalam konteks client dan dapat memanggil operasi signing, kode tersebut mungkin dapat menghasilkan DPoP proof valid selama client masih tersedia. RFC 9449 secara eksplisit memperlakukan untrusted code di konteks client sebagai batas perlindungan mekanisme ini.

Batas yang dihasilkan adalah:

key extraction blocked
        !=
key use blocked

Hardware-backed key atau non-exportable key dapat mengurangi portabilitas kredensial yang dicuri. Properti itu sendiri tidak membuat execution context menjadi tepercaya. Kontrol terhadap script injection, dependency berbahaya, proses yang terkompromi, dan akses tanpa otorisasi ke signing API tetap terpisah.

TLS tetap menjadi bagian dari model keamanan

DPoP menandatangani informasi request tertentu; mekanisme ini bukan protokol integritas HTTP message secara umum. RFC 9449 mengandalkan TLS untuk perlindungan transport.

Sebagai contoh, htu mengikat proof ke target URI berdasarkan aturan perbandingan spesifikasi, sedangkan htm mengikatnya ke method. Proof tidak melindungi setiap request header dan setiap byte body secara kriptografis. Aplikasi tidak boleh menganggap adanya DPoP JWT yang valid sebagai jaminan integritas message secara penuh.

Validasi sertifikat TLS juga tetap diperlukan. Sender-constraining pada access token tidak mengautentikasi peer jaringan sembarang sebagai authorization server atau resource server yang dimaksud.

Pencurian token dan kompromi execution context adalah kasus berbeda

DPoP memberikan perlindungan paling kuat ketika penyerang memperoleh nilai access token tetapi tidak memperoleh private key terkait atau signed proof yang masih dapat dipakai. Dalam kondisi tersebut, enforcement resource server yang benar mencegah token salinan berperilaku seperti bearer credential biasa.

Kompromi yang lebih kuat mengubah analisis. Jika penyerang dapat beroperasi di dalam konteks client, memanggil kunci, menangkap proof valid, atau mengendalikan request sebelum signing, DPoP tidak dapat memulihkan trust boundary semula dengan sendirinya.

Perbedaan ini penting secara operasional. Token storage, key storage, process isolation, integritas script browser, validasi TLS, OAuth authorization policy, dan enforcement DPoP adalah kontrol yang saling melengkapi. Memperlakukan DPoP key sebagai identitas universal atau sebagai pertahanan lengkap terhadap kompromi client memberikan properti yang tidak disediakan protokol.

Enforcement point berada di resource server

Authorization server membentuk relasi token-ke-kunci, tetapi enforcement pada protected resource membuat relasi tersebut memiliki efek praktis. Resource server yang menerima DPoP-bound token sebagai bearer token biasa membuang sender constraint.

Enforcement yang benar karena itu mewajibkan resource server memvalidasi kedua artefak secara bersamaan: access token dan DPoP proof. Server harus memastikan validitas token, validitas proof, request binding, ath, dan public-key binding. Jika nonce policy aktif, validasi nonce menjadi bagian dari rangkaian tersebut.

DPoP menggeser OAuth access token dari kepemilikan murni atas sebuah string menuju kepemilikan string ditambah kendali atas signing key tertentu. Itu adalah batas yang presisi dan berguna. Menjaga batas tersebut tetap presisi juga mencegahnya disalahartikan sebagai client authentication, penandatanganan request secara penuh, atau perlindungan terhadap kode hostile yang sudah beroperasi di tempat kunci dapat digunakan.