Jarné zabezpečenie a pripojenie OpenID

Upozorňujeme, že tento článok bol aktualizovaný na nový zásobník Spring Security OAuth 2.0. Výukový program využívajúci starší zásobník je však stále k dispozícii.

1. Prehľad

V tomto rýchlom výučbe sa zameriame na nastavenie OpenID Connect (OIDC) s Spring Security.

Predstavíme rôzne aspekty tejto špecifikácie a potom uvidíme podporu, ktorú poskytuje Spring Security na jej implementáciu na klientovi OAuth 2.0.

2. Úvod do Quick OpenID Connect

OpenID Connect je vrstva identity postavená na protokole OAuth 2.0.

Preto je skutočne dôležité poznať OAuth 2.0 skôr, ako sa ponoríte do OIDC, najmä tok autorizačného kódu.

Sada špecifikácií OIDC je rozsiahla; obsahuje základné funkcie a niekoľko ďalších voliteľných funkcií predstavených v rôznych skupinách. Hlavné sú:

  • Jadro: autentifikácia a použitie nárokov na komunikáciu informácií o koncovom používateľovi
  • Discovery: určuje, ako môže klient dynamicky určovať informácie o poskytovateľoch OpenID
  • Dynamická registrácia: určuje, ako sa môže klient zaregistrovať u poskytovateľa
  • Správa relácií: definuje, ako spravovať relácie OIDC

Okrem toho dokumenty rozlišujú autentifikačné servery OAuth 2.0, ktoré poskytujú podporu tejto špecifikácii, a označujú ich ako „poskytovateľov OpenID“ (OP) a klientov OAuth 2.0, ktorí používajú OIDC ako spoliehajúce sa strany (RP). Tejto terminológie sa budeme držať v tomto článku.

Je potrebné tiež vedieť, že klient môže požiadať o použitie tohto rozšírenia pridaním otvorený rozsahu svojej žiadosti o autorizáciu.

A nakoniec, ďalším aspektom, ktorý je užitočné pochopiť pre tento tutoriál, je skutočnosť, že OP vydávajú informácie o koncovom používateľovi ako JWT nazývaný „ID Token“.

Teraz áno, sme pripravení ponoriť sa hlbšie do sveta OIDC.

3. Nastavenie projektu

Pred zameraním na skutočný vývoj budeme musieť zaregistrovať klienta OAuth 2.o u nášho poskytovateľa OpenID.

V takom prípade použijeme Google ako poskytovateľa OpenID. Podľa týchto pokynov môžeme zaregistrovať našu klientsku aplikáciu na ich platforme. Všimnite si, že otvorený rozsah je predvolene prítomný.

Identifikátor URI presmerovania, ktorý sme nastavili v tomto procese, je koncovým bodom v našej službe: // localhost: 8081 / login / oauth2 / code / google.

Z tohto procesu by sme mali získať ID klienta a tajomstvo klienta.

3.1. Konfigurácia Maven

Začneme pridaním týchto závislostí do nášho súboru pom projektu:

 org.springframework.boot spring-boot-starter-oauth2-client 2.2.6.RELEASE 

Artefakt štartéra agreguje všetky závislosti súvisiace s Spring Security Client, vrátane:

  • the spring-security-oauth2-client závislosť na prihlasovaní OAuth 2.0 a funkčnosti klienta
  • knižnica JOSE pre podporu JWT

Ako obvykle nájdeme najnovšiu verziu tohto artefaktu pomocou vyhľadávacieho nástroja Maven Central.

4. Základná konfigurácia pomocou Spring Boot

Najskôr začneme konfiguráciou našej aplikácie tak, aby používala registráciu klienta, ktorú sme práve vytvorili pomocou spoločnosti Google.

Používanie Spring Boot to veľmi uľahčuje, pretože musíme iba definovať dve vlastnosti aplikácie:

jar: zabezpečenie: oauth2: klient: registrácia: google: ID klienta: tajomstvo klienta: 

Spustíme našu aplikáciu a pokúsime sa teraz získať prístup k koncovému bodu. Uvidíme, že budeme presmerovaní na stránku Prihlásenie Google pre nášho klienta OAuth 2.0.

Vyzerá skutočne jednoducho, ale pod kapotou sa tu deje dosť veľa vecí. Ďalej preskúmame, ako to vyrieši Spring Security.

Predtým sme v našom príspevku WebClient a OAuth 2 Support analyzovali interné prvky o tom, ako Spring Security spracováva autorizačné servery a klientov OAuth 2.0.

Tam sme videli, že musíme nakonfigurovať a, okrem ID klienta a tajného kódu klienta, poskytnúť ďalšie údaje ClientRegistration inštancia úspešne. Ako to teda funguje?

Odpoveď je, Google je známy poskytovateľ, a preto rámec ponúka niektoré preddefinované vlastnosti, ktoré uľahčujú prácu.

Na tieto konfigurácie sa môžeme pozrieť v CommonOAuth2Provider enum.

Pre Google vymenovaný typ definuje vlastnosti ako:

  • predvolené rozsahy, ktoré sa použijú
  • koncový bod autorizácie
  • koncový bod tokenu
  • koncový bod UserInfo, ktorý je tiež súčasťou špecifikácie OIDC Core

4.1. Prístup k informáciám o používateľovi

Spring Security ponúka užitočné zastúpenie príkazcu používateľa zaregistrovaného u poskytovateľa OIDC, servera OidcUser subjekt.

Okrem toho základného OAuth2AuthenticatedPrincipal metód ponúka táto entita niektoré užitočné funkcie:

  • načítať hodnotu tokenu ID a nároky, ktoré obsahuje
  • získať Nároky poskytnuté koncovým bodom UserInfo
  • generovať súhrn týchto dvoch množín

K tejto entite môžeme ľahko získať prístup v kontrolóri:

@GetMapping ("/ oidc-principal") verejné OidcUser getOidcUserPrincipal (@AuthenticationPrincipal OidcUser principál) {návratový principál; }

Alebo pomocou SecurityContextHolder vo fazuli:

Overenie autentifikácie = SecurityContextHolder.getContext (). GetAuthentication (); if (authentication.getPrincipal () instanceof OidcUser) {principál OidcUser = ((OidcUser) authentication.getPrincipal ()); // ...}

Ak skontrolujeme príkazcu, uvidíme tu veľa užitočných informácií, napríklad meno používateľa, e-mail, profilový obrázok a miestne nastavenie.

Ďalej je dôležité poznamenať, že Spring pridáva oprávnenia k príkazcovi na základe rozsahov, ktoré dostal od poskytovateľa, s predponou „ROZSAH_“. Napríklad otvorený rozsah sa stáva a SCOPE_openid udelený orgán.

Tieto orgány možno použiť napríklad na obmedzenie prístupu k určitým zdrojom:

@EnableWebSecurity verejná trieda MappedAuthorities rozširuje WebSecurityConfigurerAdapter {chránené neplatné konfigurácie (HttpSecurity http) {http .authorizeRequests (authorizeRequests -> authorizeRequests .mvcMatchers ("/ my-endpoint") .hasAuthority ("SCOPE_openid") ; }}

5. OIDC v akcii

Doteraz sme sa naučili, ako môžeme ľahko implementovať riešenie OIDC Login pomocou Spring Security

Videli sme výhodu, ktorú prináša delegovanie procesu identifikácie používateľa na poskytovateľa OpenID, ktorý zase poskytuje podrobné užitočné informácie, dokonca aj škálovateľným spôsobom.

Ale pravdou je, že sme sa doteraz nemuseli zaoberať žiadnym aspektom špecifickým pre OIDC. To znamená, že jar robí väčšinu práce za nás.

Uvidíme teda, čo sa deje v zákulisí, aby sme lepšie pochopili, ako sa táto špecifikácia uvádza do praxe, a dokázali z nej vyťažiť maximum.

5.1. Proces prihlásenia

Aby sme to videli jasne, povolme RestTemplate protokoly na zobrazenie požiadaviek, ktoré služba vykonáva:

protokolovanie: level: org.springframework.web.client.RestTemplate: DEBUG

Ak teraz zavoláme zabezpečený koncový bod, uvidíme, že služba vykonáva bežný tok autorizačného kódu OAuth 2.0. Je to preto, že ako sme už povedali, táto špecifikácia je postavená na vrchole protokolu OAuth 2.0. Aj tak existujú určité rozdiely.

Po prvé, v závislosti od poskytovateľa, ktorého používame, a rozsahov, ktoré sme nakonfigurovali, môžeme vidieť, že služba volá koncový bod UserInfo, ktorý sme spomenuli na začiatku.

Totiž, ak odpoveď na autorizáciu získa aspoň jednu z profilu, e-mail, adresa alebo telefón rámec zavolá koncový bod UserInfo, aby získal ďalšie informácie.

Aj keď by všetko nasvedčovalo tomu, že by Google mal získať profilu a e-mail rozsah - keďže ich používame v žiadosti o autorizáciu - operačný program namiesto nich načíta ich vlastné náprotivky, //www.googleapis.com/auth/userinfo.email a //www.googleapis.com/auth/userinfo.profile, teda Spring nenazýva koncový bod.

To znamená, že všetky informácie, ktoré získavame, sú súčasťou tokenu ID.

Môžeme sa tomuto správaniu prispôsobiť tým, že si vytvoríme a poskytneme svoje vlastné OidcUserService inštancia:

@Configuration verejná trieda OAuth2LoginSecurityConfig rozširuje WebSecurityConfigurerAdapter {@Override protected void configure (HttpSecurity http) vyvolá výnimku {Set googleScopes = new HashSet (); googleScopes.add ("//www.googleapis.com/auth/userinfo.email"); googleScopes.add ("//www.googleapis.com/auth/userinfo.profile"); OidcUserService googleUserService = nový OidcUserService (); googleUserService.setAccessibleScopes (googleScopes); http .authorizeRequests (authorizeRequests -> authorizeRequests .anyRequest (). authenticated ()) .oauth2Login (oauthLogin -> oauthLogin .userInfoEndpoint () .oidcUserService (googleUserService)); }}

Druhým rozdielom, ktorý budeme pozorovať, je volanie na URI sady JWK. Ako sme vysvetlili v našom príspevku JWS a JWK, toto sa používa na overenie podpisu tokenu ID vo formáte JWT.

Ďalej podrobne analyzujeme token ID.

5.2. Token ID

Špecifikácie OIDC prirodzene pokrývajú a prispôsobujú sa mnohým rôznym scenárom. V tomto prípade používame tok autorizačného kódu a protokol naznačuje, že prístupový token aj token ID sa získajú ako súčasť odpovede koncového bodu tokenu.

Ako sme už povedali, OidcUser entita obsahuje Nároky obsiahnuté v Tokene ID a skutočný token vo formáte JWT, ktorý je možné skontrolovať pomocou jwt.io.

Okrem toho ponúka spoločnosť Spring mnoho šikovných sprostredkovateľov čistého získavania štandardných reklamácií definovaných v špecifikácii.

Vidíme, že token ID obsahuje niektoré povinné nároky:

  • identifikátor emitenta naformátovaný ako adresa URL (napr. „//accounts.google.com“)
  • ID subjektu, čo je referencia koncového používateľa obsiahnutá v emitentovi
  • čas vypršania platnosti tokenu
  • čas, kedy bol token vydaný
  • publikum, ktoré bude obsahovať ID klienta OAuth 2.0, ktoré sme nakonfigurovali

A tiež veľa štandardných tvrdení OIDC, ako sme spomenuli predtým (názov, miestne nastavenie, obrázok, e-mail).

Pretože sa jedná o štandard, môžeme očakávať, že mnoho poskytovateľov vyhľadá aspoň niektoré z týchto oblastí, a tým uľahčí vývoj jednoduchších riešení.

5.3. Pohľadávky a rozsahy

Ako si vieme predstaviť, Nároky, ktoré získa OP, zodpovedajú rozsahom, ktoré sme nakonfigurovali (alebo Spring Security).

OIDC definuje niektoré rozsahy, ktoré možno použiť na vyžiadanie nárokov definovaných OIDC:

  • profilu, ktoré možno použiť na vyžiadanie predvolených nárokov na profil (napr. meno, preferovane_uzivatelske meno,obrázok, a tak dalej)
  • e-mail, na prístup k e-mail a email_verified Nároky
  • adresa
  • telefón, požiadať o telefónne číslo a phone_number_verified Nároky

Aj keď to Spring ešte nepodporuje, špecifikácia umožňuje vyžiadať jednotlivé Nároky tak, že ich uvediete v žiadosti o autorizáciu.

6. Jarná podpora pre OIDC Discovery

Ako sme si vysvetlili v úvode, OIDC okrem svojho hlavného účelu obsahuje mnoho rôznych funkcií.

Možnosti, ktoré budeme analyzovať v tejto časti a nasledujúcich, sú v OIDC voliteľné. Preto je dôležité si uvedomiť, že môžu existovať OP, ktoré ich nepodporujú.

Špecifikácia definuje mechanizmus Discovery pre RP na objavenie OP a získanie informácií potrebných na jeho interakciu.

Stručne povedané, operačné systémy poskytujú dokument JSON so štandardnými metadátami. Informácie musia byť poskytované dobre známym koncovým bodom umiestnenia emitenta, /.well-known/openid-configuration.

Jar z toho profituje tým, že nám umožňuje konfigurovať a ClientRegistration iba s jednou jednoduchou vlastnosťou, umiestnením emitenta.

Poďme však priamo na príklad, aby sme to videli jasne.

Zadefinujeme si zvyk ClientRegistration inštancia:

jar: zabezpečenie: oauth2: klient: registrácia: custom-google: client-id: client-secret: provider: custom-google: issuer-uri: //accounts.google.com

Teraz môžeme reštartovať našu aplikáciu a skontrolovať protokoly, aby sme potvrdili, že aplikácia volá konfigurácia openid koncový bod v procese spustenia.

Tento koncový bod môžeme dokonca prehliadať, aby sme sa pozreli na informácie poskytované spoločnosťou Google:

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

Vidíme napríklad autorizáciu, koncové body Token a UserInfo, ktoré musí služba používať, a podporované rozsahy.

Obzvlášť dôležitou poznámkou je skutočnosť, že ak koncový bod Discovery nie je k dispozícii v čase spustenia služby, naša aplikácia nebude môcť úspešne dokončiť proces spustenia.

7. Správa relácie OpenID Connect

Táto špecifikácia dopĺňa základné funkcie definovaním:

  • rôzne spôsoby, ako priebežne monitorovať stav prihlásenia koncového používateľa na OP, aby RP mohol odhlásiť koncového používateľa, ktorý sa odhlásil od poskytovateľa OpenID
  • možnosť registrácie URI odhlásenia RP v OP ako súčasť registrácie klienta, aby bola informovaná pri odhlásení koncového používateľa z OP
  • mechanizmus, ktorý informuje OP, že koncový používateľ sa odhlásil zo stránky a môže sa tiež chcieť odhlásiť z OP

Nie všetky OP samozrejme podporujú všetky tieto položky a niektoré z týchto riešení je možné implementovať iba v rámci front-end implementácie prostredníctvom User-Agent.

V tomto tutoriáli sa zameriame na možnosti, ktoré ponúka Spring pre poslednú položku zoznamu, Logout iniciovaný RP.

V tomto okamihu, ak sa prihlásime do našej aplikácie, môžeme normálne získať prístup ku každému koncovému bodu.

Ak sa odhlásime (voláme /odhlásiť sa endpoint) a následne pošleme požiadavku na zabezpečený zdroj, uvidíme, že dostaneme odpoveď bez nutnosti opätovného prihlásenia.

To však v skutočnosti nie je pravda; ak skontrolujeme kartu Sieť v konzole na ladenie prehľadávača, uvidíme, že keď narazíme na zabezpečený koncový bod druhýkrát, dostaneme sa k presmerovaniu na koncový bod autorizácie OP a keďže sme tam stále prihlásení, tok je dokončený transparentne , ktorý skončil v zabezpečenom koncovom bode takmer okamžite.

Samozrejme, v niektorých prípadoch to nemusí byť želané správanie. Pozrime sa, ako môžeme implementovať tento mechanizmus OIDC, aby sme sa s tým vyrovnali.

7.1. Konfigurácia poskytovateľa OpenID

V tomto prípade budeme konfigurovať a používať inštanciu Okta ako nášho poskytovateľa OpenID. Nebudeme sa zaoberať podrobnosťami o tom, ako vytvoriť inštanciu, ale môžeme postupovať podľa pokynov v tejto príručke a nezabúdať, že predvolený koncový bod spätného volania Spring Security bude / login / oauth2 / code / okta.

V našej aplikácii môžeme definovať registračné údaje klienta pomocou vlastností:

pružina: zabezpečenie: oauth2: klient: registrácia: okta: ID klienta: klientske tajomstvo: poskytovateľ: okta: vydavateľ-uri: //dev-123.okta.com

OIDC naznačuje, že koncový bod odhlásenia OP je možné určiť v dokumente Discovery ako end_session_endpoint element.

7.2. The LogoutSuccessHandler Konfigurácia

Ďalej budeme musieť nakonfigurovať HttpSecurity logiku odhlásenia poskytnutím prispôsobeného LogoutSuccessHandler inštancia:

@Override protected void configure (HttpSecurity http) vyvolá výnimku {http .authorizeRequests (authorizeRequests -> authorizeRequests .mvcMatchers ("/ home"). PermitAll () .anyRequest (). Authenticated ()) .oauth2Login (oauthLogin -> oauthLogin -> oauthLogin - ()) .logout (odhlásenie -> odhlásenie .logoutSuccessHandler (oidcLogoutSuccessHandler ())); }

Teraz sa pozrime, ako môžeme vytvoriť LogoutSuccessHandler na tento účel používa špeciálnu triedu poskytovanú spoločnosťou Spring Security, OidcClientInitiatedLogoutSuccessHandler:

@Autowired private ClientRegistrationRepository clientRegistrationRepository; private LogoutSuccessHandler oidcLogoutSuccessHandler () {OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler = nový OidcClientInitiatedLogoutSuccessHandler (this.clientRegistrationRepository); oidcLogoutSuccessHandler.setPostLogoutRedirectUri (URI.create ("// localhost: 8081 / home")); návrat oidcLogoutSuccessHandler; }

V dôsledku toho budeme musieť tento URI nastaviť ako platné URI presmerovania na odhlásenie v konfiguračnom paneli OP Client.

Je zrejmé, že konfigurácia odhlásenia OP je obsiahnutá v nastavení registrácie klienta, pretože všetko, čo používame na konfiguráciu obslužnej rutiny, je ClientRegistrationRepository fazuľa prítomná v kontexte.

Čo sa teda stane teraz?

Po prihlásení do našej aplikácie môžeme poslať žiadosť na adresu /odhlásiť sa koncový bod poskytnutý Spring Security.

Ak skontrolujeme denníky siete v konzole ladenia prehľadávača, uvidíme, že sme presmerovaní na koncový bod odhlásenia OP, až potom konečne pristúpime k nakonfigurovanému identifikátoru URI presmerovania.

Keď nabudúce vstúpime do koncového bodu v našej aplikácii, ktorý vyžaduje autentifikáciu, budeme sa musieť povinne znova prihlásiť na našej platforme OP, aby sme získali povolenia.

8. Záver

Ak to zhrnieme, v tomto tutoriáli sme sa naučili veľa o riešeniach ponúkaných OpenID Connect a o tom, ako môžeme niektoré z nich implementovať pomocou Spring Security.

Všetky úplné príklady ako vždy nájdete v našom repozitári GitHub.


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