From 2b219d81572f367fe1c7c003eb66f5b7d27b759c Mon Sep 17 00:00:00 2001 From: Jim Anderson Date: Mon, 23 Oct 2023 17:02:19 -0500 Subject: [PATCH] [SDK-4652] Spring Boot Login - Use Spring Boot 3 and Okta Spring Boot Starter --- .../webapp/java-spring-boot/01-login.md | 230 +++++++----------- .../java-spring-boot/files/application.md | 21 +- .../webapp/java-spring-boot/files/index.md | 6 +- .../java-spring-boot/files/logout-handler.md | 85 ------- .../files/security-config-logout.md | 46 +++- .../java-spring-boot/files/security-config.md | 12 +- .../webapp/java-spring-boot/index.yml | 7 +- .../webapp/java-spring-boot/interactive.md | 83 ++++--- 8 files changed, 187 insertions(+), 303 deletions(-) delete mode 100644 articles/quickstart/webapp/java-spring-boot/files/logout-handler.md diff --git a/articles/quickstart/webapp/java-spring-boot/01-login.md b/articles/quickstart/webapp/java-spring-boot/01-login.md index 1e1121d9bc..b50ce52e7e 100644 --- a/articles/quickstart/webapp/java-spring-boot/01-login.md +++ b/articles/quickstart/webapp/java-spring-boot/01-login.md @@ -1,6 +1,6 @@ --- title: Login -description: Spring Boot and Spring Security support OIDC natively, enabling you to add authentication to your application without the need for any additional libraries. This guide demonstrates how to integrate Auth0 with any new or existing Spring Boot 2 web application. +description: The Okta Spring Boot Starter makes it easy to add login to your Spring Boot application. budicon: 448 topics: - quickstarts @@ -17,15 +17,15 @@ useCase: quickstart This tutorial uses [Spring MVC](https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html). If you are using [Spring WebFlux](https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#spring-web-reactive), the steps to add authentication are similar, but some of the implementation details are different. Refer to the [Spring Boot WebFlux Sample Code](https://github.com/auth0-samples/auth0-spring-boot-login-samples/tree/master/webflux-login) to see how to integrate Auth0 with your Spring Boot WebFlux application. ::: -<%= include('../_includes/_getting_started', { library: 'Java Spring Security', callback: 'http://localhost:3000/login/oauth2/code/auth0' }) %> +<%= include('../_includes/_getting_started', { library: 'Java Spring Security', callback: 'http://localhost:3000/login/oauth2/code/okta' }) %> <%= include('../../../_includes/_logout_url', { returnTo: 'http://localhost:3000/' }) %> ## Configure Spring Boot Application -### Add Spring dependencies +### Add dependencies -Spring Boot provides a `spring-boot-starter-oauth2-client` starter, which provides all the Spring Security dependencies needed to add authentication to your web application. +To integrate your Spring Boot application with Auth0, include the [Okta Spring Boot Starter](https://github.com/okta/okta-spring-boot/) in your application's dependencies. :::note This guide uses [Thymeleaf](https://www.thymeleaf.org/) and the [Spring Security integration module](https://github.com/thymeleaf/thymeleaf-extras-springsecurity) for the view layer. If you are using a different view technology, the Spring Security configuration and components remain the same. @@ -36,14 +36,15 @@ If you're using Gradle, you can include these dependencies as shown below. ```groovy plugins { id 'java' - id 'org.springframework.boot' version '2.5.12' - id 'io.spring.dependency-management' version '1.0.9.RELEASE' + id 'org.springframework.boot' version '3.1.4' + id 'io.spring.dependency-management' version '1.1.3' } +implementation 'com.okta.spring:okta-spring-boot-starter:3.0.5' implementation 'org.springframework.boot:spring-boot-starter-web' -implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' -implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5' +implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6' +implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect' ``` If you are using Maven: @@ -52,11 +53,16 @@ If you are using Maven: org.springframework.boot spring-boot-starter-parent - 2.5.12 + 3.1.4 + + com.okta + okta-spring-boot-starter + 3.0.5 + org.springframework.boot spring-boot-starter-web @@ -71,64 +77,56 @@ If you are using Maven: org.thymeleaf.extras - thymeleaf-extras-springsecurity5 + thymeleaf-extras-springsecurity6 + + + nz.net.ultraq.thymeleaf + thymeleaf-layout-dialect ``` -:::note -The Spring Security 5.4.0 release will include [a fix](https://github.com/spring-projects/spring-security/pull/8357) to validate the issuer claim of the ID token. You should update to this release when available. -::: - ### Configure Spring Security -Spring Security makes it easy to configure your application for authentication with OIDC providers such as Auth0. In your application's configuration, configure the OAuth2 client and provider. The sample below uses an `application.yml` file, though you can also use properties files or any of the other [supported externalization mechanisms](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config). +The Okta Spring Boot Starter makes it easy to configure your application with Auth0. The sample below uses an `application.yml` file, though you can also use properties files or any of the other [supported externalization mechanisms](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config). -:::note -Spring Security will use the `issuer-uri` property value to retrieve all the information necessary to enable login and validation of the ID token at runtime. - -[Additional property mappings](https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2login-boot-property-mappings) are available for further customization, if required. -::: ```yaml # src/main/resources/application.yml -spring: - security: - oauth2: - client: - registration: - auth0: - client-id: ${account.clientId} - client-secret: YOUR_CLIENT_SECRET - scope: - - openid - - profile - - email - provider: - auth0: - # trailing slash is important! - issuer-uri: https://${account.namespace}/ +okta: + oauth2: + issuer: https://${account.namespace}/ + client-id: ${account.clientId} + client-secret: YOUR_CLIENT_SECRET ``` ## Add Login to Your Application -To enable user login with Auth0, create a class that will provide an instance of [SecurityFilterChain](https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/web/SecurityFilterChain.html), and add the `@EnableWebSecurity` annotation. +To enable user login with Auth0, create a class that will register a [SecurityFilterChain](https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/web/SecurityFilterChain.html), and add the `@Configuration` annotation. ```java package com.auth0.example; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; +import static org.springframework.security.config.Customizer.withDefaults; + +@Configuration @EnableWebSecurity public class SecurityConfig { @Bean - public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - return http.oauth2Login() - .and().build(); + public SecurityFilterChain configure(HttpSecurity http) throws Exception { + http + .authorizeHttpRequests(authorize -> authorize + .anyRequest().authenticated() + ) + .oauth2Login(withDefaults()); + return http.build(); } } ``` @@ -137,21 +135,22 @@ public class SecurityConfig { You can further configure the [HttpSecurity](https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/config/annotation/web/builders/HttpSecurity.html) instance to require authentication on all or certain paths. For example, to require authentication on all paths except the home page: ```java -http.authorizeRequests() - .mvcMatchers("/").permitAll() - .anyRequest().authenticated() - .and().oauth2Login(); + http + .authorizeHttpRequests(authorize -> authorize + .requestMatchers("/").permitAll() + .anyRequest().authenticated() + ); ``` ::: -Spring Security will use the client configuration you defined earlier to handle login when a user visits the `/oauth2/authorization/auth0` path of your application. You can use this to create a login link in your application. +The Okta Spring Boot Starter will use the client configuration you defined earlier to handle login when a user visits the `/oauth2/authorization/okta` path of your application. You can use this to create a login link in your application. ```html
- Log In + Log In

You are logged in!

@@ -198,128 +197,71 @@ Auth0 enables the Google social provider by default on new tenants and offers yo ## Add Logout to Your Application -Now that users can log into your application, they need [a way to log out](https://auth0.com/docs/logout/guides/logout-auth0). By default, when logout is enabled, Spring Security will log the user out of your application and clear the session. To enable successful logout of Auth0, you can extend the `SecurityContextLogoutHandler` class to redirect users to your [Auth0 logout endpoint](https://auth0.com/docs/api/authentication?javascript#logout) (`https://${account.namespace}/v2/logout`) and then immediately redirect them to your application. - -```java -package com.auth0.example; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.client.registration.ClientRegistration; -import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; -import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; -import org.springframework.stereotype.Controller; -import org.springframework.web.servlet.support.ServletUriComponentsBuilder; -import org.springframework.web.util.UriComponentsBuilder; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * Needed to perform SSO logout with Auth0. By default, Spring will clear the SecurityContext and the session. - * This controller will also log users out of Auth0 by calling the Auth0 logout endpoint. - */ -@Controller -public class LogoutHandler extends SecurityContextLogoutHandler { - - private final ClientRegistrationRepository clientRegistrationRepository; - - /** - * Create a new instance with a {@code ClientRegistrationRepository}, so that we can look up information about the - * configured provider to call the Auth0 logout endpoint. Called by the Spring framework. - * - * @param clientRegistrationRepository the {@code ClientRegistrationRepository} for this application. - */ - @Autowired - public LogoutHandler(ClientRegistrationRepository clientRegistrationRepository) { - this.clientRegistrationRepository = clientRegistrationRepository; - } +Now that users can log into your application, they need [a way to log out](https://auth0.com/docs/logout/guides/logout-auth0). By default, when logout is enabled, Spring Security will log the user out of your application and clear the session. To enable successful logout of Auth0, you can provide a `LogoutHandler` to redirect users to your [Auth0 logout endpoint](https://auth0.com/docs/api/authentication?javascript#logout) (`https://${account.namespace}/v2/logout`) and then immediately redirect them to your application. - /** - * Delegates to {@linkplain SecurityContextLogoutHandler} to log the user out of the application, and then logs - * the user out of Auth0. - * - * @param httpServletRequest the request. - * @param httpServletResponse the response. - * @param authentication the current authentication. - */ - @Override - public void logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, - Authentication authentication) { - - // Invalidate the session and clear the security context - super.logout(httpServletRequest, httpServletResponse, authentication); - - // Build the URL to log the user out of Auth0 and redirect them to the home page. - // URL will look like https://YOUR-DOMAIN/v2/logout?clientId=YOUR-CLIENT-ID&returnTo=http://localhost:3000 - String issuer = (String) getClientRegistration().getProviderDetails().getConfigurationMetadata().get("issuer"); - String clientId = getClientRegistration().getClientId(); - String returnTo = ServletUriComponentsBuilder.fromCurrentContextPath().build().toString(); - - String logoutUrl = UriComponentsBuilder - .fromHttpUrl(issuer + "v2/logout?client_id={clientId}&returnTo={returnTo}") - .encode() - .buildAndExpand(clientId, returnTo) - .toUriString(); - - try { - httpServletResponse.sendRedirect(logoutUrl); - } catch (IOException ioe) { - // Handle or log error redirecting to logout URL - } - } - - /** - * Gets the Spring ClientRegistration, which we use to get the registered client ID and issuer for building the - * {@code returnTo} query parameter when calling the Auth0 logout API. - * - * @return the {@code ClientRegistration} for this application. - */ - private ClientRegistration getClientRegistration() { - return this.clientRegistrationRepository.findByRegistrationId("auth0"); - } -} -``` - -Next, you need to update your implementation of `SecurityFilterChain` to register your logout handler and specify the request path that should trigger logout (`/logout` in the example below). +In the `SecurityConfig` class, provide a `LogoutHandler` that redirects to the Auth0 logout endpoint, and configure the `HttpSecurity` to add the logout handler: ```java package com.auth0.example; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.authentication.logout.LogoutHandler; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + +import java.io.IOException; +import static org.springframework.security.config.Customizer.withDefaults; + +@Configuration @EnableWebSecurity public class SecurityConfig { - private final LogoutHandler logoutHandler; + @Value("<%= "${okta.oauth2.issuer}" %>") + private String issuer; + @Value("<%= "${okta.oauth2.client-id}" %>") + private String clientId; - public SecurityConfig(LogoutHandler logoutHandler) { - this.logoutHandler = logoutHandler; + @Bean + public SecurityFilterChain configure(HttpSecurity http) throws Exception { + http + .authorizeHttpRequests(authorize -> authorize + .requestMatchers("/", "/images/**").permitAll() + .anyRequest().authenticated() + ) + .oauth2Login(withDefaults()) + + // configure logout with Auth0 + .logout(logout -> logout + .addLogoutHandler(logoutHandler())); + return http.build(); } - @Bean - public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - return http - .oauth2Login() - .and().logout() - .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) - .addLogoutHandler(logoutHandler) - .and().build(); + private LogoutHandler logoutHandler() { + return (request, response, authentication) -> { + try { + String baseUrl = ServletUriComponentsBuilder.fromCurrentContextPath().build().toUriString(); + response.sendRedirect(issuer + "v2/logout?client_id=" + clientId + "&returnTo=" + baseUrl); + } catch (IOException e) { + throw new RuntimeException(e); + } + }; } } ``` -You can then update your view to add a logout link for authenticated users. +You can then update your view to POST to the `/logout` endpoint (Spring Security provides this by default) to enable users to log out. ```html

You are logged in!

- Log Out +
+
``` diff --git a/articles/quickstart/webapp/java-spring-boot/files/application.md b/articles/quickstart/webapp/java-spring-boot/files/application.md index e59bd58b4c..093b036734 100644 --- a/articles/quickstart/webapp/java-spring-boot/files/application.md +++ b/articles/quickstart/webapp/java-spring-boot/files/application.md @@ -3,20 +3,9 @@ name: application.yml language: yaml --- ```yaml -spring: - security: - oauth2: - client: - registration: - auth0: - client-id: ${account.clientId} - client-secret: YOUR_CLIENT_SECRET - scope: - - openid - - profile - - email - provider: - auth0: - # trailing slash is important! - issuer-uri: https://${account.namespace}/ +okta: + oauth2: + issuer: https://${account.namespace}/ + client-id: ${account.clientId} + client-secret: YOUR_CLIENT_SECRET ``` \ No newline at end of file diff --git a/articles/quickstart/webapp/java-spring-boot/files/index.md b/articles/quickstart/webapp/java-spring-boot/files/index.md index 55ac64397b..453bffc798 100644 --- a/articles/quickstart/webapp/java-spring-boot/files/index.md +++ b/articles/quickstart/webapp/java-spring-boot/files/index.md @@ -7,14 +7,16 @@ language: html
- Log In + Log In

You are logged in!

" th:attr="<%= "alt=${profile.get('name')}" %>"/>

">

">

- Log Out +
+
diff --git a/articles/quickstart/webapp/java-spring-boot/files/logout-handler.md b/articles/quickstart/webapp/java-spring-boot/files/logout-handler.md deleted file mode 100644 index 2d13f39567..0000000000 --- a/articles/quickstart/webapp/java-spring-boot/files/logout-handler.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -name: LogoutHandler.java -language: java ---- -```java -package com.auth0.example; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.client.registration.ClientRegistration; -import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; -import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; -import org.springframework.stereotype.Controller; -import org.springframework.web.servlet.support.ServletUriComponentsBuilder; -import org.springframework.web.util.UriComponentsBuilder; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * Needed to perform SSO logout with Auth0. By default, Spring will clear the SecurityContext and the session. - * This controller will also log users out of Auth0 by calling the Auth0 logout endpoint. - */ -@Controller -public class LogoutHandler extends SecurityContextLogoutHandler { - - private final ClientRegistrationRepository clientRegistrationRepository; - - /** - * Create a new instance with a {@code ClientRegistrationRepository}, so that we can look up information about the - * configured provider to call the Auth0 logout endpoint. Called by the Spring framework. - * - * @param clientRegistrationRepository the {@code ClientRegistrationRepository} for this application. - */ - @Autowired - public LogoutHandler(ClientRegistrationRepository clientRegistrationRepository) { - this.clientRegistrationRepository = clientRegistrationRepository; - } - - /** - * Delegates to {@linkplain SecurityContextLogoutHandler} to log the user out of the application, and then logs - * the user out of Auth0. - * - * @param httpServletRequest the request. - * @param httpServletResponse the response. - * @param authentication the current authentication. - */ - @Override - public void logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, - Authentication authentication) { - - // Invalidate the session and clear the security context - super.logout(httpServletRequest, httpServletResponse, authentication); - - // Build the URL to log the user out of Auth0 and redirect them to the home page. - // URL will look like https://YOUR-DOMAIN/v2/logout?clientId=YOUR-CLIENT-ID&returnTo=http://localhost:3000 - String issuer = (String) getClientRegistration().getProviderDetails().getConfigurationMetadata().get("issuer"); - String clientId = getClientRegistration().getClientId(); - String returnTo = ServletUriComponentsBuilder.fromCurrentContextPath().build().toString(); - - String logoutUrl = UriComponentsBuilder - .fromHttpUrl(issuer + "v2/logout?client_id={clientId}&returnTo={returnTo}") - .encode() - .buildAndExpand(clientId, returnTo) - .toUriString(); - - try { - httpServletResponse.sendRedirect(logoutUrl); - } catch (IOException ioe) { - // Handle or log error redirecting to logout URL - } - } - - /** - * Gets the Spring ClientRegistration, which we use to get the registered client ID and issuer for building the - * {@code returnTo} query parameter when calling the Auth0 logout API. - * - * @return the {@code ClientRegistration} for this application. - */ - private ClientRegistration getClientRegistration() { - return this.clientRegistrationRepository.findByRegistrationId("auth0"); - } -} -``` \ No newline at end of file diff --git a/articles/quickstart/webapp/java-spring-boot/files/security-config-logout.md b/articles/quickstart/webapp/java-spring-boot/files/security-config-logout.md index f061b1eacf..2b60bcd070 100644 --- a/articles/quickstart/webapp/java-spring-boot/files/security-config-logout.md +++ b/articles/quickstart/webapp/java-spring-boot/files/security-config-logout.md @@ -5,29 +5,51 @@ language: java ```java package com.auth0.example; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.authentication.logout.LogoutHandler; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; +import java.io.IOException; + +import static org.springframework.security.config.Customizer.withDefaults; + +@Configuration @EnableWebSecurity public class SecurityConfig { - private final LogoutHandler logoutHandler; + @Value("<%= "${okta.oauth2.issuer}" %>") + private String issuer; + @Value("<%= "${okta.oauth2.client-id}" %>") + private String clientId; - public SecurityConfig(LogoutHandler logoutHandler) { - this.logoutHandler = logoutHandler; + @Bean + public SecurityFilterChain configure(HttpSecurity http) throws Exception { + http + .authorizeHttpRequests(authorize -> authorize + .requestMatchers("/", "/images/**").permitAll() + .anyRequest().authenticated() + ) + .oauth2Login(withDefaults()) + .logout(logout -> logout + .addLogoutHandler(logoutHandler())); + return http.build(); } - @Bean - public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - return http - .oauth2Login() - .and().logout() - .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) - .addLogoutHandler(logoutHandler) - .and().build(); + private LogoutHandler logoutHandler() { + return (request, response, authentication) -> { + try { + String baseUrl = ServletUriComponentsBuilder.fromCurrentContextPath().build().toUriString(); + response.sendRedirect(issuer + "v2/logout?client_id=" + clientId + "&returnTo=" + baseUrl); + } catch (IOException e) { + throw new RuntimeException(e); + } + }; } } + ``` \ No newline at end of file diff --git a/articles/quickstart/webapp/java-spring-boot/files/security-config.md b/articles/quickstart/webapp/java-spring-boot/files/security-config.md index fedd79774a..6c68d3b916 100644 --- a/articles/quickstart/webapp/java-spring-boot/files/security-config.md +++ b/articles/quickstart/webapp/java-spring-boot/files/security-config.md @@ -6,17 +6,25 @@ language: java package com.auth0.example; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; +import static org.springframework.security.config.Customizer.withDefaults; + +@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - return http.oauth2Login() - .and().build(); + http + .authorizeHttpRequests(authorize -> authorize + .anyRequest().authenticated() + ) + .oauth2Login(withDefaults()); + return http.build(); } } ``` \ No newline at end of file diff --git a/articles/quickstart/webapp/java-spring-boot/index.yml b/articles/quickstart/webapp/java-spring-boot/index.yml index 8d84684b90..7674acadc2 100644 --- a/articles/quickstart/webapp/java-spring-boot/index.yml +++ b/articles/quickstart/webapp/java-spring-boot/index.yml @@ -21,13 +21,16 @@ articles: show_steps: true hidden_articles: - "interactive" +sdk: + name: Okta Spring Boot Starter + url: https://github.com/okta/okta-spring-boot/ + logo: spring github: org: auth0-samples repo: auth0-spring-boot-login-samples branch: master requirements: - - Java 8 - - Gradle 6 or Maven 3 + - Java 17 next_steps: - path: 01-login list: diff --git a/articles/quickstart/webapp/java-spring-boot/interactive.md b/articles/quickstart/webapp/java-spring-boot/interactive.md index 087a9f5674..cbf7facf03 100644 --- a/articles/quickstart/webapp/java-spring-boot/interactive.md +++ b/articles/quickstart/webapp/java-spring-boot/interactive.md @@ -1,13 +1,12 @@ --- title: Add login to your Spring Webapp -description: Spring Boot and Spring Security support OIDC natively, enabling you to add authentication to your application without the need for any additional libraries. This guide demonstrates how to integrate Auth0 with any new or existing Spring Boot 2 web application. +description: The Okta Spring Boot Starter makes it easy to add login to your Spring Boot application. interactive: true files: - files/application - files/security-config - files/index - files/home-controller - - files/logout-handler - files/security-config-logout github: path: mvc-login @@ -20,7 +19,7 @@ This tutorial uses [Spring MVC](https://docs.spring.io/spring/docs/current/sprin ::: <%= include('../../_includes/_configure_auth0_interactive', { - callback: 'http://localhost:3000/login/oauth2/code/auth0', + callback: 'http://localhost:3000/login/oauth2/code/okta', returnTo: 'http://localhost:3000' }) %> @@ -28,7 +27,7 @@ This tutorial uses [Spring MVC](https://docs.spring.io/spring/docs/current/sprin ### Add Spring dependencies -Spring Boot provides a `spring-boot-starter-oauth2-client` starter, which provides all the Spring Security dependencies needed to add authentication to your web application. +To integrate your Spring Boot application with Auth0, include the [Okta Spring Boot Starter](https://github.com/okta/okta-spring-boot/) in your application's dependencies. :::note This guide uses [Thymeleaf](https://www.thymeleaf.org/) and the [Spring Security integration module](https://github.com/thymeleaf/thymeleaf-extras-springsecurity) for the view layer. If you are using a different view technology, the Spring Security configuration and components remain the same. @@ -39,16 +38,15 @@ If you're using Gradle, you can include these dependencies as shown below. ```groovy plugins { id 'java' - id 'org.springframework.boot' version '2.5.12' - id 'io.spring.dependency-management' version '1.0.9.RELEASE' + id 'org.springframework.boot' version '3.1.4' + id 'io.spring.dependency-management' version '1.1.3' } -dependencies { - implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' - implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' - implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5' -} +implementation 'com.okta.spring:okta-spring-boot-starter:3.0.5' +implementation 'org.springframework.boot:spring-boot-starter-web' +implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' +implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6' +implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect' ``` If you are using Maven: @@ -57,11 +55,16 @@ If you are using Maven: org.springframework.boot spring-boot-starter-parent - 2.5.12 + 3.1.4 + + com.okta + okta-spring-boot-starter + 3.0.5 + org.springframework.boot spring-boot-starter-web @@ -76,45 +79,49 @@ If you are using Maven: org.thymeleaf.extras - thymeleaf-extras-springsecurity5 + thymeleaf-extras-springsecurity6 + + + nz.net.ultraq.thymeleaf + thymeleaf-layout-dialect ``` -:::note -The Spring Security 5.4.0 release includes [a fix](https://github.com/spring-projects/spring-security/pull/8357) to validate the ID token issuer claim. Upgrade to 5.4.0 or higher when possible. -::: +## Configure Spring Security {{{ data-action=code data-code="application.yml#1:11" }}} -## Configure Spring Security {{{ data-action=code data-code="application.yml#1:16" }}} +The Okta Spring Boot Starter makes it easy to configure your application with Auth0. The sample below uses an `application.yml` file, though you can also use properties files or any of the other [supported externalization mechanisms](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config). -Spring Security makes it easy to configure your application for authentication with OIDC providers such as Auth0. In your application's configuration, configure the OAuth2 client and provider. The sample to the right shows an `application.yml` file, though you can also use properties files or any of the other [supported externalization mechanisms](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config). -:::note -Spring Security uses the `issuer-uri` property value to retrieve the information necessary to enable login and ID token validation at runtime. - -If you need more property mappings, [review the Spring documentation](https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2login-boot-property-mappings) for further customization. -::: +```yaml +# src/main/resources/application.yml +okta: + oauth2: + issuer: https://${account.namespace}/ + client-id: ${account.clientId} + client-secret: YOUR_CLIENT_SECRET +``` ## Add login to your application {{{ data-action=code data-code="SecurityConfig.java" }}} -To enable user login with Auth0, create a class that will provide an instance of [SecurityFilterChain](https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/web/SecurityFilterChain.html), and add the `@EnableWebSecurity` annotation. +To enable user login with Auth0, create a class that will register a [SecurityFilterChain](https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/web/SecurityFilterChain.html), and add the `@Configuration` annotation. -Later in this quickstart, you will overwrite this file with `SecurityConfigWithLogout.java` to provide extra configurations to support the logout feature. :::note You can configure the [HttpSecurity](https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/config/annotation/web/builders/HttpSecurity.html) instance to require authentication on all or certain paths. For example, to require authentication on all paths except the home page: ```java -http.authorizeRequests() - .mvcMatchers("/").permitAll() - .anyRequest().authenticated() - .and().oauth2Login(); + http + .authorizeHttpRequests(authorize -> authorize + .requestMatchers("/").permitAll() + .anyRequest().authenticated() + ); ``` ::: ## Add front page {{{ data-action=code data-code="index.html" }}} -Spring Security uses the client configuration you defined earlier to handle login when a user visits the `/oauth2/authorization/auth0` path of your application. You can use this to create a login link in your application. +The Okta Spring Boot Starter will use the client configuration you defined earlier to handle login when a user visits the `/oauth2/authorization/okta` path of your application. You can use this to create a login link in your application. This page returns the user attributes when the user authentications. You will use the `/logout` link in the template to implement the logout feature. @@ -133,7 +140,7 @@ When you click the login link, verify the application redirects you to the [Auth :::checkpoint-failure If your application did not allow login or signup: * Verify you configured the correct Callback URL -* Verify you added the login link to redirect to `/oauth2/authorization/auth0` +* Verify you added the login link to redirect to `/oauth2/authorization/okta` Still having issues? Check out our [documentation](https://auth0.com/docs) or visit our [community page](https://community.auth0.com) to get more help. @@ -147,15 +154,11 @@ Still having issues? Check out our [documentation](https://auth0.com/docs) or vi Auth0 enables the Google social provider by default on new tenants and offers you developer keys to test logging in with [social identity providers](https://auth0.com/docs/connections/identity-providers-social). However, these developer keys have some limitations that may cause your application to behave differently. For more details on what this behavior may look like and how to fix it, consult the [Test Social Connections with Auth0 Developer Keys](https://auth0.com/docs/connections/social/devkeys#limitations-of-developer-keys) document. ::: -## Add logout to your application {{{ data-action=code data-code="LogoutHandler.java" }}} - -Now that users can log into your application, they need [a way to log out](https://auth0.com/docs/logout/guides/logout-auth0). By default, Spring Security logs user out of your application and clears the session when you enable logout. To enable successful Auth0 logout, extend the `SecurityContextLogoutHandler` class to redirect users to your [Auth0 logout endpoint](https://auth0.com/docs/api/authentication?javascript#logout) (`https://${account.namespace}/v2/logout`) and then immediately redirect them to your application. - -## Update your security configuration {{{ data-action=code data-code="SecurityConfigWithLogout.java" }}} +## Add logout to your application {{{ data-action=code data-code="SecurityConfigWithLogout.java" }}} -Next, update your implementation of `SecurityFilterChain` to register your logout handler and specify the request path that should trigger logout (`/logout` in the example below). +Now that users can log into your application, they need [a way to log out](https://auth0.com/docs/logout/guides/logout-auth0). By default, when logout is enabled, Spring Security will log the user out of your application and clear the session. To enable successful logout of Auth0, you can provide a `LogoutHandler` to redirect users to your [Auth0 logout endpoint](https://auth0.com/docs/api/authentication?javascript#logout) (`https://${account.namespace}/v2/logout`) and then immediately redirect them to your application. -You can remove the `SecurityConfig.java` and replace it with `SecurityConfigWithLogout.java` or update the contents from the one file to another. +In the `SecurityConfig` class, provide a `LogoutHandler` that redirects to the Auth0 logout endpoint, and configure the `HttpSecurity` to add the logout handler ::::checkpoint @@ -166,7 +169,7 @@ When you click logout link, the application should redirect you to the address y :::checkpoint-failure If your application did not allow logout: * Verify you configured the correct logout URL -* Verify you added the logout link to redirect to `/logout` +* Verify you added the logout link to POST to `/logout` Still having issues? Check out our [documentation](https://auth0.com/docs) or visit our [community page](https://community.auth0.com) to get more help.