Disa disa muaj më parë, unë isha duke implementuar një server OpenID Connect për menaxhimin e aksesit të qindra aplikacioneve tona të brendshme. Nga zhvillimet tona personale, të përshtatshme për shkallë të vogla, kaluam në një standard të pranuar. Aksesimi përmes një shërbimi qendror thjeshton ndjeshëm operacionet monotoze, ul kostot për implementimin e autorizimeve, lejon gjetjen e shumë zgjidhjeve të gatshme dhe ndihmon në zhvillimin e aplikacioneve të reja pa shqetësime. Në këtë artikull do të flas për këtë kalim dhe për pengesat që kemi hasur.

Dikur⊠Si filloi gjithçka
Disa vjet më parë, kur numri i aplikacioneve të brendshme u bë i padurueshëm për menaxhimin manual, ne shkruam një aplikacion për kontrollin e aksesit brenda kompanisë. Ishte një aplikacion i thjeshtë në Rails, i cili lidhej me një bazë të dhënash me informacionin për punonjësit, ku konfiguroheshin akseset për funksionalitete të ndryshme. Në atë kohë ne krijuam SSO-në e parë, e cila bazohej në verifikimin e tokeneve nga klienti dhe serveri i autorizimit, tokeni dërgohej në një format të enkriptuar me disa parametra dhe kontrollohej në serverin e autorizimit. Kjo nuk ishte zgjidhja më e përshtatshme, pasi çdo aplikacion i brendshëm kërkonte një shtresë të madhe logjike, dhe bazat e të dhënave të punonjësve nuk ishin as farë të sinkronizuar me serverin e autorizimit.
Pasi kaluam njĂ«farĂ« kohe, ne vendosĂ«m ta thjeshtojmĂ« detyrĂ«n e autorizimit qendror. SSO-nĂ« e kaluam nĂ« balancues. Me ndihmĂ«n e OpenResty nĂ« Lua, shtuam njĂ« model qĂ« kontrollonte tokene, dinte se nĂ« cilin aplikacion po bĂ«nte kĂ«rkesĂ«n dhe mund tĂ« verifikonte nĂ«se kishte akses. Ky qasje e thjeshtoi ndjeshĂ«m detyrĂ«n e kontrollit tĂ« akseseve pĂ«r aplikacionet e brendshme â nĂ« kodin e çdo aplikacioni nuk ishte mĂ« e nevojshme pĂ«rcaktimi i logjikĂ«s shtesĂ«. NĂ« fund, ne mbyllĂ«m trafikimin jashtĂ«, dhe vetĂ« aplikacioni nuk dinte asgjĂ« rreth autorizimit.
Megjithatë, një nga problemet mbeti e pazgjidhur. Si të veprojmë me aplikacionet që kanë nevojë për informacion mbi punonjësit? Mund të ishim shkruar një API për shërbimin e autorizimit, por do të duhej që të shtonim logjikë shtesë për çdo aplikacion të tillë. Përveç kësaj, ne dëshironim të shpëtonim nga varësia nga një aplikacion tonin të niveli të lartë, i orientuar në vazhdim për t'u transferuar në OpenSource, nga serveri ynë i brendshëm të autorizimit. Për këtë ne do të flasim ndonjëherë në një tjetër rast. Zgjidhja për të dy problemet ishte OAuth.
NĂ« standartet e pranuara
OAuth është një standard i qartë dhe i pranuar i autorizimit, por pasi funksionaliteti i tij nuk ishte i mjaftueshëm, filluan të shqyrtojnë gjithashtu OpenID Connect (OIDC). OIDC për vete është realizimi i tretë i një standardi të hapur të autentifikimit, që u bë një shtesë mbi protokollin OAuth 2.0 (protokoll i hapur i autorizimit). Ky zgjidhje zbulon problemin e mungesës së të dhënave për përdoruesin përfundimtar, si dhe ofron mundësinë e ndryshimit të ofruesit të autorizimit.
Megjithatë ne nuk vendosëm të zgjedhim një ofrues të veçantë dhe vendosëm që për serverin tonë ekzistues të autorizimit të shtonim integrimin me OIDC. Një arsye për këtë zgjidhje ishte se OIDC është shumë fleksibël në lidhje me autorizimin e përdoruesit përfundimtar. Kështu, u krijua mundësia për të himbret mbështetje OIDC në serverin tonë aktual të autorizimit.

Rruga jonë për implementimin e serverit OIDC
1) Organizimi i të dhënave në formën e duhur
Për integrimin OIDC, është e nevojshme të sjellim të dhënat aktuale të përdoruesve në një formë që standardi ta kuptojë. Në OIDC, kjo quhet Claims. Claims, në thelb, janë fushat përfundimtare në bazën e të dhënave për përdoruesit (emri, emaili, telefoni, etj.). Ekziston , dhe çdo gjë që nuk përfshihet në këtë listë konsiderohet si e personalizuar. Prandaj, momenti i parë që duhet të kihet parasysh nëse doni të zgjidhni një ofrues ekzistues OIDC është mundësia e lehtë për të personalizuar claims të reja.
Grupi i claims bashkohet nĂ« njĂ« nĂ«npjesĂ« tĂ« tillĂ« â Scope. GjatĂ« autorizimit, bĂ«het kĂ«rkesĂ« pĂ«r akses jo nĂ« claims tĂ« caktuara, por pikĂ«risht nĂ« scopes, edhe nĂ«se njĂ« pjesĂ« e claims nga scope nuk Ă«shtĂ« e nevojshme.
2) Realizuam grants të nevojshme
Pjesa tjetër e integrimit OIDC është zgjedhja dhe implementimi i llojeve të autorizimit, të ashtuquajturave grants. Scenari më pas i ndërveprimit të aplikacionit të zgjedhur me serverin e autorizimit do të varet nga grant-i i zgjedhur. Një skemë e përafërt e zgjedhjes së grantit të nevojshëm është paraqitur në figurën më poshtë.

PĂ«r aplikacionin tonĂ« tĂ« parĂ«, ne pĂ«rdorĂ«m grantin mĂ« tĂ« zakonshĂ«m - Authorization Code. Dallimi i tij nga tĂ« tjerĂ«t Ă«shtĂ« se ai kalon nĂ«pĂ«r njĂ« verifikim me tre hapa, domethĂ«nĂ« kalon njĂ« kontroll shtesĂ«. Fillimisht, pĂ«rdoruesi bĂ«n njĂ« kĂ«rkesĂ« pĂ«r lejen e autorizimit, merr njĂ« token â Authorization Code, pastaj me kĂ«tĂ« token, ashtu si me njĂ« biletĂ« udhĂ«timi, kĂ«rkon njĂ« token akses. TĂ« gjitha ndĂ«rveprimet kryesore tĂ« kĂ«tij skenari autorizimi janĂ« tĂ« bazuara nĂ« redireketime midis aplikacionit dhe serverit tĂ« autorizimit. PĂ«r mĂ« shumĂ« detaje mbi kĂ«tĂ« grant mund tĂ« lexoni. .
OAuth ndjek konceptin se tokenĂ«t e aksesit, tĂ« fituar pas autorizimit, duhet tĂ« jenĂ« tĂ« pĂ«rkohshĂ«m dhe tĂ« ndryshohen preferohet çdo 10 minuta. Grant Authorization Code Ă«shtĂ« njĂ« verifikim me tre hapa pĂ«rmes redireketimeve, dhe tĂ« pĂ«rfundohet ky proces çdo 10 minuta, pa dashtĂ« thĂ«nĂ«, nuk Ă«shtĂ« mĂ« e kĂ«ndshme pĂ«r sytĂ«. PĂ«r tĂ« zgjidhur kĂ«tĂ« problem, ekziston njĂ« grant tjetĂ«r â Refresh Token, qĂ« ne gjithashtu e pĂ«rdorim. KĂ«tu Ă«shtĂ« mĂ« e thjeshtĂ«. GjatĂ« verifikimit me grantin tjetĂ«r, pĂ«rveç tokenit kryesor tĂ« aksesit, jepet njĂ« tjetĂ«r â Refresh Token, qĂ« mund tĂ« pĂ«rdoret vetĂ«m njĂ« herĂ« dhe koha e saj e jetĂ«s, zakonisht, Ă«shtĂ« dukshĂ«m mĂ« e gjatĂ«. Me kĂ«tĂ« Refresh Token, kur tĂ« pĂ«rfundojĂ« TTL (Koha e JetĂ«s) e tokenit kryesor tĂ« aksesit, kĂ«rkesa pĂ«r njĂ« token tĂ« ri akses do tĂ« vijĂ« nĂ« endpoint-in e grantit tjetĂ«r. Refresh Token e pĂ«rdorur menjĂ«herĂ« anulohet. Ky kontroll Ă«shtĂ« njĂ« verifikim me dy hapa dhe mund tĂ« kryhet nĂ« sfond, pa u vĂ«nĂ« re nga pĂ«rdoruesi.
3) Konfiguruam formatet e daljes për të dhënat e përdoruesve
Pasi që grantet e zgjedhura janë implementuar, autorizimi funksionon, është e rëndësishme të përmendet marrja e të dhënave të përdoruesit të fundit. Në OIDC ka një endpoint të veçantë për këtë, ku me tokenin tuaj aktual të aksesit dhe me validitetin e tij, mund të kërkoni të dhënat e përdoruesve. Dhe nëse të dhënat e përdoruesit nuk ndryshojnë kaq shpesh, por ne kemi nevojë për ato aktuale shpesh, mund të arrijmë në një zgjidhje siç është tokenet JWT. Këto token janë gjithashtu të mbështetur nga standarti. Vetë tokeni JWT përbëhet nga tre pjesë: header (informacion për tokenin), payload (çfarëdo të dhënash të nevojshme) dhe signature (nënshkrimi, tokeni nënshkruhet nga serveri dhe më vonë mund të verifikohet burimi i nënshkrimit të tij).
Në implementimin e OIDC, tokeni JWT quhet id_token. Ai mund të kërkohet së bashku me tokenin e zakonshëm të aksesit dhe gjithçka që mbetet është të kontrolloni nënshkrimin. Për këtë, serveri i autorizimit ka një endpoint të veçantë me një lidhje të çelësave publikë në formatin . Dhe duke folur për këtë, duhet të përmendet se ekziston një tjetër endpoint, i cili mbi bazën e standardit reflekton konfigurimin aktual të serverit OIDC. Në të përfshihen të gjitha adresat e endpoint-eve (përfshire adresën e lidhjes së çelësave publikë të përdorur për nënshkrim), claim-et e mbështetur dhe scope-et, algoritmet e kodimit të mbështetur, grantet e mbështetur, etj.
Për shembull në 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"
]
}Kështu, me ndihmën e id_token-it mund të transmetohen të gjithë claim-et e nevojshme në payload të tokenit dhe nuk është e nevojshme të kthehemi çdo herë në serverin e autorizimit për të kërkuar të dhënat për përdoruesin. Disavantazhi i këtij qasje është se ndryshimi i të dhënave të përdoruesit nga serveri nuk vjen menjëherë, por së bashku me një token të ri akses.
Përmbledhje e implementimit
Kështu, pas implementimit të serverit tonë të OIDC dhe konfigurimit të lidhjeve me të në anën e aplikacioneve, ne zgjidhëm problemin e transmetimit të informacionit për përdoruesit.
Duke qenë se OIDC është një standard i hapur, ne fituam mundësinë për të zgjedhur një ofrues ekzistues ose për të implementuar një server. Ne provuam Keycloak, i cili u tregua shumë i përshtatshëm për konfigurimin, pas konfigurimit dhe ndryshimit të konfigurimeve të lidhjes në anën e aplikacioneve ai është gati për t'u përdorur. Në anën e aplikacioneve mbetet vetëm të ndryshojmë konfigurimet e lidhjes.
Duke folur për zgjidhjet ekzistuese
Brenda organizatës sonë, si serveri ynë i parë OIDC, ne kemi krijuar implementimin tonë që u plotësua sipas nevojës. Pas një shqyrtimi të detajuar të zgjidhjeve të tjera të gatshme, mund të themi se kjo është një çështje e diskutueshme. Në favor të zgjidhjes së një serveri të realizuar nga ne, ndikuan frikat nga ofruesit për mungesën e funksionaliteteve të nevojshme, si dhe ekzistenca e një sistemi të vjetër në të cilin kishte autorizime të ndryshme për disa shërbime dhe tashmë ruheshin shumë të dhëna mbi punonjësit. Megjithatë, implementimet e gatshme ofrojnë lehtësi për integrim. Për shembull, në Keycloak ekziston sistemi i menaxhimit të përdoruesve dhe të dhënat ruhen direkt aty, ndërsa kalimi i përdoruesve tanë atje nuk do të jetë një problem i madh. Për këtë, Keycloak ofron një API, i cili do të lejojë për të realizuar plotësisht të gjitha veprimet e nevojshme për transferim.
NjĂ« shembull tjetĂ«r i njĂ« implementimi tĂ« certifikuar, qĂ« mendoj se Ă«shtĂ« interesant â Ory Hydra. Ajo Ă«shtĂ« interesante sepse pĂ«rbĂ«het nga komponente tĂ« ndryshme. PĂ«r integrim do t'ju nevojitet tĂ« lidhni shĂ«rbimin tuaj tĂ« menaxhimit tĂ« pĂ«rdoruesve me shĂ«rbimin e tyre tĂ« autorizimit dhe ta zgjidhni sipas nevojĂ«s.
Keycloak dhe Ory Hydra nuk janë zgjidhjet e vetme të gatshme. Më së miri është të zgjidhni një implementim të certifikuar nga OpenID Foundation. Zakonisht, këto zgjidhje kanë një shenjë të Certifikimit OpenID.

Mos harroni gjithashtu për ofruesit e pagesave ekzistues, nëse nuk dëshironi të mbani serverin tuaj OIDC. Aktualisht ka shumë mundësi të mira.
ĂfarĂ« ndodh mĂ« pas
Në të ardhmen e afërt, ne planifikojmë të mbyllim trafikun në shërbimet tona të brendshme në një mënyrë tjetër. Po planifikojmë të transferojmë SSO-në tonë aktuale në balancuesin me ndihmën e OpenResty në një proxy, mbi të cilin bazohet OAuth. Këtu gjithashtu ekzistojnë shumë zgjidhje të gatshme, për shembull:
Materiale Shtesë
â njĂ« shĂ«rbim i mirĂ« pĂ«r verifikimin e JWT-tokens
â lista e implementimeve tĂ« certifikuara OIDC
Burimi: habr.com
