OpenID Connect: sisemiste rakenduste autoriseerimine kohandatud lahendustest standardini

Mõni kuu tagasi töötasin OpenID Connect serveri rakendamise kallal, et hallata ligipääsu sadadele meie sisemistele rakendustele. Omandatud lahendustest, mis olid mugavad väiksematel ulatustel, liikusime üldiselt aktsepteeritud standardini. Ligipääs keskse teenuse kaudu lihtsustab oluliselt rutiinseid toiminguid, vähendab autoriseerimise rakendamise kulusid, võimaldab leida palju valmis lahendusi ning ei pane pead vaeva uute arendamisel. Selles artiklis räägin maagilisest üleminekust ja saamudest, mis me oleme saanud.

OpenID Connect: sisemiste rakenduste autoriseerimine kohandatud lahendustest standardini

Kaugel-kaugel... Kuidas kõik alguse sai

Mõned aastad tagasi, kui meie organisatsiooni sisemisi rakendusi oli liiga palju, et neid käsitsi hallata, arendasime pääsukontrolli rakenduse. See oli lihtne Rails-rakendus, mis liitus töötajate teavet sisaldava andmebaasiga, kus seadistati juurdepääs erinevatele funktsioonidele. Sel ajal rakendasime ka esimest SSO-d, mis põhines klientide ja autoriseerimiserveri vaheliste tokenite kontrollimisel; token edastati krüptitud kujul koos mitmete parameetritega ja kontrolliti autoriseerimiserveris. See polnud kõige mugavam lahendus, sest igas sisemises rakenduses tuli rakendada märkimisväärne loogikakiht ja töötajate andmebaasid ei sünkroniseerunud autoriseerimiserveriga.

Mõne aja pärast otsustasime keskse autentimise ülesande lihtsustada. SSO viidud koormuse tasakaalustajale. OpenResty abil Lua-s lisasime šablooni, mis kontrollis tokenid, teadis, millisesse rakendusse päring läheb ja sai kontrollida, kas seal on juurdepääs. Selline lähenemine lihtsustas siseringi rakenduste ligipääsu kontrollimise ülesannet — iga rakenduse koodis ei olnud enam vaja kirjeldada täiendavat loogikat. Lõppkokkuvõttes sulgesime välist liiklust, aga rakendus ei teadnud autentimisest midagi.

Kuid üks probleem jäi lahendamata. Kuidas neid rakendusi käsitleda, mis vajavad töötajate teavet? Võisime kirjutada autoriseerimisteenuse API, kuid sel juhul oleks tulnud lisada iga rakenduse jaoks täiendav loogika. Samuti soovisime loobuda sõltuvusest ühest meie ise kirjutatud rakendusest, mis suunatud edaspidi OpenSource'i, meie sisemisest autoriseerimisteenusest. Sellest räägime mõni teine kord. Mõlema probleemi lahenduseks oli OAuth.

Üldiselt aktsepteeritud standarditele

OAuth on arusaadav, üldiselt aktsepteeritud autentimisstandard, kuid kuna selle funktsionaalsus üksi ei piisa, hakati kohe vaatama ka OpenID Connecti (OIDC). OIDC on kolmas avatud autentimisstandard, mis on üles ehitatud OAuth 2.0 (avatud autoriseerimise protokoll) peale. Selline lahendus lahendab lõppkasutaja andmete puudumise probleemi ning pakub võimalust autoriseerimisprovajderi vahetamiseks.

Siiski ei olnud me otsustanud konkreetset provajderit ja otsustasime oma olemasolevale autoriseerimiserverile lisada OIDC integreerimise. Sellise lahenduse kasuks rääkis OIDC suur paindlikkus lõppkasutaja autoriseerimisel. Seega oli meil võimalus OIDC toetust oma praeguses autoriseerimiserveris rakendada.

OpenID Connect: sisemiste rakenduste autoriseerimine kohandatud lahendustest standardini

Meie tee oma OIDC-serveri teostamiseni

1) Toimesime andmed vajaliku vormingusse

OIDC integreerimiseks on vaja olemasolevad kasutajaandmed viia vormingusse, mis on standardiga arusaadav. OIDC-s nimetatakse seda Kleepsudeks. Kleepsud on põhimõtteliselt lõplikud väljad kasutajate andmebaasis (nimi, e-post, telefon jne). On olemas standardne kleepsude nimekiri, ja kõik, mis ei kuulu sellesse loendisse, loetakse kohandatuks. Seega on esimene asi, millele peate tähelepanu pöörama, kui soovite valida olemasoleva OIDC-prosidendi, uute claimide mugav kohandamine.

Claimide rühm koondub järgmisse alarühma – Scope. Autoriseerimise käigus küsitakse juurdepääsu mitte konkreetsetele claimidele, vaid just nimelt skoopidele, isegi kui osa skoopi claimidest ei ole vajalik.

2) Realiseeritud vajalikud grantid

Järgmiseks osaks OIDC integreerimisel on autoriseerimistüüpide valimine ja rakendamine, nn grantid. Valitud grant sõltub edasise suhtlemise stsenaarium valitud rakenduse ja autoriseerimiserveri vahel. Näidis skeem vajalikest grantidest on esitatud alloleval joonisel.

OpenID Connect: sisemiste rakenduste autoriseerimine kohandatud lahendustest standardini

Meie esimese rakenduse jaoks kasutasime kõige levinumat volitust – Authorization Code. Selle erinevus teistega on see, et see on kolmesammuline, s.t. see läbib täiendava kontrolli. Esiteks teeb kasutaja volituse saamiseks päringu, saab toekina – Authorization Code, seejärel küsib ta selle tokeniga, nagu piletiga sõitmiseks, juurdepääsu tokenit. Kõik peamine interaktsioon selle autoriseerimise stsenaariumi puhul põhineb suunamistel rakenduse ja autoriseerimisserveri vahel. Rohkem selle volituse kohta saab lugeda siit. siit.

OAuth järgib põhimõtet, et autoriseerimise teel saadud juurdepääsutokendid peaksid olema ajutised ja neid tuleks vahetada soovitatavalt keskmiselt iga 10 minuti järel. Autoriseerimiskoodi grant on kolmeastmeline protsess, mis toimub ümbersuunamiste kaudu, ning iga 10 minuti järel sellise sammu tegemine ei ole ausalt öeldes kõige meeldivam vaatepilt. Selle probleemi lahendamiseks on olemas veel üks grant – Refresh Token, mida me samuti kasutame. Siin on kõik lihtsam. Kontrollimise käigus teise grant'iga annab juurdepääsutokendi kõrval välja ka Refresh Token'i, mida saab kasutada ainult üks kord ja mille eluaeg on tavaliselt oluliselt pikem. Selle Refresh Token'iga, kui peamise juurdepääsutokendi TTL (Time to Live) aeg on lõppenud, saadetakse uus juurdepääsutokeni päring juba mõne teise grant'i lõpp-punkti. Kasutatud Refresh Token nullitakse kohe. Selline kontroll on kaheastmeline ja seda saab teha taustal, kasutajale märkamatult.

3) Konfigureerisime kasutajandmete väljundiformaadid

Kui valitud toetused on rakendatud ja autoriseerimine töötab, tasub mainida lõppkasutaja andmete saamist. OIDC-s on selleks eraldi lõpp-punkt, kus kehtiva juurdepääsu tokeniga saab kasutajaandmeid küsida. Kui kasutajaandmed ei muutu sageli, aga neid peab mitu korda küsima, võib leida lahenduse JWT-tokenite kasutamisel. Need tokenid on samuti standardi kohaselt toetatud. Iga JWT-token koosneb kolmest osast: header (tokeni teave), payload (vajalikud andmed) ja signature (allkiri, token allkirjastatakse serveris ja hiljem saab kontrollida allkiri allikat).

OIDC rakenduses nimetatakse JWT-tokenit id_tokeniks. Seda saab küsida koos tavalise juurdepääsu tokeniga ja kõik, mis jääb üle, on allkirja kontrollimine. Autoriseerimisteenusel on selleks eraldi lõpp-punkt koos avalike võtmete paariga, mis on formaadis JWK. Rääkides sellest, tasub mainida, et on olemas veel üks lõpp-punkt, mis põhineb standardil RFC5785 peegeldab praegust OIDC-serveri konfiguratsiooni. See sisaldab kõiki endpoint’ide aadresse (sealhulgas avalike võtmete sidumise aadressid, mida kasutatakse allkirjastamiseks), toetatud väiteid ja ulatusi, kasutatavaid krüpteerimisalgoritme, toetatud grant'e jne.

Näiteks Google'is:

{
 "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"
 ]
}

Sel viisil saab id_token'i abil edastada kõik vajalikud väited tokeni koormuses, ilma et peaks iga kord autentimisseerverilt kasutaja andmeid küsima. Selle lähenemise miinus on see, et kasutaja andmete muutmine serverist ei jõua koheselt, vaid koos uue juurdepääsutokeniga.

Tegevuste kokkuvõte

Nii et pärast oma OIDC-serveri elluviimist ja ühenduste seadistamist rakenduste poolel lahendasime kasutajate teabe edastamise probleemi.
Kuna OIDC on avatud standard, on meil võimalus valida olemasolev teenusepakkuja või rakendada oma server. Proovisime Keycloak'i, mis osutus väga mugavaks seadistamisel; pärast seadistamist ja rakenduste poolel ühenduste konfigureerimise muutmist on see tööks valmis. Rakenduste poolel jääb alles vaid seadistuste muutmine.

Rääkides olemasolevatest lahendustest

Meie organisatsiooni raames oleme esimese OIDC-serverina kokku pannud oma rakenduse, mida on vajadusel täiustatud. Pärast teiste valmis lahenduste põhjalikku läbivaatamist võib öelda, et see on vaieldav teema. Oma serveri rakenduse kasuks rääkisid mured teenusepakkujate poolt vajaliku funktsionaalsuse puudumise üle, samuti vana süsteemi olemasolu, mis sisaldas erinevaid kohandatud autoriseerimisi teatud teenuste jaoks ja kus oli juba üsna palju töötajate andmeid. Siiski, valmis lahendustes on mugavusi integratsiooniks. Näiteks Keycloak's on oma kasutajate haldamise süsteem ning andmed säilitatakse otse seal, mistõttu oma kasutajate üleviimine sinna ei tekita suuri raskusi. Selleks on Keycloak's API, mis võimaldab teostada kõik vajalikud toimingud andmete üleviimiseks.

Veel ühe sertifitseeritud, huvitava lahenduse näide on Ory Hydra. See on huvitav, kuna see koosneb erinevatest komponentidest. Integreerimiseks peate siduma oma kasutajate haldusteenuse nende autoriseerimisteenusega ning vajadusel laiendama.

Keycloak ja Ory Hydra ei ole ainsad valmislahendused. Parim on valida sertifitseeritud OpenID Foundation'i lahendus. Tüüpiliselt on sellistel lahendustel OpenID sertifitseerimise ikoon.

OpenID Connect: sisemiste rakenduste autoriseerimine kohandatud lahendustest standardini

Samuti ärge unustage olemasolevaid tasulisi teenuseid, kui te ei soovi oma OIDC-serverit hallata. Täna on palju häid valikuid.

Mis edasi

Lähiajal plaanime suunata liiklust siseteenustele teistmoodi. Kavatseme viia oma praeguse SSO tasakaalustajale OpenResty abil proxy'le, mille aluseks on OAuth. Ka siin on olemas palju valmislahendusi, näiteks:
github.com/bitly/oauth2_proxy
github.com/ory/oathkeeper
github.com/keycloak/keycloak-gatekeeper

Lisamaterjalid

jwt.io – hea teenus JWT-tokenite kontrollimiseks
openid.net/developers/certified — sertifitseeritud OIDC lahenduste nimekiri

Allikas: habr.com

Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster