Tavaszi biztonság és OpenID Connect

Vegye figyelembe, hogy ez a cikk frissült az új Spring Security OAuth 2.0 veremre. A régi verem használatával készült oktatóanyag azonban továbbra is elérhető.

1. Áttekintés

Ebben a gyors bemutatóban az OpenID Connect (OIDC) beállítására összpontosítunk a Spring Security segítségével.

Bemutatjuk a specifikáció különböző aspektusait, majd meglátjuk a Spring Security által kínált támogatást annak megvalósításához egy OAuth 2.0 kliensen.

2. Gyors OpenID Connect bevezetés

Az OpenID Connect az OAuth 2.0 protokoll tetejére épített identitásréteg.

Ezért nagyon fontos ismerni az OAuth 2.0-t, mielőtt belevágna az OIDC-be, különös tekintettel az Engedélyezési kód folyamatra.

Az OIDC specifikációs csomagja kiterjedt; magában foglalja az alapfunkciókat és számos más opcionális képességet, különböző csoportokban bemutatva. A legfontosabbak:

  • Core: hitelesítés és az igények felhasználása a végfelhasználói információk közlésére
  • Felfedezés: meghatározza, hogy az ügyfél hogyan tudja dinamikusan meghatározni az OpenID-szolgáltatókkal kapcsolatos információkat
  • Dinamikus regisztráció: meghatározza, hogy az ügyfél hogyan regisztrálhat a szolgáltatónál
  • Session Management: meghatározza az OIDC munkamenetek kezelésének módját

Ráadásul a dokumentumok megkülönböztetik az OAuth 2.0 hitelesítési szervereket, amelyek támogatást nyújtanak ehhez a specifikációhoz, „OpenID szolgáltatókként” (OP) és az OAC 2.0 ügyfelekként hivatkozva, akik megbízó felekként (RP) használják. Ebben a cikkben ragaszkodunk ehhez a terminológiához.

Érdemes tudni azt is, hogy az ügyfél a kiterjesztés hozzáadásával kérheti ennek a kiterjesztésnek a használatát nyitott engedélyezési kérelmében.

Végül egy másik szempont, amelyet hasznos megérteni ebben az oktatóanyagban, az a tény, hogy az operációs rendszerek „végfelhasználói információkat” JWT-ként bocsátanak ki, „ID tokennek” hívva.

Most igen, készen állunk mélyebbre merülni az OIDC világában.

3. Projekt beállítása

Mielőtt a tényleges fejlesztésre összpontosítanánk, regisztrálnunk kell egy OAuth 2.o klienst az OpenID szolgáltatónknál.

Ebben az esetben a Google-t fogjuk használni OpenID szolgáltatóként. Ezeket az utasításokat követve regisztrálhatjuk kliens alkalmazásunkat a platformjukon. Figyeljük meg, hogy a nyitott hatókör alapértelmezés szerint jelen van.

Az ebben a folyamatban beállított Átirányítási URI egy végpont a szolgáltatásunkban: // localhost: 8081 / login / oauth2 / code / google.

Ehhez a folyamathoz meg kell szereznünk egy ügyfél-azonosítót és egy ügyfél-titkot.

3.1. Maven konfiguráció

Először ezeket a függőségeket adjuk hozzá a projekt pom fájlunkhoz:

 org.springframework.boot spring-boot-starter-oauth2-client 2.2.6. KÖZLEMÉNY 

Az indítótermék összesíti a Spring Security Client összes függőségét, beleértve:

  • a spring-security-oauth2-client az OAuth 2.0 bejelentkezés és kliens funkcionalitás függősége
  • a JOSE könyvtár a JWT támogatáshoz

Szokás szerint ennek a műtárgynak a legújabb verzióját a Maven Central keresőmotor segítségével találhatjuk meg.

4. Alapkonfiguráció a Spring Boot használatával

Először is azzal kezdjük, hogy konfiguráljuk az alkalmazásunkat az imént a Google-lal létrehozott kliens regisztráció használatára.

A Spring Boot használata ezt nagyon megkönnyíti, mivel csak két alkalmazás tulajdonságot kell megadnunk:

tavasz: biztonság: oauth2: kliens: regisztráció: google: kliens-azonosító: kliens-titok: 

Indítsuk el az alkalmazást, és próbáljunk meg most elérni egy végpontot. Meglátjuk, hogy átirányítunk egy Google Login oldalra az OAuth 2.0 kliens számára.

Nagyon egyszerűnek tűnik, de itt nagyon sok minden zajlik a motorháztető alatt. Ezután megvizsgáljuk, hogy a Spring Security hogyan húzza ezt le.

Korábban a WebClient és az OAuth 2 támogatási bejegyzésünkben elemeztük a belső elemeket, hogy a Spring Security hogyan kezeli az OAuth 2.0 engedélyezési kiszolgálókat és klienseket.

Odabent láttuk, hogy a kliens azonosítóján és a kliens titkán kívül további adatokat kell megadnunk a ClientRegistration példány sikeresen. Szóval, hogy működik ez?

A válasz, A Google jól ismert szolgáltató, ezért a keretrendszer előre meghatározott tulajdonságokat kínál a dolgok megkönnyítése érdekében.

Megtekinthetjük ezeket a konfigurációkat a CommonOAuth2Provider enum.

A Google esetében a felsorolt ​​típus a következő tulajdonságokat határozza meg:

  • az alapértelmezett hatókörök
  • az Engedélyezési végpont
  • a Token végpont
  • a UserInfo végpont, amely szintén része az OIDC Core specifikációnak

4.1. Hozzáférés a felhasználói információkhoz

A Spring Security egy OIDC-szolgáltatónál regisztrált felhasználó, a OidcUser entitás.

Eltekintve az alap OAuth2AuthenticatedPrincipal módszerek, ez az entitás hasznos funkciókat kínál:

  • töltse le az ID-token értékét és az abban szereplő követeléseket
  • szerezze meg a UserInfo végpont által biztosított követeléseket
  • generálja a két halmaz összesítését

Könnyen hozzáférhetünk ehhez az entitáshoz egy vezérlőben:

@GetMapping ("/ oidc-primary") nyilvános OidcUser getOidcUserPrincipal (@AuthenticationPrincipal OidcUser igazgató) {return principál; }

Vagy a SecurityContextHolder babban:

Hitelesítési hitelesítés = SecurityContextHolder.getContext (). GetAuthentication (); if (hitelesítés.getPrincipal () OidcUser példány) {OidcUser fő = ((OidcUser) hitelesítés.getPrincipal ()); // ...}

Ha megvizsgáljuk a megbízót, sok hasznos információt látunk itt, például a felhasználó nevét, e-mail címét, profilképét és területi beállításait.

Ezenkívül fontos megjegyezni, hogy Spring a szolgáltatótól kapott hatókörök alapján hozzáadja a hatóságokat a megbízóhoz, aHATÁLY_“. Például a nyitott hatókör lesz a SCOPE_openid meghatalmazást kapott.

Ezek a hatóságok felhasználhatók például bizonyos forrásokhoz való hozzáférés korlátozására:

A @EnableWebSecurity nyilvános osztály, a MappedAuthorities kiterjeszti a WebSecurityConfigurerAdapter {protected void configure (HttpSecurity http) {http .authorizeRequests (authorizeRequests -> authorizeRequests .mvcMatchers ("/ én-végpont") .hasAuthorany ("SCOPE_. ; }}

5. Az OIDC működés közben

Eddig megtanultuk, hogyan lehet az OIDC Login megoldást egyszerűen megvalósítani a Spring Security segítségével

Láttuk, milyen előnye származik abból, ha a felhasználói azonosítási folyamatot egy OpenID szolgáltatóra ruházza át, amely viszont részletes, hasznos információkat szolgáltat, akár méretezhető módon is.

De az az igazság, hogy eddig nem kellett OIDC-specifikus szempontokkal foglalkoznunk. Ez azt jelenti, hogy a tavasz a legtöbb munkát elvégzi helyettünk.

Ezért meglátjuk, mi történik a kulisszák mögött, hogy jobban megértsük, hogyan hajtják végre ezt a specifikációt, és hogy a lehető legtöbbet hozzuk ki belőle.

5.1. A bejelentkezési folyamat

Annak érdekében, hogy ezt világosan lássuk, engedélyezzük a RestTemplate naplózza a szolgáltatás által végrehajtott kérelmeket:

naplózás: szint: org.springframework.web.client.RestTemplate: DEBUG

Ha most biztonságos végpontot hívunk, akkor láthatjuk, hogy a szolgáltatás végrehajtja az OAuth 2.0 rendszeres engedélyezési kódfolyamatát. Ez azért van, mert, mint mondtuk, ez a specifikáció az OAuth 2.0 tetejére épül. Egyébként vannak bizonyos különbségek.

Először is, az általunk használt szolgáltatótól és a konfigurált hatókörektől függően láthatjuk, hogy a szolgáltatás hívást kezdeményez az elején említett UserInfo végponton.

Nevezetesen, ha az Engedélyezési válasz lekér legalább egyet profil, email, cím vagy telefon hatókörét, a keretrendszer további információk beszerzése érdekében felhívja a UserInfo végpontot.

Annak ellenére, hogy minden jelezné, hogy a Google-nak be kell szereznie a profil és a email hatókör - mivel ezeket az engedélyezési kérelemben használjuk - az OP ehelyett lekéri egyéni társaikat, //www.googleapis.com/auth/userinfo.email és //www.googleapis.com/auth/userinfo.profile, így Spring nem hívja meg a végpontot.

Ez azt jelenti, hogy az összes megszerzett információ az ID Token része.

Saját magunk létrehozásával és biztosításával alkalmazkodhatunk ehhez a viselkedéshez OidcUserService példa:

A @Configuration nyilvános OAuth2LoginSecurityConfig osztály kiterjeszti a WebSecurityConfigurerAdapter {@Orride védett void configure (HttpSecurity http) kivételét dobja {Set googleScopes = new HashSet (); googleScopes.add ("//www.googleapis.com/auth/userinfo.email"); googleScopes.add ("//www.googleapis.com/auth/userinfo.profile"); OidcUserService googleUserService = új OidcUserService (); googleUserService.setAccessibleScopes (googleScopes); http .authorizeRequests (autorizeRequests -> autorizeRequests .anyRequest (). hitelesített ()) .oauth2Login (oauthLogin -> oauthLogin .userInfoEndpoint () .oidcUserService (googleUserService)); }}

A második különbség, amelyet megfigyelünk, a JWK Set URI hívása. Amint azt JWS és JWK bejegyzésünkben kifejtettük, ez a JWT formátumú ID Token aláírás ellenőrzésére szolgál.

Ezután részletesen elemezzük az ID-tokent.

5.2. Az azonosító token

Természetesen az OIDC specifikáció sokféle forgatókönyvre kiterjed és alkalmazkodik hozzájuk. Ebben az esetben az Engedélyezési kód folyamatot használjuk, és a protokoll azt jelzi, hogy mind az Access Token, mind az ID Token a Token Endpoint válasz részeként kerül letöltésre.

Mint korábban mondtuk, a OidcUser entitás tartalmazza az ID-tokenben található követeléseket és a tényleges JWT-formátumú tokent, amelyeket a jwt.io használatával lehet ellenőrizni.

Ráadásul a Spring sok praktikus gettert kínál a specifikáció által meghatározott standard igénypontok tiszta módon történő megszerzéséhez.

Láthatjuk, hogy az azonosító token tartalmaz néhány kötelező követelést:

  • a kibocsátó azonosítója URL-ként van formázva (pl.//accounts.google.com“)
  • tárgyazonosító, amely a végfelhasználó hivatkozása a kibocsátó által
  • a token lejárati ideje
  • a token kiadásának időpontja
  • a közönség, amely az általunk konfigurált OAuth 2.0 kliens azonosítót tartalmazza

És számos OIDC szabványos követelés, mint amilyeneket korábban említettünk (név, területi beállítás, kép, email).

Mivel ezek szabványosak, sok szolgáltatótól elvárhatjuk, hogy legalább néhány ilyen területet megszerezzen, és ezzel megkönnyítse az egyszerűbb megoldások kidolgozását.

5.3. Követelések és hatályok

Mint azt elképzelhetjük, az OP által letöltött követelések megfelelnek az általunk (vagy a Spring Security) által konfigurált hatóköröknek.

Az OIDC meghatároz néhány hatókört, amelyek felhasználhatók az OIDC által meghatározott igénypontok kérésére:

  • profil, amellyel alapértelmezett profilkéréseket lehet kérni (pl. név, preferált_felhasználónév,kép, satöbbi)
  • email, a email és email_verified Követelések
  • cím
  • telefon, a telefonszám és telefonszám ellenőrzött Követelések

Annak ellenére, hogy a Spring még nem támogatja, a specifikáció lehetővé teszi az egyes követelések igénylését azáltal, hogy megadja azokat az engedélyezési kérelemben.

6. Az OIDC Discovery tavaszi támogatása

Amint azt a bevezetőben kifejtettük, az OIDC alapvető célján kívül számos különféle funkciót tartalmaz.

Az ebben a szakaszban és az alábbiakban elemezni kívánt képességek nem kötelezőek az OIDC-ben. Ezért fontos megérteni, hogy lehetnek olyan operatív programok, amelyek nem támogatják őket.

A specifikáció meghatározza a felfedezési mechanizmust az RP számára, hogy felfedezze az operációs rendszert és megszerezze a vele való interakcióhoz szükséges információkat.

Dióhéjban az OP-k JSON szabványos metaadatokat tartalmazó dokumentumot nyújtanak be. Az információt a kibocsátó helyének jól ismert végpontjának kell szolgáltatnia, /.well-known/openid-configuration.

A tavasz profitál ebből azáltal, hogy konfigurálhatjuk a ClientRegistration csak egy egyszerű tulajdonsággal, a kibocsátó helyével.

De ugorjunk rögtön egy példába, hogy ezt tisztán lássuk.

Meghatározunk egy szokást ClientRegistration példa:

tavasz: biztonság: oauth2: kliens: regisztráció: custom-google: kliens-azonosító: kliens-titok: szolgáltató: custom-google: kibocsátó-uri: //accounts.google.com

Most újraindíthatjuk az alkalmazásunkat, és ellenőrizhetjük a naplókat, hogy megerősítsük-e az alkalmazás hívását openid-configuration végpont az indítási folyamatban.

Még ezen a végponton is böngészhetünk, hogy megnézhessük a Google által nyújtott információkat:

//accounts.google.com/.well-known/openid-configuration

Láthatjuk például a jogosultságot, a tokent és a UserInfo végpontokat, amelyeket a szolgáltatásnak használnia kell, valamint a támogatott hatóköröket.

Különösen fontos megjegyezni, hogy ha a szolgáltatás elindításakor a Discovery végpont nem áll rendelkezésre, akkor alkalmazásunk nem tudja sikeresen befejezni az indítási folyamatot.

7. OpenID Connect munkamenet-kezelés

Ez a specifikáció kiegészíti az alapfunkciókat az alábbiak meghatározásával:

  • különböző módok a végfelhasználó bejelentkezési állapotának folyamatos figyelemmel kísérésére az OP-n annak érdekében, hogy az RP kijelentkezhessen az OpenID-szolgáltatóból kijelentkezett végfelhasználóból
  • RP kijelentkezési URI-k regisztrálásának lehetősége az OP-nél az ügyfélregisztráció részeként, hogy értesítést kapjon, amikor a végfelhasználó kijelentkezik az OP-ból
  • mechanizmus arra, hogy értesítsék az OP-t arról, hogy a Végfelhasználó kijelentkezett a webhelyről, és érdemes lehet kijelentkeznie az OP-ból is

Természetesen nem minden operációs rendszer támogatja ezeket az elemeket, és ezeknek a megoldásoknak a némelyike ​​csak egy felhasználói felületen keresztül valósítható meg a User-Agent segítségével.

Ebben az oktatóanyagban a Spring által a lista utolsó eleméhez, az RP által kezdeményezett kijelentkezéshez kínált lehetőségekre összpontosítunk.

Ezen a ponton, ha bejelentkezünk az alkalmazásunkba, akkor általában elérhetünk minden végpontot.

Ha kijelentkezünk (hívjuk a /Kijelentkezés végpont), és utána kérünk egy biztonságos erőforrást, látni fogjuk, hogy úgy kapjuk meg a választ, hogy nem kell újra bejelentkeznünk.

Ez azonban valójában nem igaz; ha megvizsgáljuk a Hálózat fület a böngésző hibakereső konzolján, látni fogjuk, hogy amikor másodszor elérjük a biztonságos végpontot, átirányítjuk az OP engedélyezési végpontra, és mivel még mindig ott vagyunk bejelentkezve, a folyamat átláthatóan befejeződik , szinte azonnal a biztonságos végpontba kerül.

Természetesen ez bizonyos esetekben nem biztos, hogy a kívánt viselkedés. Lássuk, hogyan tudjuk megvalósítani ezt az OIDC-mechanizmust ennek kezelésére.

7.1. Az OpenID szolgáltató konfigurációja

Ebben az esetben egy Okta példányt fogunk konfigurálni és használni OpenID szolgáltatóként. Nem részletezzük a példány létrehozásának részleteit, de követhetjük ennek az útmutatónak a lépéseit, és szem előtt tartva, hogy a Spring Security alapértelmezett visszahívási végpontja / login / oauth2 / code / okta.

Alkalmazásunkban meghatározhatjuk a kliens regisztrációs adatait tulajdonságokkal:

tavasz: biztonság: oauth2: kliens: regisztráció: okta: kliens-azonosító: kliens-titok: szolgáltató: okta: kibocsátó-uri: //dev-123.okta.com

Az OIDC azt jelzi, hogy az OP kijelentkezési végpont megadható a Discovery dokumentumban, mint end_session_endpoint elem.

7.2. A LogoutSuccessHandler Konfiguráció

Ezután konfigurálnunk kell a HttpBiztonság kijelentkezési logika testreszabott módon LogoutSuccessHandler példa:

A @Orride védett void configure (HttpSecurity http) dobja a {http .authorizeRequests (authorizeRequests -> authorizeRequests .mvcMatchers ("/ home"). SallAll () .anyRequest (). Hitelesített ()) .oauth2Login (oauthLogin -> oauthermelogin -> oautherminogin ()) .logout (kijelentkezés -> kijelentkezés .logoutSuccessHandler (oidcLogoutSuccessHandler ())); }

Most nézzük meg, hogyan hozhatunk létre a LogoutSuccessHandler erre a célra a Spring Security által biztosított speciális osztály, az OidcClientInitiatedLogoutSuccessHandler:

@Autowired private ClientRegistrationRepository clientRegistrationRepository; privát LogoutSuccessHandler oidcLogoutSuccessHandler () {OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler = új OidcClientInitiatedLogoutSuccessHandler (this.clientRegistrationRepository); oidcLogoutSuccessHandler.setPostLogoutRedirectUri (URI.create ("// localhost: 8081 / home")); return oidcLogoutSuccessHandler; }

Következésképpen ezt az URI-t érvényes kijelentkezési átirányítási URI-ként kell beállítanunk az OP Client konfigurációs paneljén.

Nyilvánvaló, hogy az OP kijelentkezés konfigurációja az ügyfélregisztráció beállításában található, mivel a kezelő konfigurálásához csak a ClientRegistrationRepository bab jelen van a kontextusban.

És most mi lesz?

Miután bejelentkeztünk alkalmazásunkba, kérelmet küldhetünk a /Kijelentkezés végpontot a Spring Security nyújtotta.

Ha ellenőrizzük a hálózati naplókat a böngésző hibakereső konzolján, látni fogjuk, hogy átirányítottunk egy OP kijelentkezési végpontba, mielőtt végül elérnénk a konfigurált Átirányítási URI-t.

Ha legközelebb hozzáférünk egy olyan hitelesítést igénylő végponthoz az alkalmazásunkban, akkor engedélyek megszerzéséhez kötelezően újra be kell jelentkeznünk az OP platformunkon.

8. Következtetés

Összefoglalva: ebben az oktatóanyagban sokat megtudhattunk az OpenID Connect által kínált megoldásokról, és arról, hogy miként valósíthatunk meg néhányat a Spring Security segítségével.

Mint mindig, az összes teljes példa megtalálható a GitHub repóban.


$config[zx-auto] not found$config[zx-overlay] not found