Enkel enkelt login med Spring Security OAuth2

1. Oversigt

I denne vejledning diskuterer vi, hvordan du implementerer SSO - Single Sign On - ved hjælp af Spring Security OAuth og Spring Boot, ved hjælp af Keycloak som autorisationsserver.

Vi bruger 4 separate applikationer:

  • En autorisationsserver - som er den centrale godkendelsesmekanisme
  • En ressource server - udbyderen af Foos
  • To klientapplikationer - applikationerne ved hjælp af SSO

Meget enkelt sagt, når en bruger forsøger at få adgang til en ressource via en klientapp, bliver de omdirigeret til godkendelse først gennem autorisationsserveren. Keycloak logger brugeren ind, og mens den stadig er logget ind i den første app, skal brugeren ikke indtaste deres legitimationsoplysninger igen, hvis der er adgang til den anden klientapp ved hjælp af den samme browser.

Vi skal bruge Autorisationskode tildel type ud af OAuth2 for at drive delegering af godkendelse.

Vi bruger OAuth-stakken i Spring Security 5. Hvis du vil bruge Spring Security OAuth legacy stack, skal du kigge på denne tidligere artikel: Simple Single Sign-On with Spring Security OAuth2 (legacy stack)

I henhold til migrationsguiden:

Spring Security henviser til denne funktion som OAuth 2.0 Login, mens Spring Security OAuth henviser til den som SSO

Okay, lad os hoppe lige ind.

2. Autorisationsserveren

Tidligere tilbød Spring Security OAuth-stakken muligheden for at oprette en autorisationsserver som en Spring Application.

OAuth-stakken er imidlertid udfaset af Spring, og nu bruger vi Keycloak som vores autorisationsserver.

Så denne gang opretter vi vores autorisationsserver som en integreret Keycloak-server i en Spring Boot-app.

I vores forudkonfiguration vi definerer to klienter, ssoClient-1 og ssoClient-2, en til hver klientapplikation.

3. Ressource-serveren

Dernæst har vi brug for en ressource server eller REST API, som giver os Foos vores klientapp bruger.

Det er stort set det samme som vi tidligere brugte til vores Angular Client Apps.

4. Klientapplikationerne

Lad os nu se på vores Thymeleaf Client Application; Vi bruger selvfølgelig Spring Boot til at minimere konfigurationen.

Husk det vi bliver nødt til at have to af disse for at demonstrere Single Sign-On-funktionalitet.

4.1. Maven afhængigheder

For det første har vi brug for følgende afhængigheder i vores pom.xml:

 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-oauth2-client org.springframework.boot spring-boot-starter-thymeleaf org.thymeleaf.extras thymeleaf-extras-springsecurity5 org. springframework spring-webflux io.projectreactor.netty reactor-netty 

For at inkludere al den klientsupport, vi har brug for, inklusive sikkerhed, skal vi bare tilføje spring-boot-starter-oauth2-klient. Også siden den gamle RestTemplate bliver udfaset, skal vi bruge Webklient, og det er derfor, vi tilføjede fjeder-webstrøm og reaktor-netty.

4.2. Sikkerhedskonfiguration

Dernæst den vigtigste del, sikkerhedskonfigurationen af ​​vores første klientapplikation:

@EnableWebSecurity offentlig klasse UiSecurityConfig udvider WebSecurityConfigurerAdapter {@Override public void configure (HttpSecurity http) kaster undtagelse {http.antMatcher ("/ **") .authorizeRequests () .antMatchers ("/") .permitAll () .any. godkendt () .og () .oauth2Login (); } @Bean WebClient webClient (ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientRepository autorisedClientRepository) {ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2 = new ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2 = new ServletOAuth2AuthorisedClientExchangeFilterFunction oauth2.setDefaultOAuth2AuthorizedClient (true); returner WebClient.builder (). anvend (oauth2.oauth2Configuration ()). build (); }}

Den centrale del af denne konfiguration er oauth2Login () metode, der bruges til at aktivere Spring Securitys OAuth 2.0 Login support. Da vi bruger Keycloak, som som standard er en enkelt logon-løsning til webapps og RESTful webtjenester, behøver vi ikke tilføje yderligere konfiguration til SSO.

Endelig definerede vi også en Webklient bean til at fungere som en simpel HTTP-klient til at håndtere anmodninger, der skal sendes til vores ressource server.

Og her er den ansøgning.yml:

forår: sikkerhed: oauth2: klient: registrering: brugerdefineret: klient-id: ssoClient-1 klient-hemmelighed: ssoClientSecret-1 rækkevidde: læse, skrive autorisation-tildelingstype: autorisationskode omdirigere-uri: // localhost: 8082 / ui- en / login / oauth2 / kode / brugerdefineret udbyder: brugerdefineret: autorisation-uri: // localhost: 8083 / auth / realms / baeldung / protokol / openid-connect / auth token-uri: // localhost: 8083 / auth / realms / baeldung / protocol / openid-connect / token user-info-uri: // localhost: 8083 / auth / realms / baeldung / protocol / openid-connect / userinfo user-name-attribute: preferred_username thymeleaf: cache: false server: port: 8082 servlet: context-path: / ui-one resourceserver: api: project: url: // localhost: 8081 / sso-resource-server / api / foos / 

Her, spring.security.oauth2.client.registration er rodnavneområdet til registrering af en klient. Vi definerede en klient med registrerings-id brugerdefinerede. Så definerede vi dens klient-id, klienthemmelighed, rækkevidde, autorisation-tildelingstype og omdirigere-uri, hvilket naturligvis skal være det samme som det, der er defineret for vores autorisationsserver.

Derefter definerede vi vores tjenesteudbyder eller autorisationsserveren igen med den samme id brugerdefineredeog listede de forskellige URI'er, som Spring Security skal bruge. Det er alt, hvad vi har brug for at definere, og rammen udfører hele loginprocessen, inklusive omdirigering til Keycloak, problemfrit for os.

Bemærk også, at vi i vores eksempel her rullede vores autorisationsserver ud, men selvfølgelig kan vi også bruge andre tredjepartsudbydere som Facebook eller GitHub.

4.3. Controlleren

Lad os nu implementere vores controller i klientappen for at bede om Foos fra vores ressource server:

@Controller offentlig klasse FooClientController {@Value ("$ {resourceserver.api.url}") privat streng fooApiUrl; @Autowired privat WebClient webClient; @GetMapping ("/ foos") offentlig String getFoos (Modelmodel) {Liste foos = this.webClient.get () .uri (fooApiUrl) .hent () .bodyToMono (ny ParameterizedTypeReference() {}) .block (); model.addAttribute ("foos", foos); returner "foos"; }}

Som vi kan se, har vi kun en metode her, der uddeler ressourcerne til foos skabelon. Vi behøvede ikke at tilføje nogen kode til login.

4.4. Frontend

Lad os nu se på front-end-konfigurationen af ​​vores klientapplikation. Vi vil ikke fokusere på det her, primært fordi vi allerede dækkede ind på siden.

Vores klientapplikation her har en meget enkel front-end; her er den index.html:

Spring OAuth Client Thymeleaf - 1 Velkommen!

Log på

Og foos.html:

Spring OAuth Client Thymeleaf -1 Hej, foretrukket_brugernavn 
IDNavn
Ingen foos
ID Navn

Det foos.html siden skal brugerne godkendes. Hvis en ikke-godkendt bruger forsøger at få adgang foos.html, de bliver omdirigeret til Keycloaks login-side først.

4.5. Den anden klientapplikation

Vi konfigurerer en anden applikation, Spring OAuth Client Thymeleaf -2 ved hjælp af en anden klient_idssoClient-2.

Det vil for det meste være det samme som den første applikation, vi lige har beskrevet.

Det ansøgning.yml vil variere for at inkludere en anden klient_id, klienthemmelighed og redirect_uri i dets spring.security.oauth2.client.registration:

forår: sikkerhed: oauth2: klient: registrering: brugerdefineret: klient-id: ssoClient-2 klienthemmelighed: ssoClientSecret-2 rækkevidde: læse, skrive autorisation-tildelingstype: autorisation_kode omdirigere-uri: // localhost: 8084 / ui- to / login / oauth2 / kode / brugerdefineret

Og selvfølgelig skal vi også have en anden serverport, så vi kan køre dem parallelt:

server: port: 8084 servlet: kontekststi: / ui-two

Endelig tilpasser vi frontend-HTML'erne for at få en titel som Spring OAuth Client Thymeleaf - 2 i stedet for – 1 så vi kan skelne mellem de to.

5. Test af SSO-adfærd

Lad os køre vores applikationer for at teste SSO-opførsel.

Vi har brug for alle vores 4 boot-apps - autorisationsserveren, ressource-serveren og begge klientapplikationer - for at være i gang med dette.

Lad os nu åbne en browser, sig Chrome, og log ind på Klient-1 ved hjælp af legitimationsoplysninger [e-mail-beskyttet] / 123. Klik derefter på webadressen for i et andet vindue eller en anden fane Klient-2. Når du klikker på login-knappen, omdirigeres vi til Foos side straks, uden om godkendelsestrinet.

Tilsvarende hvis brugeren logger på Klient-2 først skal de ikke indtaste deres brugernavn / adgangskode til Klient-1.

6. Konklusion

I denne vejledning fokuserede vi på at implementere Single Sign-On ved hjælp af Spring Security OAuth2 og Spring Boot ved hjælp af Keycloak som identitetsudbyder.

Som altid kan den fulde kildekode findes på GitHub.