OpenID Connect: ներքին հավելվածների հեղինակություն՝ ինքնագործվածներից ստանդարտներին

Միական ամիսներ առաջ ես իրականացրել եմ OpenID Connect սերվեր՝ մեր մի քանի ներսի հավելվածների մուտքի կառավարումը։ Ինքնագործված համակարգերից, որոնք հարմար էին փոքր չափերով, մենք անցանք ընդունված ստանդարտին։ Արտաքին ծառայության միջոցով մուտքը զգալիորեն հեշտացնում է monotonny գործողությունները, նվազեցնում հեղինակության իրականացման ծախսերը, թույլ է տալիս գտնել շատ պատրաստի լուծումներ և չմտածել նորերի մշակման ժամանակ։ Այս հոդվածում ես կպատմեմ այս անցման մասին և այն խնդիրների մասին, որոնք արդեն հասցրել ենք լուծել։

OpenID Connect: ներքին հավելվածների հեղինակություն՝ ինքնագործվածներից ստանդարտներին

Երևի շատ տարիներ առաջ… Ինչպե՞ս ամենը սկսվեց

Ամեն անգամ, երբ ներսի հավելվածների քանակը սկսեց մեծանալ, մենք գրեցինք մի հավելված, որը վերահսկում էր մուտքերի կառավարմանը։ Սա մի պարզ Rails հավելված էր, որը միանում էր աշխատակիցների տվյալների բազային, որտեղ սահմանվում էր մուտքը տարբեր գործառույթներին։ Այդ ժամանակ մենք անցկացրեցինք առաջին SSO, որը հիմնված էր հաճախորդի և հեղինակության սերվերի կողմից մուտքի վավերացման վրա, վավերացման տոմսը փոխանցվում էր ի՞նչ էլեկտրոնային ձևով՝ մի քանի պարամետրերով, և ստուգվում հեղինակության սերվերում։ Սա ամենահարմար տարբերակը չէր, քանի որ յուրաքանչյուր ներսի հավելվածում պետք էր նկարագրել ոչ քիչ տրամաբանություն, և աշխատակիցների բազաները ընդհանրապես չունեին համակարգման տեղեկացումներ հեղինակության սերվերի հետ։

Որոշ ժամանակ անց մենք որոշեցինք հեշտացնել կենտրոնացված հեղինակության խնդիրը։ SSO-ն տեղափոխեցինք բալանսավորիչի վրա։ OpenResty-ի Lua-ի միջոցով մենք ավելացրեցինք սքանչելիություն, որը ստուգում էր մուտքի վավերացման էկրանները, գիտեր, թե որն է հավելվածը, և կարող էր ստուգել, ի՞նչ մուտք կա այնտեղ։ Այս մոտեցումը զգալիորեն հեշտացրեց ներսի հավելվածների մուտքի վերահսկման խնդիրը՝ յուրաքանչյուր հավելվածի կոդում այլևս անհրաժեշտ չէր նկարագրել լրացուցիչ տրամաբանություն։ Վերջում մենք փակեցինք արտաքին միայնությունը, իսկ ինքը հավելվածը ոչինչ չգիտեր հեղինակության մասին։

Բայց մի խնդիր մնացել էր չլուծված։ Ինչպե՞ս լինել այն հավելվածների հետ, որոնք անհրաժեշտ Ավտորացված աշխատակիցների մասին տեղեկություններ։ Կարող էինք գրել API հեղինակման ծառայության համար, բայց այդ դեպքում պետք էր ավելացնել լրացուցիչ տրամաբանություն այդ յուրաքանչյուր հավելման համար։ Բացի այդ, մենք ուզում էինք ազատվել մեր ինքնագործված հավելվածից, որը հետագայում միտված է OpenSource-ին, մեր ներսի հեղինակության սերվերից։ Այդ մասին կխոսենք երբևէ։ Բացի այդ, թե՛ OAuth-ը եղավ ի պատասխան երկու խնդիրների։

Ներկայացված ստանդարտներին

OAuth — սա հասկանալի, ընդունված հեղինակավորման ստանդարտ է, սակայն քանի որ միայն նրա ֆունկցիաների բավարար չէ, սկսեցին դիտարկել OpenID Connect (OIDC): Ինքը OIDC-ն՝ բացավերած հեղինակավորման ստանդարտի երրորդ իրականացումն է, որը կառուցվել է OAuth 2.0 (բացավերած հեղինակավորման արձանագրություն) պրոտոկոլի վրա: Այսպիսի լուծումը փակվում է վերջնական օգտվողի մասին տեղեկատվության պակասը, ինչպես նաև թույլ է տալիս փոփոխել հեղինակավորման մատակարարին:

Անկախ նրանից, մենք չենք ընտրել հատուկ մատակարար և որոշեցինք մեր առկա հեղինակավորման սերվրին ավելացնել OIDC ինտեգրման: Այսպիսի լուծման օգտին է ծառայում այն, որ OIDC-ն շատ ճկուն է վերջնական օգտվողի հեղինակավորման առնչությամբ: Այսպիսով, առաջացավ հնարավորությունը OIDC պաշտպանել մեր առկա հեղինակավորման սերվրում:

OpenID Connect: ներքին հավելվածների հեղինակություն՝ ինքնագործվածներից ստանդարտներին

Մեր OIDC սերվերի իրականացման ուղի

1) Դատել տվյալները անհրաժեշտ տեսքի

OIDC-ի ինտեգրման համար անհրաժեշտ է ներկայիս օգտագործողների տվյալները բերել μορֆայիս, որը հասկանալի է ստանդարտին: OIDC-ում այսը կոչվում է Claims: Claims-ը ըստ էության՝ տվյալների շտեմարանում օգտագործողների վերջնական դաշտերն են (անուն, էլ. փոստ, հեռախոս և այլն): Կան стандարտային ցանկ claims, իսկ այն ամենը, ինչը չի մտնում այս ցանկում, համարվում է նեղացված: Ուստի առաջին պահը, որի վրա պետք է ուշադրություն դարձնել, եթե ցանկանում եք ընտրել առկա OIDC մատակարար – նոր claims-ի հարմարեցման հեշտությունը:

Claims խմբերը միավորվում են հետևյալ ենթախմբի մեջ՝ Scope: Հեղինակավորման ժամանակ մուտքային կոչվում է հասանելիություն ոչ կոնկրետ claims-ի, այլ հենց scopes-ի, նույնիսկ եթե scopes-ի մեջ որոշ claims-ներ անհրաժեշտ չեն:

2) Արձագանքեցին անհրաժեշտ grants-ները

OIDC ինտեգրման հաջորդ մասը ՝ հեղինակավորման տեսակների ընտրությունն ու իրականացումը, որոնք կոչվում են grants: Ընտրած grants-ի վրա կախված է հետագա սցենարը՝ ընտրված դիմումի հետ կապի համար հեղինակավորման սերվերի հետ: Հարցականի մոդելը ընտրած grants-ի անհրաժեշտ տեսակը ներկայացված է ստորև նկարի վրա:

OpenID Connect: ներքին հավելվածների հեղինակություն՝ ինքնագործվածներից ստանդարտներին

Մեր առաջին դիմումի համար մենք օգտագործեցինք ամենատարածված grants-ը՝ Authorization Code: Նրա առանձնահատկությունը մյուսներից այն է, որ այն երեք քայլով գործողություն է, այսինքն անցնում է լրացուցիչ ստուգում: Նախ, օգտագործողը գնահատում է հեղինակավորման թույլտվություն խնդրելու համար, ստանում է թոքեն՝ Authorization Code, ապա այս թոքենով, կարծես, ուղեբեռով, խնդրում է հասանելիության թոքեն: Այս հեղինակավորման սցենարի հիմնական շփումը հիմնված է վերածնունդների միջև, դիմումի և հեղինակավորման սերվերի միջև: Տվյալ grants-ի մասին ավելին կարող եք կարդալ այստեղ: այստեղ.

OAuth-ի սկզբունքը այն է, որ մուտքի տոքենները, որոնք ձեռք են բերվում հեղինակացումից հետո, պետք է լինեն ժամանակավոր և փոփոխվեն համապատասխանաբար միջինում յուրաքանչյուր 10 րոպեյում: Authorization Code-ի տրամադրումը երեք քայլով ստուգման մեթոդ է՝ ռեդիրեկտների միջոցով, ամբողջությամբ ամեն 10 րոպեյը կրկնելը, սիրահուշ, ամենևին հաճելի չէ աչքերի համար: Այս խնդիրը լուծելու համար կա մեկ այլ տրամադրում՝ Refresh Token, որը մենք նույնպես օգտագործում ենք: Այստեղ ամեն բան պարզ է: Մյուս տրամադրման ընթացքում, բացի հիմնական մուտքի տոքենից, տրվելու է նաև մեկ այլ՝ Refresh Token, որը կարող է օգտագործվել միայն մեկ անգամ և waarvan կյանքի ժամանակը, որպես կանոն, զգալիորեն երկար է: Այս Refresh Token-ով, երբ հիմնական մուտքի տոքենի TTL (Time to Live) ավարտվի, նոր մուտքի տոքենի հարցումը կկատարվի արդեն մյուս տրամադրման endpoint-ում: Օգտագործված Refresh Token-ը անմիջապես կջնջվի: Այս ստուգումը երկակի քայլանի է և կարող է իրականացվել ֆոնի վրա, օգտվողի համար աննկատ:

3) Կարգավորեցինք օգտվողի տվյալների ելքի ձևաչափերը

Այսպես, երբ ընտրված տրամադրումներն իրականացվել են և հեղինակացումը գործում է, արժե նշել վերջնական օգտվողի Աջակցության տվյալների ձեռքբերումը: OIDC-ում կա առանձին endpoint դրա համար, որի միջոցով ձեր ընթացիկ մուտքի տոքենով և դրա վավերությամբ կարելի է հարցնել օգտվողների տվյալները: Եթե օգտվողի տվյալները այդքան հաճախ չեն փոխվում, իսկ ընթացիկի համար հաճախակի հարցումներ են անհրաժեշտ, կարելի է անդրադառնալ այնպիսի լուծման, ինչպես JWT-տոքեններ: Այս տոքենները նույնպես աջակցվում են ստանդարտի կողմից: JWT-տոքենը ինքնին բաղկացած է երեք մասից. header (տոքենի մասին տեղեկություն), payload (փակագանձված տվյալներ) և signature (ձեռք Signature, տոքենը կնքում է սերվերը և դրանից հետո կարելի է ստուգել նրա ստորագրության աղբյուրը):

OIDC-ի իրականացումների մեջ JWT-տոքենը կոչվում է id_token: Այն կարող է հարցվել սովորական մուտքի տոքենի հետ և այն ամենը, რაც մնում է՝ ստուգել ստորագրությունը: Հեղինակավորման սերվերում սա իրականացնելու համար կա առանձին endpoint, որը կապված է հանրային բանալիի զույգի հետ JWK. Այս մասին խոսելիս, արժե նշել, որ կա ևս մեկ endpoint, որը հիմնված է ստանդարտի վրա RFC5785 արտահայտում է OIDC-սերվերի ներկայիս կոնֆիգուրացիան: Այն ունի բոլոր endpoint-ների հասցեները (միասին հանրային բանալու հասցեն, որն օգտագործվում է ստորագրման համար), աջակիցքի կլեյմները և սքոփերը, օգտագործվող encryption-ի ալգորիթմները, աջակցվող տրամադրումները և այլն:

Օրինակ՝ 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"
 ]
}

Այպես, id_token-ի միջոցով կարելի է փոխանցել բոլոր անհրաժեշտ կլեյմները տոկենի payload-ում և յուրաքանչյուր անգամ չհամալրել հեղինակացման սերվերին օգտագործողի մասին տվյալների հարցման համար: Հասարակ դէպքում, այս մոտեցման բացասական կողմն է այն, որ սերվերից օգտագործողի տվյալների փոփոխությունը գալիս է միանգամից, նոր մուտք գործելու տոկենով:

Կիրառման եզրակացությունները

Այդպիսով, սեփական OIDC սերվերի իրականացումից և դրա հետ ընդհանրացումներից հետո, մենք լուծեցինք օգտագործողների տեղեկատվության փոխանցման խնդիրը:
Որպեսզի OIDC-ն բաց ստանդարտ է, մեզ հնարավորություն ընձեռվեց ընտրել գոյություն ունեցող մատակարար կամ սեփական սերվեր իրականացնել: Մենք փորձեցինք Keycloak-ը, որը շատ հարմար էր կոնֆիգուրացնել, և դրա հետ կապված փոփոխությունների կարգավորողը պատրաստ էր աշխատելու: Հիմա приложениям մնում է միայն փոխել կապի կարգավորումներն:

Բարձրաձայնելով գոյություն ունեցող լուծումների մասին

Մեր կազմակերպության շրջանակներում, որպես առաջին OIDC-սերվեր, մենք հավաքեցինք իրագործված տարբերակը, որը կատարվել է ըստ անհրաժեշտության: Մյուս պատրաստի լուծումների մանրամասն ուսումնասիրությունից հետո, կարելի է ասել, որ սա վիճելի հարց է: Սեփական սերվերի իրականացման կողմնակի դրդմանը ի նպաստ էին մատակարարների մտավախությունները տիրապետման անհրաժեշտ գործառույթների բացակայության, ինչպես նաև հին համակարգի առկայությունը, որտեղ առկա էին տարբեր ադապտիվ հեղինակություններ որոշ ծառայությունների համար և արդեն բավականաչափ տվյալներ հավաքված էին աշխատողների մասին: Սակայն պատրաստի լուծումներում առկա conveniences-երը ընձեռված են ինտեգրման համար: Օրինակ, Keycloak-ում իր սեփական օգտվողների կառավարում համակարգը է, և տվյալները պահվում են այնտեղ, իսկ սեփական օգտվողներին այնտեղ տեղափոխելը չեն անի մեծ դժվարությունների: Այս նպատակով Keycloak-ում կա API, որը թույլ կտա ամբողջությամբ իրականացնել անհրաժեշտ գործողությունները տեղափոխման համար.

Մեկ այլ օրինակ սերտիֆիկացված, հետաքրքիր, իմ կարծիքով, իրագործման՝ Ory Hydra: Այն հետաքրքիր է նրանով, որ բաղկացած է տարբեր բաղադրիչներից: Այն նախատեսված է ինտեգրելու ձեր օգտվողների կառավարման ծառայությունը նրանց հեղինակացման ծառայությանը և անհրաժեշտության դեպքում ընդլայնելու:

Keycloak և Ory Hydra՝ կազմակերպված լուծումներ չեն: Լավագույնն է ընտրել սերտիֆիկացված OpenID Foundation լուծում: Այսպիսի լուծումները սովորաբար ունեն OpenID Certification լոգոն:

OpenID Connect: ներքին հավելվածների հեղինակություն՝ ինքնագործվածներից ստանդարտներին

Այնպես որ, մի մոռացեք այլ վճարովի մատակարարների մասին, եթե չեք ցանկանում պահել ձեր OIDC սերվերը: Այսօր շատ լավ տարբերակներ կան:

Ի՞նչ է հաջորդը

Անցյալում մենք նախատեսում ենք փակել երթևեկությունը ներքին ծառայություններին այլ լուծումներով: Կլորացնում ենք մեր ներկայիս SSO-ն բալանսավորիչի միջոցով OpenResty գործարկող օգնությամբ, որի հիմքը OAuth-ն է: Այստեղ նույնպես շատ մշակված լուծումներ կան, օրինակ՝
github.com/bitly/oauth2_proxy
github.com/ory/oathkeeper
github.com/keycloak/keycloak-gatekeeper

Լրացուցիչ նյութեր

jwt.io – լավ ծառայություն JWT-թոքենների ստուգման համար
openid.net/developers/certified — սերտիֆիկացված OIDC լուծումների ցուցակ

Ընտանիք: habr.com

Գնել հուսալի հյուրընկալում DDoS պաշտպանությամբ, VPS VDS սերվերներով 🔥 Գնել հուսալի հյուրընկալում DDoS պաշտպանությամբ, VPS VDS սերվերներով | ProHoster