OpenID Connect: otorisasi aplikasi internal dari generik ke standar

Beberapa bulan yang lalu, saya mengimplementasikan server OpenID Connect untuk mengontrol akses ke ratusan aplikasi internal kami. Dari perkembangan kami sendiri, nyaman dalam skala yang lebih kecil, kami beralih ke standar yang berlaku umum. Akses melalui layanan pusat sangat menyederhanakan operasi monoton, mengurangi biaya penerapan otorisasi, memungkinkan Anda menemukan banyak solusi yang siap pakai dan tidak mematahkan otak Anda ketika mengembangkan yang baru. Dalam artikel ini saya akan berbicara tentang transisi ini dan benjolan yang berhasil kami isi.

intro

Sekali waktu ... Bagaimana semuanya dimulai


Beberapa tahun yang lalu, ketika ada terlalu banyak aplikasi internal untuk kontrol manual, kami menulis aplikasi untuk kontrol akses di dalam perusahaan. Itu adalah aplikasi Rails sederhana yang terhubung ke database dengan informasi tentang karyawan, di mana akses ke berbagai fungsi dikonfigurasi. Kemudian kami mengangkat SSO pertama, yang didasarkan pada verifikasi token dari klien dan server otorisasi, token ditransmisikan dalam bentuk terenkripsi dengan beberapa parameter dan diperiksa pada server otorisasi. Ini bukan pilihan yang paling nyaman, karena pada setiap aplikasi internal perlu untuk menggambarkan lapisan logika yang cukup, dan basis karyawan sepenuhnya disinkronkan dengan server otorisasi.

Setelah beberapa waktu, kami memutuskan untuk menyederhanakan tugas otorisasi terpusat. SSO ditransfer ke penyeimbang. Dengan menggunakan OpenResty di Lua, mereka menambahkan templat yang memeriksa token, tahu aplikasi mana yang memasukkan permintaan, dan dapat memeriksa apakah ada akses di sana. Pendekatan ini sangat menyederhanakan tugas mengendalikan akses aplikasi internal - dalam kode setiap aplikasi, tidak perlu lagi untuk menggambarkan logika tambahan. Akibatnya, kami menutup lalu lintas secara eksternal, dan aplikasi itu sendiri tidak tahu apa-apa tentang otorisasi.

Namun, salah satu masalah tetap belum terselesaikan. Bagaimana dengan aplikasi yang membutuhkan informasi tentang karyawan? Anda dapat menulis API untuk layanan otorisasi, tetapi kemudian Anda harus menambahkan logika tambahan untuk setiap aplikasi tersebut. Selain itu, kami ingin menghilangkan ketergantungan pada salah satu aplikasi yang kami tulis sendiri, yang lebih berorientasi pada terjemahan ke dalam OpenSource, pada server otorisasi internal kami. Kami akan membicarakannya lain kali. Solusi untuk kedua masalah itu adalah OAuth.

Untuk standar yang diterima secara umum


OAuth adalah standar otorisasi yang dapat dipahami dan diterima secara umum, tetapi karena fungsinya tidak cukup, OpenID Connect (OIDC) segera mulai dipertimbangkan. OIDC sendiri adalah implementasi ketiga dari standar otentikasi terbuka yang telah menyebar ke add-in melalui protokol OAuth 2.0 (protokol otorisasi terbuka). Solusi ini menutup masalah kurangnya data tentang pengguna akhir, dan juga memungkinkan untuk mengubah penyedia otorisasi.

Namun, kami tidak memilih penyedia tertentu dan memutuskan untuk menambahkan integrasi dengan OIDC untuk server otorisasi kami yang ada. Dalam mendukung solusi seperti itu, OIDC sangat fleksibel dalam hal mengotorisasi pengguna akhir. Dengan demikian, dimungkinkan untuk menerapkan dukungan OIDC pada server otorisasi Anda saat ini.

gambar

Cara kami untuk mengimplementasikan server OIDC kami sendiri


1) Mereka membawa data ke formulir yang diinginkan


Untuk mengintegrasikan OIDC, Anda perlu membawa data pengguna saat ini dengan cara yang dapat dimengerti oleh standar. Dalam OIDC, ini disebut Klaim. Merek pada dasarnya adalah bidang akhir dalam basis data pengguna (nama, email, telepon, dll.). Ada daftar merek standar , dan segala sesuatu yang tidak termasuk dalam daftar ini dianggap kebiasaan. Oleh karena itu, poin pertama yang perlu Anda perhatikan jika Anda ingin memilih penyedia OIDC yang ada adalah kemampuan untuk menyesuaikan merek baru dengan mudah.

Kelompok merek digabungkan ke dalam subset berikutnya - Lingkup. Selama otorisasi, akses diminta untuk tidak ke merek tertentu, yaitu ke cakupan, bahkan jika beberapa ciri dari ruang lingkup tidak diperlukan.

2) Menerapkan hibah yang diperlukan


Bagian selanjutnya dari integrasi OIDC adalah pemilihan dan implementasi jenis otorisasi, yang disebut hibah. Skenario selanjutnya dari interaksi aplikasi yang dipilih dengan server otorisasi akan tergantung pada hibah yang dipilih. Skema perkiraan untuk memilih hibah yang tepat disajikan pada gambar di bawah ini.

gambar

Untuk aplikasi pertama kami, kami menggunakan hibah yang paling umum - Kode Otorisasi. Perbedaannya dari yang lain adalah bahwa itu adalah tiga langkah, yaitu melewati verifikasi tambahan. Pertama, pengguna membuat permintaan izin otorisasi, menerima Token - Kode Otorisasi, kemudian dengan token ini, seolah-olah dengan tiket untuk perjalanan, meminta token akses. Semua interaksi utama skenario otorisasi ini didasarkan pada pengalihan antara aplikasi dan server otorisasi. Baca lebih lanjut tentang hibah ini di sini .

OAuth menganut konsep bahwa token akses yang diterima setelah otorisasi harus bersifat sementara dan berubah rata-rata setiap 10 menit. Pemberian Kode Otorisasi adalah pemeriksaan tiga langkah melalui pengalihan, setiap 10 menit, memutar langkah seperti itu, terus terang, bukan pengalaman yang menyenangkan bagi mata. Untuk mengatasi masalah ini, ada hibah lain - Segarkan Token, yang juga kami libatkan. Semuanya lebih sederhana di sini. Selama pengujian, dari hibah lain, selain token akses utama, satu lagi dikeluarkan - Segarkan Token, yang dapat digunakan hanya sekali dan masa pakainya, sebagai suatu peraturan, secara signifikan lebih lama. Dengan Refresh Token ini, ketika TTL (Time to Live) dari token akses utama berakhir, permintaan untuk token akses baru akan sampai ke titik akhir dari hibah lain. Refresh Token yang digunakan segera direset.Pemeriksaan semacam itu adalah dua langkah dan dapat dilakukan di latar belakang, tanpa terlihat oleh pengguna.

3) Format output data pengguna yang disesuaikan


Setelah hibah terpilih diimplementasikan, otorisasi berfungsi, perlu disebutkan penerimaan data tentang pengguna akhir. OIDC memiliki titik akhir yang terpisah untuk ini, di mana Anda dapat meminta data pengguna dengan token akses Anda saat ini dan ketika relevan. Dan jika data pengguna tidak terlalu sering berubah, dan Anda harus mengikuti arus berkali-kali, Anda dapat mengambil keputusan seperti token JWT. Token ini juga didukung oleh standar. Token JWT itu sendiri terdiri dari tiga bagian: header (informasi tentang token), payload (semua data yang diperlukan) dan tanda tangan (tanda tangan, token ditandatangani oleh server dan Anda dapat memeriksa sumber tanda tangannya di masa mendatang).

Dalam implementasi OIDC, token JWT disebut id_token. Itu dapat diminta bersama dengan token akses reguler, dan yang tersisa adalah memverifikasi tanda tangan. Server otorisasi memiliki titik akhir yang terpisah untuk ini dengan sekelompok kunci publik dalam format JWK . Dan berbicara tentang ini, perlu disebutkan bahwa ada titik akhir lain yang, berdasarkan standar RFC5785, mencerminkan konfigurasi server OIDC saat ini. Ini berisi semua alamat titik akhir (termasuk alamat gantungan kunci publik yang digunakan untuk penandatanganan), merek dan cakupan yang didukung, algoritma enkripsi yang digunakan, hibah yang didukung, dll.

Misalnya di Google:
{
 "issuer": "https://accounts.google.com",
 "authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth",
 "device_authorization_endpoint": "https://oauth2.googleapis.com/device/code",
 "token_endpoint": "https://oauth2.googleapis.com/token",
 "userinfo_endpoint": "https://openidconnect.googleapis.com/v1/userinfo",
 "revocation_endpoint": "https://oauth2.googleapis.com/revoke",
 "jwks_uri": "https://www.googleapis.com/oauth2/v3/certs",
 "response_types_supported": [
  "code",
  "token",
  "id_token",
  "code token",
  "code id_token",
  "token id_token",
  "code token id_token",
  "none"
 ],
 "subject_types_supported": [
  "public"
 ],
 "id_token_signing_alg_values_supported": [
  "RS256"
 ],
 "scopes_supported": [
  "openid",
  "email",
  "profile"
 ],
 "token_endpoint_auth_methods_supported": [
  "client_secret_post",
  "client_secret_basic"
 ],
 "claims_supported": [
  "aud",
  "email",
  "email_verified",
  "exp",
  "family_name",
  "given_name",
  "iat",
  "iss",
  "locale",
  "name",
  "picture",
  "sub"
 ],
 "code_challenge_methods_supported": [
  "plain",
  "S256"
 ],
 "grant_types_supported": [
  "authorization_code",
  "refresh_token",
  "urn:ietf:params:oauth:grant-type:device_code",
  "urn:ietf:params:oauth:grant-type:jwt-bearer"
 ]
}


Dengan demikian, menggunakan id_token, Anda dapat mentransfer semua tanda yang diperlukan ke payload token dan tidak menghubungi server otorisasi setiap kali untuk meminta data tentang pengguna. Kerugian dari pendekatan ini adalah bahwa mengubah data pengguna dari server tidak datang segera, tetapi dengan token akses baru.

Hasil implementasi


Jadi, setelah mengimplementasikan server OIDC kami sendiri dan mengatur koneksi ke sisi aplikasi, kami memecahkan masalah pengiriman informasi pengguna.
Karena OIDC adalah standar terbuka, kami memiliki kesempatan untuk memilih penyedia atau implementasi server yang ada. Kami mencoba Keycloak, yang ternyata sangat mudah dikonfigurasikan, setelah mengatur dan mengubah konfigurasi koneksi di sisi aplikasi, siap untuk bekerja. Di sisi aplikasi, hanya mengubah konfigurasi koneksi.

Berbicara tentang solusi yang ada


Sebagai bagian dari organisasi kami, sebagai server OIDC pertama, kami mengumpulkan implementasi kami, yang ditambahkan sesuai kebutuhan. Setelah meninjau secara terperinci solusi siap pakai lainnya, kita dapat mengatakan bahwa ini adalah poin yang dapat diperdebatkan. Kekhawatiran pihak penyedia tentang kurangnya fungsionalitas yang diperlukan berfungsi sebagai solusi untuk implementasi server mereka, serta keberadaan sistem lama di mana terdapat berbagai otorisasi khusus untuk beberapa layanan dan cukup banyak data disimpan tentang karyawan. Namun, dalam implementasi yang sudah jadi, ada kemudahan untuk integrasi. Misalnya, Keycloak memiliki sistem manajemen penggunanya sendiri dan data disimpan langsung di dalamnya, dan tidak akan sulit untuk menyalip penggunanya di sana. Untuk ini, Keycloak memiliki API yang akan memungkinkan Anda untuk sepenuhnya menerapkan semua langkah yang diperlukan untuk transfer.

Contoh lain dari sertifikasi, menarik, menurut saya, implementasi adalah Ory Hydra. Sangat menarik karena terdiri dari berbagai komponen. Untuk integrasi, Anda perlu menautkan layanan manajemen pengguna Anda dengan layanan otorisasi mereka dan memperluas seperlunya.

Keycloak dan Ory Hydra bukan satu-satunya solusi turnkey. Yang terbaik adalah memilih implementasi OpenID Foundation yang bersertifikat. Biasanya, solusi semacam itu memiliki lencana Sertifikasi OpenID.

Sertifikasi terbuka


Juga, jangan lupa tentang penyedia berbayar yang ada jika Anda tidak ingin menyimpan server OIDC Anda. Ada banyak opsi bagus hingga saat ini.

Apa berikutnya


Dalam waktu dekat, kami akan menutup lalu lintas ke layanan internal dengan cara lain. Kami berencana untuk mentransfer SSO kami saat ini pada penyeimbang menggunakan OpenResty ke proksi berdasarkan OAuth. Ada juga banyak solusi siap pakai di sini, misalnya:
github.com/bitly/oauth2_proxy
github.com/ory/oathkeeper
github.com/keycloak/keycloak-gatekeeper

Bahan tambahan


jwt.io - layanan yang bagus untuk memeriksa
openid.net/developers/certified JWT token - daftar implementasi OIDC bersertifikat

All Articles