Eenvoudige eenmalige aanmelding met Spring Security OAuth2

1. Overzicht

In deze zelfstudie bespreken we hoe u SSO - Single Sign On - met Spring Security OAuth en Spring Boot, met Keycloak als de autorisatieserver.

We gebruiken 4 afzonderlijke applicaties:

  • Een autorisatieserver - het centrale authenticatiemechanisme
  • A Resource Server - de aanbieder van Foos
  • Twee clienttoepassingen - de toepassingen die SSO gebruiken

Heel eenvoudig gezegd: wanneer een gebruiker toegang probeert te krijgen tot een bron via één Client-app, wordt hij of zij eerst omgeleid om zich te authenticeren, via de autorisatieserver. Keycloak zal de gebruiker aanmelden, en terwijl hij nog steeds is aangemeld bij de eerste app, als de tweede Client-app wordt geopend met dezelfde browser, hoeft de gebruiker zijn inloggegevens niet opnieuw in te voeren.

We gaan de Authorisatie Code verlenen type uit OAuth2 om de delegatie van authenticatie aan te sturen.

We gebruiken de OAuth-stack in Spring Security 5. Als u de legacy-stack van Spring Security OAuth wilt gebruiken, bekijk dan dit vorige artikel: Simple Single Sign-On met Spring Security OAuth2 (legacy-stack)

Volgens de migratiegids:

Spring Security verwijst naar deze functie als OAuth 2.0 Login, terwijl Spring Security OAuth ernaar verwijst als SSO

Oké, laten we meteen beginnen.

2. De autorisatieserver

Eerder bood de Spring Security OAuth-stack de mogelijkheid om een ​​Authorization Server in te richten als Spring Application.

De OAuth-stack is echter verouderd door Spring en nu gebruiken we Keycloak als onze autorisatieserver.

Dus deze keer zullen we onze Authorization Server instellen als een embedded Keycloak-server in een Spring Boot-app.

In onze voorconfiguratie we zullen twee klanten definiëren, ssoClient-1 en ssoClient-2, één voor elke clienttoepassing.

3. De bronserver

Vervolgens hebben we een Resource Server of de REST API nodig die ons de Foos onze Client-app zal verbruiken.

Het is in wezen hetzelfde als dat we eerder gebruikten voor onze Angular Client-apps.

4. De clienttoepassingen

Laten we nu eens kijken naar onze Thymeleaf Client Application; we zullen natuurlijk Spring Boot gebruiken om de configuratie te minimaliseren.

Houd daar rekening mee we hebben er twee nodig om Single Sign-On-functionaliteit te demonstreren.

4.1. Afhankelijkheden van Maven

Ten eerste hebben we de volgende afhankelijkheden nodig in onze 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 

Om alle klantondersteuning die we nodig hebben, inclusief beveiliging, op te nemen, hoeven we alleen maar toe te voegen spring-boot-starter-oauth2-client. Ook sinds de oude RestTemplate wordt verouderd, we gaan gebruiken Web cliënt, en daarom hebben we toegevoegd lente-webflux en reactor-netty.

4.2. Beveiligingsconfiguratie

Vervolgens het belangrijkste onderdeel, de beveiligingsconfiguratie van onze eerste clienttoepassing:

@EnableWebSecurity openbare klasse UiSecurityConfig breidt WebSecurityConfigurerAdapter uit {@Override public void configure (HttpSecurity http) genereert uitzondering {http.antMatcher ("/ **") .authorizeRequests () .antMatchers ("/") .permitAll (). geverifieerd (). en () .oauth2Login (); } @Bean WebClient webClient (ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientRepository geautoriseerdeClientRepository) {ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2 = nieuwe ServletOAuth2AuthorizedClientRepository client, geautoriseerde client; oauth2.setDefaultOAuth2AuthorizedClient (true); retourneer WebClient.builder (). apply (oauth2.oauth2Configuration ()). build (); }}

Het belangrijkste onderdeel van deze configuratie is het oauth2Login () methode, die wordt gebruikt om de OAuth 2.0 Login-ondersteuning van Spring Security in te schakelen. Omdat we Keycloak gebruiken, wat standaard een single sign-on-oplossing is voor web-apps en RESTful-webservices, hoeven we geen verdere configuratie voor SSO toe te voegen.

Ten slotte hebben we ook een Web cliënt bean om te fungeren als een eenvoudige HTTP-client om verzoeken af ​​te handelen die naar onze Resource Server moeten worden verzonden.

En hier is de application.yml:

spring: security: oauth2: client: registration: custom: client-id: ssoClient-1 client-secret: ssoClientSecret-1 scope: read, write authorisation-grant-type: authorisation_code redirect-uri: // localhost: 8082 / ui- one / login / oauth2 / code / custom provider: custom: autorisatie-uri: // localhost: 8083 / auth / realms / baeldung / protocol / 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 gebruikersnaam-attribuut: preferred_username thymeleaf: cache: false server: port: 8082-servlet: contextpad: / ui-one resourceserver: api: project: url: // localhost: 8081 / sso-resource-server / api / foos / 

Hier, spring.security.oauth2.client.registration is de root-naamruimte voor het registreren van een client. We hebben een klant met registratie-ID gedefinieerd Op maat. Vervolgens hebben we het gedefinieerd klant identificatie, cliëntgeheim, reikwijdte, autorisatie-toekenning-type en redirect-uri, wat natuurlijk hetzelfde zou moeten zijn als gedefinieerd voor onze autorisatieserver.

Daarna hebben we onze serviceprovider of de autorisatieserver gedefinieerd, opnieuw met dezelfde id van Op maat, en de verschillende URI's opgesomd die Spring Security kan gebruiken. Dat is alles wat we nodig hebben om te definiëren, en het framework doet het volledige inlogproces, inclusief doorverwijzing naar Keycloak, naadloos voor ons.

Merk ook op dat we in ons voorbeeld hier onze autorisatieserver hebben uitgerold, maar we kunnen natuurlijk ook andere externe providers gebruiken, zoals Facebook of GitHub.

4.3. De controller

Laten we nu onze controller implementeren in de Client-app waar we om vragen Foos van onze Resource Server:

@Controller openbare klasse FooClientController {@Value ("$ {resourceserver.api.url}") privé String fooApiUrl; @Autowired private WebClient webClient; @GetMapping ("/ foos") public String getFoos (Modelmodel) {List foos = this.webClient.get () .uri (fooApiUrl) .retrieve () .bodyToMono (nieuw ParameterizedTypeReference() {}) .block (); model.addAttribute ("foos", foos); retourneer "foos"; }}

Zoals we kunnen zien, hebben we hier maar één methode die de bronnen naar het foos sjabloon. We hoefden geen code toe te voegen om in te loggen.

4.4. Voorkant

Laten we nu eens kijken naar de front-end-configuratie van onze clienttoepassing. Daar gaan we ons hier niet op concentreren, vooral omdat we het al op de site hebben behandeld.

Onze klanttoepassing heeft hier een heel eenvoudige front-end; hier is de index.html:

Spring OAuth Client Thymeleaf - 1 Welkom!

Log in

En de foos.html:

Spring OAuth-client Thymeleaf -1 Hallo, voorkeursgebruikersnaam 
ID kaartNaam
Geen foos
ID kaart Naam

De foos.html pagina heeft de gebruikers nodig om te worden geverifieerd. Als een niet-geauthenticeerde gebruiker toegang probeert te krijgen foos.html, worden ze eerst doorgestuurd naar de inlogpagina van Keycloak.

4.5. De tweede clienttoepassing

We zullen een tweede applicatie configureren, Spring OAuth-client Thymeleaf -2 een ander gebruiken klant identificatiessoClient-2.

Het zal grotendeels hetzelfde zijn als de eerste applicatie die we zojuist hebben beschreven.

De application.yml zal verschillen om een ​​andere op te nemen klant identificatie, client_secret en redirect_uri in zijn spring.security.oauth2.client.registration:

spring: security: oauth2: client: registration: custom: client-id: ssoClient-2 client-secret: ssoClientSecret-2 scope: read, write authorisation-grant-type: authorisation_code redirect-uri: // localhost: 8084 / ui- two / login / oauth2 / code / custom

En natuurlijk hebben we er ook een andere serverpoort voor nodig, zodat we ze parallel kunnen draaien:

server: poort: 8084 servlet: contextpad: / ui-two

Ten slotte zullen we de front-end HTML's aanpassen om een ​​titel te hebben als Spring OAuth-client Thymeleaf - 2 in plaats van – 1 zodat we onderscheid kunnen maken tussen de twee.

5. SSO-gedrag testen

Laten we onze applicaties uitvoeren om SSO-gedrag te testen.

Hiervoor hebben we al onze 4 Boot Apps - de Authorization Server, de Resource Server en beide Client Applicaties - nodig.

Laten we nu een browser openen, bijvoorbeeld Chrome, en inloggen op Client-1 met behulp van de inloggegevens [e-mail beveiligd] / 123. Druk vervolgens in een ander venster of tabblad op de URL voor Client-2. Als u op de login-knop klikt, worden we doorgestuurd naar het Foos pagina meteen, waarbij u de authenticatiestap overslaat.

Evenzo als de gebruiker zich aanmeldt bij Client-2 Ten eerste hoeven ze hun gebruikersnaam / wachtwoord niet in te voeren voor Client-1.

6. Conclusie

In deze tutorial hebben we ons gericht op het implementeren van Single Sign-On met Spring Security OAuth2 en Spring Boot met Keycloak als identiteitsprovider.

Zoals altijd is de volledige broncode te vinden op GitHub.