OpenID Connect: autorizácia interných aplikácií od vlastných riešení k štandardu

Pred niekoľkými mesiacmi som sa zaoberal implementáciou servera OpenID Connect na správu prístupu k stovkám našich interných aplikácií. Od vlastných riešení, ktoré boli vhodné pri menších mierkach, sme prešli na široko prijatý štandard. Prístup cez centrálnu službu značne zjednodušuje monotónne operácie, znižuje náklady na implementáciu autorizácií, umožňuje nájsť množstvo hotových riešení a odbremení nás od problémov pri vývoji nových. V tomto článku sa podelím o tento prechod a o skúsenostiach, ktoré sme počas neho nadobudli.

OpenID Connect: autorizácia interných aplikácií od vlastných riešení k štandardu

Kedysi dávno… Ako to všetko začalo

Pred niekoľkými rokmi, keď sa interných aplikácií stalo príliš veľa na ručné riadenie, sme napísali aplikáciu na kontrolu prístupov v rámci spoločnosti. Bola to jednoduchá aplikácia na Rails, ktorá sa pripájala k databáze s informáciami o zamestnancoch, kde sa nastavoval prístup k rôznemu funkčnému vybaveniu. Vtedy sme tiež spustili prvé SSO, ktoré sa zakladalo na kontrole tokenov zo strany klienta a servera autorizácie, pričom token bol prenášaný v zašifrovanej forme s niekoľkými parametrami a overoval sa na serveri autorizácie. Nebol to najpohodlnejší variant, pretože na každej internnej aplikácii bolo potrebné popísať nemalé množstvo logiky, a databázy zamestnancov sa dokonca synchronizovali so serverom autorizácie.

Po určitom čase sme sa rozhodli zjednodušiť úlohu centralizovanej autorizácie. SSO sme preniesli na vyrovnávacie zariadenie. S pomocou OpenResty na Lua sme pridali šablónu, ktorá kontrolovala tokeny, vedela, do ktorého aplikácie bola žiadosť smerovaná, a mohla overiť, či je na ňu prístup. Takýto prístup výrazne zjednodušil kontrolu prístupov k interným aplikáciám — v kóde každej aplikácie už nebolo potrebné popisovať dodatočnú logiku. Na konci sme uzavreli vonkajší prenos a samotná aplikácia nič nevedela o autorizácii.

Jedným z problémov však zostalo nevyriešené. Ako byť s aplikáciami, ktoré potrebujú informácie o zamestnancoch? Mohli sme napísať API pre autorizačnú službu, ale potom by bolo potrebné pridať ďalšiu logiku pre každú takúto aplikáciu. Navyše sme sa chceli zbaviť závislosti na našej vlastnej aplikácii, ktorá je v budúcnosti zameraná na prechod do OpenSource, a na našom internom autorizačnom serveri. O ňom povieme niekedy inokedy. Riešením oboch problémov sa stal OAuth.

K bežným štandardom

OAuth je jasný, všeobecne uznávaný štandard autorizácie, ale pretože jeho funkcionalita sama o sebe nestačí, začali sme uvažovať aj o OpenID Connect (OIDC). OIDC je tretia implementácia otvoreného autentifikačného štandardu, ktorý sa stal nadstavbou nad protokolom OAuth 2.0 (otvorený autorizačný protokol). Toto riešenie uzatvára problém nedostatku údajov o konečnom používateľovi, ako aj umožňuje zmenu poskytovateľa autorizácie.

Nakoniec sme sa nerozhodli pre konkrétneho poskytovateľa a rozhodli sme sa pridať integráciu s OIDC do nášho existujúceho autorizačného servera. Ako argument pre toto rozhodnutie poslúžila flexibilita OIDC v oblasti autorizácie konečného používateľa. Takto sme mali možnosť implementovať podporu OIDC na svojom aktuálnom autorizačnom serveri.

OpenID Connect: autorizácia interných aplikácií od vlastných riešení k štandardu

Naša cesta k implementácii vlastného OIDC servera

1) Pripravili sme dáta do požadovanej podoby

Na integráciu OIDC je potrebné previesť aktuálne údaje o používateľoch do formátu, ktorý je štandardu zrozumiteľný. V OIDC sa to nazýva Claims. Kliešťami sú v podstate konečné polia v databáze používateľov (meno, email, telefón atď.). Existuje štandardný zoznam kľúčov, a všetko, čo nie je v tomto zozname, sa považuje za prispôsobené. Preto prvý aspekt, na ktorý treba dbať, ak sa rozhodnete vybrať existujúceho poskytovateľa OIDC – možnosť pohodlného prispôsobenia nových kľúčov.

Skupina kľúčov sa zjednocuje do nasledujúceho podmnožstva – Scope. Pri autorizácii sa žiada prístup nielen k konkrétnym kľúčom, ale práve k rozsahu, aj keď niektoré kľúče zo scopu nie sú potrebné.

2) Implementovali sme potrebné granty

Ďalšou súčasťou integrácie OIDC je výber a realizácia typov autorizácie, takzvaných grantov. Od zvoleného grantu bude závisieť ďalší scenár interakcie zvoleného aplikácie s autorizačným serverom. Príkladná schéma výberu potrebného grantu je zobrazená na obrázku nižšie.

OpenID Connect: autorizácia interných aplikácií od vlastných riešení k štandardu

Pre našu prvú aplikáciu sme použili najrozšírenejší grant – Authorization Code. Jeho odlišnosť od ostatných je v tom, že je trojstupňový, t.j. prechádza ďalšou kontrolou. Najprv používateľ žiada o povolenie autorizácie, získa token – Authorization Code, potom s týmto tokenom, akoby s lístkom na cestu, žiada o prístupový token. Všetka hlavná interakcia tohto scenára autorizácie je založená na presmerovaniach medzi aplikáciou a autorizačným serverom. O tomto grante sa môžete dozvedieť viac. tu.

OAuth sa drží konceptu, že prístupové tokeny, získané po autorizácii, by mali byť dočasné a mali by sa meniť ideálne každých 10 minút. Grant Authorization Code je trojstupňová kontrola prostredníctvom presmerovaní, každý 10 minút tento krok vykonávať, úprimne povedané, nie je práve najpríjemnejšia činnosť pre oči. Na riešenie tohto problému existuje ešte jeden grant – Refresh Token, ktorý sme u seba tiež použili. Tu je všetko jednoduchšie. Počas kontroly z iného grantu, okrem hlavného prístupového tokenu, sa vydáva ešte jeden – Refresh Token, ktorý sa môže použiť iba raz a jeho doba života je zvyčajne podstatne dlhšia. S týmto Refresh Tokenom, keď vyprší TTL (Time to Live) hlavného prístupového tokenu, žiadosť o nový prístupový token príde na endpoint už z iného grantu. Použitý Refresh Token sa okamžite nulizuje. Táto kontrola je dvojstupňová a môže sa vykonať na pozadí, neviditeľne pre používateľa.

3) Nastavili formáty výstupu používateľských dát

Po realizácii vybraných grantov a fungujúcej autorizácii je potrebné spomenúť získavanie údajov o koncovom užívateľovi. V OIDC existuje samostatný endpoint, kde je možné so súčasným prístupovým tokenom a v prípade jeho platnosti požadovať údaje o užívateľoch. A ak sa údaje o užívateľoch nemenia tak často a je potrebné po ne chodiť viackrát, je možné prísť k takému riešeniu, akým sú JWT tokeny. Tieto tokeny sú tiež podporované štandardom. JWT token sám o sebe pozostáva z troch častí: header (informácie o tokene), payload (akékoľvek potrebné údaje) a signature (podpis, token je podpísaný serverom a neskôr sa môže overiť zdroj jeho podpisu).

V implementácii OIDC sa JWT token nazýva id_token. Môže byť požadovaný spolu s bežným prístupovým tokenom a všetko, čo zostáva, je overiť podpis. Pre tento účel existuje na serveri autorizácie samostatný endpoint so sadou verejných kľúčov vo formáte JWK. A hovoriac o tom, je potrebné spomenúť, že existuje ešte jeden endpoint, ktorý na základe štandardu RFC5785 odráža súčasnú konfiguráciu OIDC servera. Obsahuje všetky adresy endpointov (vrátane adresy sadzby verejných kľúčov používaných na podpis), podporované nároky a rozsahy, používané metódy šifrovania, podporované granty a podobne.

Například v 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"
 ]
}

Takže pomocou id_tokenu je možné prenášať všetky potrebné nároky v payloade tokenu a neobrácať sa zakaždým na server autorizácie na požiadanie údajov o používateľovi. Nevýhodou tohto prístupu je, že zmeny používateľských údajov zo servera prichádzajú postupne, spolu s novým prístupovým tokenom.

Zhrnutie implementácie

Po implementácii vlastného OIDC servera a nastavení pripojení k nemu na strane aplikácií sme vyriešili problém s prenášaním informácií o používateľoch.
Keďže OIDC je otvorený štandard, získali sme možnosť vybrať si existujúceho poskytovateľa alebo implementovať server. Skúsili sme Keycloak, ktorý sa ukázal ako veľmi praktický na konfiguráciu, a po úprave a zmene pripojovacích konfigurácií na strane aplikácií bol pripravený na prácu. Na strane aplikácií zostáva iba zmeniť pripojovacie konfigurácie.

Pokiaľ ide o existujúce riešenia

V rámci našej organizácie sme ako prvý OIDC server vytvorili vlastnú implementáciu, ktorá sa dopĺňala podľa potreby. Po podrobnom preskúmaní iných hotových riešení môžeme povedať, že ide o kontroverzné rozhodnutie. Na podporu implementácie vlastného servera hrali úlohu obavy od poskytovateľov z nedostatku potrebnej funkčnosti, ako aj existencia starej systému, v ktorom boli rôzne prispôsobené autorizácie pre niektoré služby a uchovávalo sa už pomerne veľa údajov o zamestnancoch. Avšak v hotových implementáciách existujú výhody pre integráciu. Napríklad v Keycloak je vlastný systém správy používateľov a údaje sú uložené priamo tam, a prevod svojich používateľov tam nie je veľkým problémom. Na to je v Keycloak k dispozícii API, ktoré umožní vykonať všetky potrebné akcie na presun.

Ďalším príkladom certifikovanej, zaujímavej implementácie, podľa môjho názoru, je Ory Hydra. Zaujímavá je tým, že pozostáva z rôznych komponentov. Pre integráciu budete musieť prepojiť svoj systém správy používateľov s ich autorizačnou službou a rozširovať podľa potreby.

Keycloak a Ory Hydra nie sú jediné hotové riešenia. Najlepšie je vyberať certifikovanú implementáciu OpenID Foundation. Zvyčajne takéto riešenia majú logo certifikácie OpenID.

OpenID Connect: autorizácia interných aplikácií od vlastných riešení k štandardu

Nezabudnite ani na existujúcich platených poskytovateľov, ak si nechcete držať svoj server OIDC. Dnes je k dispozícii množstvo dobrých možností.

Čo ďalej

V blízkej budúcnosti plánujeme obmedziť prístup k vnútorným službám iným spôsobom. Chystáme sa presunúť naše súčasné SSO na balancer s OpenResty pomocou proxy, založenej na OAuth. Existuje už aj mnoho hotových riešení, napríklad:
github.com/bitly/oauth2_proxy
github.com/ory/oathkeeper
github.com/keycloak/keycloak-gatekeeper

Ďalšie materiály

jwt.io – dobrý servis na overenie JWT tokenov
openid.net/developers/certified — zoznam certifikovaných implementácií OIDC

Zdroj: habr.com

Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster