OAuth 2.0 ve OpenID Connect ile Güvenli Bulut Tabanlı Uygulamalar
Bulut uygulamalarınızı OAuth 2.0 ve OpenID Connect ile güvence altına almak ve kimlik doğrulama ve yetkilendirme ile harika bir kullanıcı deneyimi sunmak için eksiksiz bir kılavuz.
Bulut uygulamalarınızı OAuth 2.0 ve OpenID Connect ile güvence altına almak ve kimlik doğrulama ve yetkilendirme ile harika bir kullanıcı deneyimi sunmak için eksiksiz bir kılavuz.
Bulut tabanlı uygulamalar günümüzde trenddir. Uygulama türü değişse de (web, mobil, masaüstü, vb.), hepsi bir hizmet sağlama arka planına sahiptir, depolama, hesaplama ve veritabanları gibi hizmetler sağlarlar. Çoğu zaman, bu uygulamalar kullanıcıları kimlik doğrulamasına ve belirli kaynaklara erişim için yetkilendirmeye ihtiyaç duyar.
Kendi başımıza geliştirdiğimiz kimlik doğrulama ve yetkilendirme mekanizmaları mümkün olsa da, güvenlik bulut uygulamaları geliştirirken en önemli endişelerden biri haline gelmiştir. Neyse ki, sektörümüz, güvenli kimlik doğrulama ve yetkilendirme uygulamamıza yardımcı olacak OAuth 2.0 ve OpenID Connect gibi test edilmiş standartlara sahiptir.
Bu yazı aşağıdaki varsayımları taşımaktadır:
Evet, 2 ve 3 için "duymak" yeterlidir. Bu yazı, gerçek dünya örneklerini kullanarak kavramları açıklayacak ve süreci diyagramlarla aydınlatacaktır. Hadi başlayalım!
OAuth 2.0 ve OpenID Connect hakkında bilgi sahibiyseniz, bu bölümü de okuyabilirsiniz; çünkü bu bölümde bazı gerçek dünya örneklerini ele alacağız. Eğer bu standartlara yeniyseniz de okumaya devam edebilirsiniz, çünkü onları basit bir şekilde tanıtacağız.
OAuth 2.0, bir uygulamanın başka bir uygulama üzerindeki korunan kaynaklara kullanıcı veya uygulamanın kendisi adına sınırlı erişim elde etmesini sağlayan bir yetkilendirme çerçevesidir. Google, Facebook ve GitHub gibi popüler hizmetlerin çoğu sosyal giriş için OAuth 2.0 kullanır (örneğin, "Google ile Giriş Yap").
Örneğin, MyApp adında bir web uygulamanız var ve bu uygulama kullanıcının Google Drive'ına erişmek istiyor. Kullanıcının Google Drive kimlik bilgilerini paylaşmasını istemek yerine, MyApp, OAuth 2.0 kullanarak kullanıcı adına Google Drive'a erişim isteyebilir. İşte basitleştirilmiş bir akış:
Bu akışta, MyApp kullanıcının Google Drive kimlik bilgilerini asla görmez. Bunun yerine, Google'dan, kullanıcı adına Google Drive'a erişmesini sağlayan bir erişim belirteci alır.
OAuth 2.0 terimleriyle, MyApp bir istemci, Google ise basitlik açısından hem yetkilendirme sunucusu hem de kaynak sunucusu olarak görev yapar. Gerçek dünyada, genellikle tek oturum açma (SSO) deneyimi sunmak için ayrı yetkilendirme ve kaynak sunucularımız vardır. Örneğin, Google yetkilendirme sunucusu ve birden fazla kaynak sunucusu olabilir, Google Drive, Gmail ve YouTube gibi.
Dikkat edin, gerçek yetkilendirme akışı bundan daha karmaşıktır. OAuth 2.0'ın farklı yetkilendirme türleri, kapsamlar ve farkında olmanız gereken diğer kavramları vardır. Şimdilik bunu bir kenara bırakalım ve OpenID Connect'e geçelim.
OAuth 2.0 yetkilendirme için harikadır, ancak kullanıcının nasıl tanınacağını (yani kimlik doğrulaması) sağlamaz. OpenID Connect, kimlik doğrulama yetenekleri ekleyen OAuth 2.0 üzerinde bir kimlik katmanıdır.
Yukarıdaki örnekte, MyApp yetkilendirme akışını başlatmadan önce kullanıcıyı tanımalıdır. Burada iki kullanıcı vardır: MyApp'in kullanıcısı ve Google Drive'ın kullanıcısı. Bu durumda, MyApp kendi uygulamasının kullanıcısını tanımalıdır.
Kullanıcıların MyApp'e kullanıcı adı ve şifre kullanarak giriş yapabileceğini varsayalım ve basit bir örnek görelim:
Kendi uygulamamızın kullanıcısını doğruladığımız için, genellikle Google'ın OAuth 2.0 akışında yaptığı gibi izin istemeye gerek yoktur. Bu sırada kullanıcıyı tanımlayabilecek bir şeye ihtiyacımız var. OpenID Connect, Kimlik belirteci ve kullanıcı bilgisi uç noktası gibi kavramları bize yardımcı olmak için getirir.
Kimlik sağlayıcı (IdP), akışta yeni bağımsız bir katılımcıdır. OAuth 2.0'da yetkilendirme sunucusuyla aynıdır, ancak daha iyi bir açıklık için, kullanıcının kimlik doğrulaması ve kimlik yönetiminden sorumlu olduğuna işaret etmek için IdP terimini kullanıyoruz.
İşletmeniz büyüdüğünde, aynı kullanıcı veritabanını paylaşan birden fazla uygulamanız olabilir. OAuth 2.0 gibi, OpenID Connect de size birden fazla uygulama için kullanıcılara kimlik doğrulaması yapabilen tek bir yetkilendirme sunucusu kullanma olanağı tanır. Bir kullanıcı bir uygulamaya zaten giriş yapmışsa, başka bir uygulama onları IdP'ye yönlendirdiğinde tekrar kimlik bilgilerini girmelerine gerek yoktur. Akış, kullanıcı etkileşimi olmadan otomatik olarak gerçekleştirilebilir. Buna tek oturum açma (SSO) denir.
Yine, bu oldukça basitleştirilmiş bir akıştır ve perde arkasında daha fazla detay vardır. Bilgi bombardımanından kaçınmak için bir sonraki bölüme geçelim.
Önceki bölümde, web uygulamalarını örnek olarak kullandık, ancak dünya daha çeşitlidir. Bir kimlik sağlayıcısı için kullandığınız kesin programlama dili, çerçeve veya platform gerçekten önemli değildir. Pratikte, önemli bir fark, uygulamanın bir kamu istemcisi veya bir özel (güvenilir) istemci olup olmadığıdır:
Bunu göz önünde bulundurarak, OAuth 2.0 ve OpenID Connect'in farklı uygulama türlerinde nasıl kullanılabileceğini görelim.
Bu yazının bağlamında "Uygulama" ve "istemci" birbirinin yerine kullanılabilir.
Uygulama bir sunucuda çalışır ve kullanıcılara HTML sayfaları sunar. Express.js, Django ve Ruby on Rails gibi birçok popüler web çerçevesi bu kategoriye girer; ve Next.js ve Nuxt.js gibi backend-for-frontend (BFF) çerçeveleri de dahildir. Bu uygulamaların şu özellikleri vardır:
Bu arada, uygulamanın bir mikro hizmet mimarisi içinde başka iç API hizmetlerine erişmesi veya monolitik bir uygulamanın farklı bölümleri için erişim kontrolüne ihtiyacı olabilir. Bunu "API'nizi Koruyun" bölümünde tartışacağız.
Uygulama, kullanıcının tarayıcısında çalışır ve sunucuyla API'ler aracılığıyla iletişim kurar. React, Angular ve Vue.js, SPA'lar oluşturmak için popüler çerçevelerdir. Bu uygulamaların şu özellikleri vardır:
Genellikle, SPA'lar veri getirme ve güncelleme için başka API hizmetlerine erişmesi gerekir. Bunu "API'nizi Koruyun" bölümünde tartışacağız.
Uygulama bir mobil cihazda (iOS, Android, vb.) çalışır ve sunucuyla API'ler aracılığıyla iletişim kurar. Çoğu durumda, bu uygulamalar SPA'larla aynı özelliklere sahiptir.
Makineden makineye uygulamalar, başka sunucularla iletişim kuran bir sunucuda (makine) çalışan istemcilerdir. Bu uygulamaların şu özellikleri vardır:
Diğer hizmetlere erişirken, uygulama isteğin başlığına erişim belirtecini eklemesi gerekebilir. Bunu "API'nizi Koruyun" bölümünde tartışacağız.
Uygulama IoT cihazında (örneğin, akıllı ev cihazları, giyilebilir cihazlar, vb.) çalışır ve sunucuyla API'ler aracılığıyla iletişim kurar. Bu uygulamaların şu özellikleri vardır:
Sunucuyla iletişim kurarken, cihaz isteğin başlığına erişim belirtecini eklemesi gerekebilir. Bunu "API'nizi Koruyun" bölümünde tartışacağız.
OpenID Connect ile kullanıcıyı tanımlamak ve kullanıcıya özel verileri Kimlik belirteçleri veya kullanıcı bilgisi uç noktaları aracılığıyla getirmek mümkündür. Bu işleme kimlik doğrulaması denir. Ancak, muhtemelen tüm kaynaklarınızı tüm kimliği doğrulanmış kullanıcılara açmak istemezsiniz, örneğin, yalnızca yöneticiler kullanıcı yönetim sayfasına erişebilir.
Bu durumda, yetkilendirme devreye girer. OAuth 2.0'ın bir yetkilendirme çerçevesi olduğunu ve OpenID Connect'in OAuth 2.0 üzerine eklenmiş bir kimlik katmanı olduğunu unutmayın; bu, OpenID Connect zaten kullanılıyorsa OAuth 2.0'ı da kullanabileceğiniz anlamına gelir.
"OAuth 2.0" bölümünde kullandığımız örneği hatırlayalım: MyApp, kullanıcının Google Drive'ına erişmek istiyor. Tüm kullanıcı dosyalarına Google Drive'da erişim izni vermek pratik değildir. Bunun yerine, MyApp'in neye erişmek istediğini açıkça belirtmesi gerekir (örneğin, belirli bir klasördeki dosyalara salt okunur erişim). OAuth 2.0 terimleriyle, bunu bir kapsam olarak adlandırırız.
Bazen "kapsam" kelimesi standart olmayan kullanıcılar için belirsiz göründüğü için "izin" terimini OAuth 2.0 bağlamında "kapsam" ile birbirinin yerine kullanıldığını görebilirsiniz.
Kullanıcı MyApp'e erişim izni verdiğinde, yetkilendirme sunucusu istenen kapsama sahip bir erişim belirteci verir. Erişim belirteci daha sonra kullanıcının dosyalarına erişmek için kaynak sunucuya (Google Drive) gönderilir.
Doğal olarak, Google Drive'ı kendi API hizmetlerimizle değiştirebiliriz. Örneğin, MyApp kullanıcının sipariş geçmişini almak için OrderService'e erişmesi gerekir. Bu sefer, kimlik doğrulama zaten kimlik sağlayıcı tarafından yapıldığından ve hem MyApp hem de OrderService kontrolümüzde olduğundan, kullanıcının erişim izni vermesi gerekmez; MyApp, kimlik sağlayıcı tarafından verilen erişim belirteci ile doğrudan OrderService'e isteği gönderebilir.
Erişim belirteci, kullanıcının kendi sipariş geçmişini okuyabileceğini belirtmek için read:order kapsamını içerebilir.
Şimdi, kullanıcı yanlışlıkla tarayıcıya bir yönetici sayfası URL'si girerse ne olur. Kullanıcı yönetici olmadığından, erişim belirtecinde admin kapsamı yoktur. OrderService isteği reddedecek ve bir hata mesajı döndürecektir.
Bu durumda, OrderService kullanıcının yönetici sayfasına erişim izni olmadığını belirtmek için 403 Yasaklı durum kodunu döndürebilir.
Makineden makineye (M2M) uygulamalar için, süreçte kullanıcı yer almaz. Uygulamalar, kimlik sağlayıcısından doğrudan erişim belirteçleri talep edebilir ve bunları diğer hizmetlere erişmek için kullanabilir. Aynı kavram geçerlidir: erişim belirtecinde kaynaklara erişim için gerekli kapsamlar bulunur.
API hizmetlerinizi korumak için yetkilendirme tasarlarken dikkat etmeniz gereken iki önemli şey vardır:
read:order, write:order) veya daha genel (örneğin, order) olabilir.admin kapsamına sahip olabilir.Erişim kontrolü ile ilgili bazı popüler yaklaşımlar şunlardır:
Her iki yaklaşım için de standart bir erişim kontrol doğrulama yolunun, roller veya öznitelikler yerine erişim belirtecinin kapsamlarını kontrol etmektir. Roller ve öznitelikler çok dinamik olabilir, oysa kapsamlar daha statiktir, bu da yönetimi oldukça kolaylaştırır.
Erişim kontrolüne ilişkin detaylı bilgi için RBAC ve ABAC: Bilmeniz Gereken Erişim Kontrol Modelleri adlı yazıya başvurabilirsiniz.
"Erişim belirteci" terimini birçok kez kullanmamıza rağmen, nasıl elde edileceğini tartışmadık. OAuth 2.0'da, erişim belirteci, başarılı bir yetkilendirme akışının ardından yetkilendirme sunucusu (kimlik sağlayıcı) tarafından verilir.
Google Drive örneğine daha yakından bakalım ve yetkilendirme kodu akışını kullandığımızı varsayalım:
Erişim belirteci verilmesi sürecinde önemli adımlar:
Yukarıdaki örnek, yetkilendirme sunucusu (kimlik sağlayıcı) ile kaynak sunucusunun aynı olduğunu varsayar (Google). Eğer ayrıysa, MyApp ve OrderService örneğini ele alırsak, akış şöyle olur:
Bu akışta, yetkilendirme sunucusu (IdP) MyApp'e hem Kimlik belirteci hem de erişim belirteci verir (adım 8). Kimlik belirteci kullanıcıyı tanımlamak için kullanılırken, erişim belirteci OrderService gibi diğer hizmetlere erişmek için kullanılır. Hem MyApp hem de OrderService birinci taraf hizmetler olduğu için, genellikle kullanıcının erişim izni vermesi gerekmemektedir; bunun yerine, kimlik sağlayıcısındaki erişim kontrolüne dayanarak, kullanıcının kaynaklara erişip erişemeyeceği (yani, erişim belirtecinin gerekli kapsamları içerip içermediği) belirlenir.
Son olarak, erişim belirtecinin makineden makineye (M2M) uygulamalarda nasıl kullanıldığına bakalım. Kullanıcı süreçte yer almadığı ve uygulama güvenilir olduğu için, kimlik sağlayıcısından doğrudan erişim belirteci talep edebilir:
Erişim kontrolü burada da uygulanabilir. OrderService için, kullanıcının kim olduğu veya verileri kimin talep ettiği önemli değildir; sadece erişim belirteci ve içerdiği kapsamlarla ilgilenir.
Erişim belirteçleri genellikle JSON Web Belirteçleri (JWT) olarak kodlanır. JWT hakkında daha fazla bilgi için JSON Web Belirteci (JWT) Nedir? yazısına başvurabilirsiniz.
OAuth 2.0, erişim kontrolü için kapsam kavramını tanıtır. Ancak, kapsamların yeterli olmadığını hızlıca fark edebilirsiniz:
openid, offline_access ve profile gibi bir dizi standart kapsam tanımlar. Bu standart kapsamlarla özel kapsamlarınızı karıştırmak kafa karıştırıcı olabilir.Yaygın bir çözüm, kapsam adlarına kaynak (API hizmeti) belirtmek için son ekler (veya ön ekler) eklemektir. Örneğin, read:order ve read:product, read ve readden daha açıktır. Bir OAuth 2.0 uzantısı olan RFC 8707, istemcinin erişmek istediği kaynak sunucusunu belirtmek için yeni bir resource parametresi getirir.
Gerçek dünyada, API hizmetleri genellikle URL'lerle tanımlanır, bu nedenle yetkilendirme isteklerinde ve erişim belirteçlerinde kaynak göstergeleri olarak URL'leri kullanmak daha doğaldır. Örneğin, OrderService API şöyle temsil edilebilir:
Gördüğünüz gibi, parametre gerçek kaynak URL'lerini yetkilendirme isteklerinde ve erişim belirteçlerinde kullanmanın rahatlığını getirir. RFC 8707'nin tüm kimlik sağlayıcılar tarafından uygulanmamış olabileceğini belirtmekte fayda var. Kimlik sağlayıcınızın resource parametresini destekleyip desteklemediğini görmek için ilgili belgeleri kontrol etmelisiniz (Logto bunu destekler).
Özetle, istemcinin erişmek istediği kaynağı belirtmek için resource parametresi yetkilendirme isteklerinde ve erişim belirteçlerinde kullanılabilir.
Kaynak göstergelerinin erişilebilirliği konusunda herhangi bir kısıtlama yoktur, yani kaynak göstergesi bir API hizmetine işaret eden gerçek bir URL olmak zorunda değildir. Bu nedenle, "kaynak göstergesi" adı, yetkilendirme sürecindeki rolünü doğru şekilde yansıtır. Koruma altına almak istediğiniz kaynakları temsil etmek için sanal URL'ler kullanabilirsiniz. Örneğin, yönetici tarafından erişilebilen kaynağı temsil etmek için uygulamanızda sanal bir URL
https://api.example.com/admintanımlayabilirsiniz.
Bu noktada, OAuth 2.0 ve OpenID Connect'in temelleri ve farklı uygulama türleri ve senaryolarında nasıl kullanılabileceği üzerinde durduk. Bunları ayrı ayrı tartışsak da, iş gereksinimlerinize göre birleştirebilirsiniz. Genel mimari şu kadar basit olabilir:
Veya biraz daha karmaşık:
Uygulamanız büyüdükçe, kimlik sağlayıcı (IdP) mimaride kritik bir rol oynar; ancak doğrudan iş hedeflerinizle ilgili değildir. Bunu güvenilir bir satıcıya yükleme fikri harika olsa da, kimlik sağlayıcısını dikkatli seçmeliyiz. İyi bir kimlik sağlayıcısı süreci büyük ölçüde basitleştirebilir, geliştime çabasını azaltabilir ve sizi potansiyel güvenlik tehlikelerinden koruyabilir.
Modern bulut uygulamaları için kimlik sağlayıcı (veya yetkilendirme sunucusu), kullanıcı kimlik doğrulaması, kimlik yönetimi ve erişim kontrolü için merkezi bir yerdir. Bu yazıda birçok kavramı tartışmış olsak da, böyle bir sistem uygularken göz önünde bulundurulması gereken birçok ayrıntı vardır. Daha fazla bilgi edinmekle ilgileniyorsanız, blogumuzu daha derinlemesine makaleler için inceleyebilirsiniz.