Bir neçə ay əvvəl, bizim daxili tətbiqlərin yüzlərləini idarə etmək üçün OpenID Connect serverinin reallaşdırılması ilə məşğul oldum. Kiçik miqyaslarda daha rahat olan öz həllərimizdən, qəbul edilmiş standartlara keçdik. Mərkəzi xidmət vasitəsilə giriş monoton əməliyyatları xeyli asanlaşdırır, avtorizasiya tətbiqlərinin icra xərclərini azaldır, hazır həlləri tapmağı mümkünsüz edir və yeni həllərin hazırlanmasında baş sındırmağa ehtiyac qalmır. Bu məqalədə bu keçid barədə və başımıza gələn bəzi çətinliklərdən danışacağam.

Çoxdan… Hər şey necə başlamışdı
Bir neçə il əvvəl, daxili tətbiqlərin sayı əl ilə idarə etməyə artıq çoxaldığı zaman, şirkət daxilində girişləri idarə etməyə kömək edəcək bir tətbiq yazdıq. Bu, işçilər haqqında məlumatların olduğu verilənlər bazasına qoşulmuş sadə bir Rails tətbiqi idi, burada müxtəlif funksiyalardan istifadə üçün giriş tənzimlənirdi. Eyni zamanda, müştəri və avtorizasiya serverinin tokenləri yoxlayan ilk SSO-nu qurdıq. Token, şifrələnmiş formada bir neçə parametrlə göndərilirdi və avtorizasiya serveri tərəfindən yoxlanılırdı. Bu, hər daxili tətbiqdə əlavə bir dövrə yaratmaq tələb olunduğundan olduqca rahat deyildi və işçilərin verilənlər bazası tamamilə avtorizasiya serveri ilə sinxronizasiya olunurdu.
Bir müddət sonra mərkəzləşdirilmiş avtorizasiya işini asanlaşdırmağı qərara aldıq. SSO-ları balanslayıcıya köçürdük. Lua ilə OpenResty istifadə edərək, tokenləri yoxlayan, hansı tətbiqə sorğu göndərildiyini bilən və oraya girişi yoxlaya bilən bir şablon əlavə etdik. Bu yanaşma daxili tətbiqlərin girişini idarə etməyi xeyli asanlaşdırdı — hər bir tətbiqin kodunda əlavə məntiqi izah etməyə ehtiyac qalmadı. Nəticədə, trafikimizi xaricdən bağladıq və tətbiq birbaşa avtorizasiyadan xəbərsiz idi.
Ancaq bir problem hələ də həll edilməmiş qaldı. İşçilərlə bağlı məlumat lazım olan tətbiqlərlə nə edəcəyik? Avtorizasiya xidməti üçün bir API yazmaq olardı, lakin bu halda hər bir tətbiq üçün əlavə məntiq əlavə etmək lazım olacaqdı. Bundan əlavə, OpenSource-a keçməyi planlaşdıran bir öz tətbiqimizdən asılı olmağı arzu edirdik, bizindəki daxili avtorizasiya serverimizdən. Onun haqqında başqa bir vaxt danışarıq. Hər iki problemin həlli OAuth oldu.
Qəbul edilmiş standartlara
OAuth — aydın, qəbul edilmiş bir autentifikasiya standartıdır, amma onun funksionallığı kifayət etmir, buna görə də OpenID Connect (OIDC) nəzərə alınmağa başlandı. OIDC, əsasında, OAuth 2.0 (açıq autentifikasiya protokolu) üstündəki üçüncü açıq standartdır. Bu həll, son istifadəçi haqqında məlumatların olmaması problemini aradan qaldırır və autentifikasiya provayderinin dəyişdirilməsinə imkan tanıyır.
Amma biz konkret provayder seçməyi düşünmədik və mövcud autentifikasiya serverimizə OIDC inteqrasiyasını əlavə etməyə qərar verdik. Bu qərar üçün səbəb, OIDC-nin son istifadəçinin autentifikasiyasında çox çevik olmasıdır. Beləliklə, OIDC dəstəyini mövcud autentifikasiya serverimizdə tətbiq etmə imkanı oldu.

Öz OIDC-serverimizi həyata keçirmək yolumuz
1) Məlumatları lazım olan formata gətirdik
OIDC inteqrasiyası üçün, mövcud istifadəçi məlumatlarını standart üçün başa düşülən formata gətirmək lazımdır. OIDC-də buna Claims (İddialar) deyilir. İddialar, əslində, istifadəçilərin verilənlər bazasındakı son sahələrdir (ad, e-poçt, telefon və s.). , bu siyahıya daxil olmayan hər şey isə özəldir. Bu səbəbdən, mövcud OIDC provayderini seçmək istəsəniz, yeni iddiaların asan uyğunlaşdırılmasında nəzərə alınmalı ilk məqamdır.
İddialar qrupu aşağıdakı alt küme - Scope (Hüdud) ilə birləşir. Autentifikasiya zamanı spesifik iddialara deyil, tam olaraq hüdudlara giriş izni istənilir, hətta hüduddan istifadə olunmayan bəzi iddialar olsa belə.
2) Lazım olan grantları həyata keçirdik
OIDC inteqrasiyasının növbəti hissəsi, autentifikasiyanın növlərini, yəni grantları seçmək və həyata keçirməkdir. Seçilmiş grant, seçilmiş tətbiqin autentifikasiya serveri ilə qarşılıqlı təsirinin gələcək ssenarisini müəyyən edəcək. Seçim zamanı lazım olan grantı seçməyin təxminən sxemi aşağıda göstərilir.

İlk tətbiqimiz üçün, ən geniş yayılmış grant olan Authorization Code-dan istifadə etdik. Bunun üstünlüyü, onun üç mərhələli olmasıdır, yəni əlavə bir yoxlamadan keçir. İlk növbədə, istifadəçi autentifikasiya icazəsi üçün müraciət edir, Authorization Code adlı token alır, sonra bu token ilə, sanki nəqliyyat bileti kimi, giriş tokeni tələb edir. Bu autentifikasiya ssenarisi çərçivəsindəki əsas qarşılıqlı əlaqə tətbiq ilə autentifikasiya serveri arasında yönləndirmələr əsasında qurulmuşdur. Bu grant haqqında daha ətraflı məlumatı burada oxuya bilərsiniz. .
OAuth, hüquqi etibarnamələrin müvəqqəti olmasını və ən azı 10 dəqiqədən bir dəyişdirilməsini tələb edir. Authorization Code icazə prosesi, 10 dəqiqədən bir yönləndirmələr vasitəsilə üç mərhələli bir yoxlama təqdim edir; bu, açığı, gözlər üçün çox da xoş olmayan bir fəaliyyətdir. Bu problemi həll etmək üçün Refresh Token adlı bir grant var ki, biz də onunla istifadə edirik. Burada işlər daha asandır. Digər grantla yoxlama aparılarkən, əsas giriş tokenindən savayı, tək dəfə istifadə edilə bilən bir Refresh Token də verilir və onun ömrü, adətən, xeyli uzundur. Bu Refresh Token ilə əsas giriş tokeninin TTL (Time to Live) müddəti bitdikdə, yeni giriş tokeni üçün tələb artıq fərqli bir grantın endpoint'inə yönləndirilir. İstifadə olunan Refresh Token dərhal etibarsız hala gətirilir. Bu cür yoxlama iki mərhələli olub fon rejimində, istifadəçi tərəfindən hiss olunmadan həyata keçirilə bilər.
3) İstifadəçi məlumatlarının çıxarılması formatlarını konfiqurasiya etdik
Seçilmiş grantlar həyata keçirildikdən sonra, avtorizasiya işləyir, son istifadəçi məlumatlarını əldə etməkdən də bəhs etmək lazımdır. OIDC-də bunun üçün ayrıca bir endpoint mövcuddur, burada cari giriş tokeni ilə və onun aktual olması halında istifadəçi məlumatlarını tələb edə bilərsiniz. Və əgər istifadəçi məlumatları bu qədər tez-tez dəyişmirsə, amma cari məlumatları bir çox dəfə əldə etmək lazımdırsa, JWT tokenlərindən istifadə etməyə qərar vermək olar. Bu tokenlər də standart tərəfindən dəstəklənir. JWT token özü üç hissədən ibarətdir: header (token haqqında məlumat), payload (istənilən məlumat) və signature (token server tərəfindən imzalanır və sonra onun imzasının mənbəyini yoxlamaq mümkündür).
OIDC implementasiyasında JWT tokeni id_token adlanır. O, adi giriş tokeni ilə birgə tələb oluna bilər, və geridə qalan yeganə iş imzanı yoxlamaqdır. Avtorizasiya serverinin bunun üçün ayrıca bir endpoint’i var, açıq açarların cütlüyü formatında . Bu kontekstdə, daha bir endpoint-in mövcud olduğu qeyd edilməlidir ki, OIDC serverinin cari konfiqurasiyasını standart əsasında əks etdirir . Bu endpoint-lərdə (həmçinin imza üçün istifadə olunan açarların cütlüyü ünvanı daxil olmaqla) bütün endpoint ünvanları, dəstəklənən kleymlər və sahələr, istifadə olunan şifrələmə algoritmları, dəstəklənən grantlar və s. mövcuddur.
Məsələn, 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"
]
}Beləliklə, id_token vasitəsilə payload-a lazım olan bütün kleymləri ötürmək və istifadəçi məlumatları üçün avtorizasiya serverinə hər dəfə sorğu göndərməyə ehtiyac qalmır. Bu yanaşmanın mənfi tərəfi isə odur ki, istifadəçi məlumatlarının serverdən dəyişməsi dərhal baş vermir, yeni giriş tokeni ilə birlikdə gəlir.
İcra nəticələri
Beləliklə, öz OIDC serverimizi qurduqdan və tətbiqlər tərəfində ona bağlantılar tənzimlədikdən sonra istifadəçi məlumatlarının ötürülməsi problemini həll etdik.
OIDC açıq standart olduğuna görə, mövcud provayderi seçmək və ya serveri reallaşdırmaq imkanı əldə etdik. Keycloak-u sınaqdan keçirdik, o, tənzimləmələr baxımından çox rahatdır. Tənzimləmə və tətbiqlər tərəfində bağlantı konfiqurasiyalarını dəyişdirdikdən sonra, işə başlamağa hazırdır. Tətbiqlər tərəfində yalnız bağlantı konfiqurasiyalarını dəyişmək qalır.
Mövcud həllər haqqında danışdıqda
Təşkilatımız çərçivəsində birinci OIDC serveri kimi öz reallaşdırmamızı yaratdıq, bu reallaşdırma lazım olduqca genişləndirildi. Digər hazır həlləri ətraflı araşdırdıqdan sonra, bu məsələdə mübahisəli fikirlər var. Öz serverimizin reallaşdırılması lehinə qərar verməyimiz, provayderlərin tələb olunan funksiyaların olmaması ilə bağlı narahatlıqları və bəzi xidmətlər üçün müxtəlif xüsusi avtorizasiyaları olan köhnə sistemin mövcudluğu, həmçinin işçilər haqqında xeyli məlumatın olmasıdır. Lakin hazır reallaşdırmalarda inteqrasiya üçün rahatlıqlar mövcuddur. Məsələn, Keycloak-da öz istifadəçi idarəetmə sistemi var və məlumatlar birbaşa orada saxlanılır, istifadəçiləri oraya köçürmək böyük çətinlik yaratmayacaq. Bunun üçün Keycloak-da tələb olunan bütün köçürmə əməliyyatlarını həyata keçirmək imkanı verən API vardır.
Bir daha cəlbedici, sertifikatlı bir tətbiq nümunəsi — Ory Hydra. O, fərqli komponentlərdən ibarət olması ilə maraqlıdır. İnteqrasiya üçün istifadəçi idarəetmə xidmətinizi onların avtorizasiya xidməti ilə əlaqələndirməli və lazım olduqda genişləndirməlisiniz.
Keycloak və Ory Hydra — yeganə hazır həllər deyil. Ən yaxşı seçim sertifikatlı OpenID Foundation tətbiqini seçməkdir. Bu cür həllərin adətən OpenID Certification nişanı olur.

Eğer OIDC serverinizi saxlamaq istəmirsinizsə, mövcud ödənişli provayderlər haqqında da unutmayın. Hazırda yaxşı variantlar çoxdur.
Növbəti nələrdir
Gələcəkdə daxili xidmətlərə trafikimizi başqa cür bağlamağı planlaşdırırıq. Hazırkı SSO-nu OpenResty ile balanslaşdırıcı vasitəsilə OAuth əsaslı proksiyaya köçürməyi düşünürük. Burada da artıq bir çox hazır həll mövcuddur, məsələn:
Əlavə materiallar
— JWT tokenlərini yoxlamaq üçün yaxşı bir xidmət
— OIDC ilə sertifikatlaşdırılmış tətbiqlərin siyahısı
Mənbə: habr.com
