Birkaç ay önce, yüzlerce dahili uygulamamıza erişimi yönetmek için bir OpenID Connect sunucusu uyguluyordum. Daha küçük bir ölçekte uygun olan kendi geliştirmelerimizden, genel kabul görmüş bir standarda geçtik. Merkezi hizmet üzerinden erişim, monoton işlemleri büyük ölçüde basitleştirir, yetkilendirme uygulama maliyetini azaltır, birçok hazır çözüm bulmanızı ve yenilerini geliştirirken kafa yormanızı sağlar. Bu yazıda bu geçişten ve doldurmayı başardığımız tümseklerden bahsedeceğim.
Uzun zaman önce... Her şey nasıl başladı?
Birkaç yıl önce, manuel kontrol için çok fazla dahili uygulama varken, şirket içinde erişimi kontrol etmek için bir uygulama yazdık. Çeşitli işlevlere erişimin yapılandırıldığı, çalışanlar hakkında bilgi içeren bir veritabanına bağlanan basit bir Rails uygulamasıydı. Aynı zamanda, istemci ve yetkilendirme sunucusu tarafından belirteçlerin doğrulanmasına dayanan ilk SSO'yu yükselttik, belirteç çeşitli parametrelerle şifrelenmiş biçimde iletildi ve yetkilendirme sunucusunda doğrulandı. Bu en uygun seçenek değildi, çünkü her dahili uygulamanın önemli bir mantık katmanı tanımlaması gerekiyordu ve çalışan veritabanları yetkilendirme sunucusuyla tamamen senkronize edilmişti.
Bir süre sonra, merkezi yetkilendirme görevini basitleştirmeye karar verdik. SSO, dengeleyiciye aktarıldı. OpenResty'nin yardımıyla Lua'ya belirteçleri kontrol eden, isteğin hangi uygulamaya gideceğini bilen ve orada erişim olup olmadığını kontrol edebilen bir şablon eklendi. Bu yaklaşım, dahili uygulamalara erişimi kontrol etme görevini büyük ölçüde basitleştirdi - artık her uygulamanın kodunda ek mantığı açıklamaya gerek yoktu. Sonuç olarak, trafiği harici olarak kapattık ve uygulamanın kendisi yetkilendirme hakkında hiçbir şey bilmiyordu.
Ancak bir sorun çözülmeden kaldı. Peki ya çalışanlar hakkında bilgi gerektiren uygulamalar? Yetkilendirme hizmeti için bir API yazmak mümkündü, ancak bu tür her uygulama için ek mantık eklemeniz gerekecekti. Ek olarak, kendi yazdığımız ve daha sonra OpenSource'a çevrilecek olan uygulamalarımızdan birinin dahili yetkilendirme sunucumuza olan bağımlılığından kurtulmak istedik. Bunu başka bir zaman konuşuruz. Her iki sorunun da çözümü OAuth idi.
ortak standartlara
OAuth, anlaşılır, genel kabul görmüş bir yetkilendirme standardıdır, ancak yalnızca işlevselliği yeterli olmadığı için hemen OpenID Connect'i (OIDC) düşünmeye başladılar. OIDC'nin kendisi, OAuth 2.0 protokolü (bir açık yetkilendirme protokolü) üzerinden bir eklentiye dönüşen açık kimlik doğrulama standardının üçüncü uygulamasıdır. Bu çözüm, son kullanıcı ile ilgili veri eksikliği sorununu kapattığı gibi, yetkilendirme sağlayıcısının değiştirilmesini de mümkün kılmaktadır.
Ancak belirli bir sağlayıcı seçmedik ve mevcut yetkilendirme sunucumuz için OIDC ile entegrasyon eklemeye karar verdik. OIDC'nin son kullanıcı yetkilendirmesi açısından çok esnek olması bu kararın lehine oldu. Böylece mevcut yetkilendirme sunucunuz üzerinde OIDC desteğini hayata geçirmeniz mümkün oldu.
Kendi OIDC sunucumuzu uygulama yöntemimiz
1) Verileri istenen forma getirdi
OIDC'yi entegre etmek için mevcut kullanıcı verilerini standardın anlayabileceği bir forma getirmek gerekir. OIDC'de buna Talepler denir. Talepler, temelde kullanıcı veri tabanındaki nihai alanlardır (ad, e-posta, telefon vb.). var
Ayırt edici özellik grubu, aşağıdaki alt kümede birleştirilir - Kapsam. Yetkilendirme sırasında belirli markalara değil, kapsamdaki bazı markalara ihtiyaç duyulmasa bile kapsamlara erişim talep edilir.
2) Gerekli hibeleri hayata geçirdi
OIDC entegrasyonunun bir sonraki kısmı, hibe adı verilen yetkilendirme türlerinin seçimi ve uygulanmasıdır. Seçilen uygulama ile yetkilendirme sunucusu arasındaki diğer etkileşim senaryosu, seçilen yetkiye bağlı olacaktır. Doğru hibeyi seçmek için örnek bir şema aşağıdaki şekilde gösterilmektedir.
İlk başvurumuzda en yaygın hibe olan Yetki Kodu'nu kullandık. Diğerlerinden farkı üç adımlı olmasıdır, yani. ek testlerden geçiyor. İlk olarak, kullanıcı yetkilendirme izni talebinde bulunur, bir jeton - Yetkilendirme Kodu alır, ardından bu jetonla sanki bir seyahat bileti ile bir erişim jetonu ister. Bu yetkilendirme komut dosyasının tüm ana etkileşimi, uygulama ile yetkilendirme sunucusu arasındaki yönlendirmelere dayalıdır. Bu hibe hakkında daha fazla bilgi edinebilirsiniz
OAuth, yetkilendirmeden sonra elde edilen erişim belirteçlerinin geçici olması ve tercihen ortalama olarak her 10 dakikada bir değişmesi gerektiği konseptine bağlı kalır. Yetkilendirme Kodu hibesi, yönlendirmeler yoluyla üç aşamalı bir doğrulamadır, her 10 dakikada bir böyle bir adımı çevirmek, açıkçası, göze pek hoş gelen bir iş değildir. Bu sorunu çözmek için başka bir hibe daha var - Ülkemizde de kullandığımız Yenileme Simgesi. Burada her şey daha kolay. Başka bir hibeden doğrulama sırasında, ana erişim belirtecine ek olarak, yalnızca bir kez kullanılabilen ve kullanım ömrü genellikle çok daha uzun olan Yenileme Simgesi olan bir tane daha verilir. Bu Yenileme Jetonu ile ana erişim jetonunun TTL'si (Yaşam Süresi) sona erdiğinde, yeni bir erişim jetonu talebi başka bir hibenin bitiş noktasına gelecektir. Kullanılan Yenileme Simgesi hemen sıfırlanır. Bu kontrol iki aşamalıdır ve kullanıcı tarafından algılanmayacak şekilde arka planda gerçekleştirilebilir.
3) Özel veri çıkış formatlarını ayarlayın
Seçilen hibeler hayata geçirildikten, yetkilendirme çalışmaları yapıldıktan sonra son kullanıcı hakkında veri alınmasından bahsetmekte fayda var. OIDC'nin bunun için ayrı bir uç noktası vardır; burada mevcut erişim belirtecinizle ve güncelse kullanıcı verilerini talep edebilirsiniz. Ve kullanıcının verileri çok sık değişmiyorsa ve güncel olanları birçok kez takip etmeniz gerekiyorsa, JWT belirteçleri gibi bir çözüme gelebilirsiniz. Bu belirteçler standart tarafından da desteklenmektedir. JWT belirtecinin kendisi üç bölümden oluşur: başlık (belirteç hakkında bilgi), yük (gerekli herhangi bir veri) ve imza (imza, belirteç sunucu tarafından imzalanır ve daha sonra imzasının kaynağını kontrol edebilirsiniz).
OIDC uygulamasında, JWT belirtecine id_token adı verilir. Normal bir erişim belirteci ile birlikte talep edilebilir ve geriye kalan tek şey imzayı doğrulamaktır. Yetkilendirme sunucusunun bunun için bir grup ortak anahtar biçiminde ayrı bir uç noktası vardır.
Örneğin Google'da:
{
"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"
]
}
Böylece, id_token kullanarak, gerekli tüm ayırt edici özellikleri belirtecin yüküne aktarabilir ve kullanıcı verilerini istemek için her seferinde yetkilendirme sunucusuyla iletişim kurmayabilirsiniz. Bu yaklaşımın dezavantajı, sunucudan kullanıcı verilerindeki değişikliğin hemen değil, yeni bir erişim belirteci ile birlikte gelmesidir.
Uygulama sonuçları
Böylece, kendi OIDC sunucumuzu hayata geçirdikten ve uygulama tarafında ona bağlantıları yapılandırdıktan sonra, kullanıcılar hakkında bilgi aktarma sorununu çözdük.
OIDC açık bir standart olduğundan, mevcut bir sağlayıcıyı veya sunucu uygulamasını seçme seçeneğine sahibiz. Yapılandırılması oldukça uygun olan Keycloak'ı denedik, uygulama tarafında ayarlayıp bağlantı konfigürasyonlarını değiştirdikten sonra kullanıma hazır. Uygulama tarafında geriye kalan tek şey bağlantı yapılandırmalarını değiştirmek.
Mevcut çözümler hakkında konuşmak
Kendi bünyemizde ilk OIDC sunucusu olarak kendi implementasyonumuzu kurduk ve gerekli durumlarda eklemeler yaptık. Diğer hazır çözümleri detaylı bir şekilde inceledikten sonra bunun tartışmalı bir konu olduğunu söyleyebiliriz. Kendi sunucularını uygulama kararı lehine, sağlayıcıların gerekli işlevselliğin olmaması ve bazı hizmetler için farklı özel yetkilerin olduğu eski bir sistemin varlığı ve oldukça fazla olması konusunda endişeleri vardı. çalışanlarla ilgili veriler zaten depolanmıştı. Ancak hazır uygulamalarda entegrasyon için kolaylıklar vardır. Örneğin, Keycloak'ın kendi kullanıcı yönetim sistemi vardır ve veriler doğrudan onun içinde depolanır ve orada kullanıcılarınızı sollamak zor olmayacaktır. Bunu yapmak için Keycloak, gerekli tüm transfer eylemlerini tam olarak gerçekleştirmenize izin verecek bir API'ye sahiptir.
Bence sertifikalı, ilginç bir uygulamanın bir başka örneği de Ory Hydra. İlginç çünkü farklı bileşenlerden oluşuyor. Entegre etmek için, kullanıcı yönetimi hizmetinizi onların yetkilendirme hizmetine bağlamanız ve gerektiğinde genişletmeniz gerekir.
Keycloak ve Ory Hydra kullanıma hazır çözümler değildir. OpenID Vakfı tarafından onaylanmış bir uygulama seçmek en iyisidir. Bu çözümler genellikle bir OpenID Sertifikasyon rozetine sahiptir.
OIDC sunucunuzu korumak istemiyorsanız, mevcut ücretli sağlayıcıları da unutmayın. Bugün birçok iyi seçenek var.
sonra ne
Yakın gelecekte trafiği farklı bir şekilde dahili servislere kapatacağız. Dengeleyicideki mevcut SSO'muzu OpenResty kullanarak OAuth tabanlı bir proxy'ye aktarmayı planlıyoruz. Burada zaten birçok hazır çözüm var, örneğin:
Ek malzemeler
Kaynak: habr.com