From cba0da27c4fcfaa9dde2f00380787271171042ff Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 29 Dec 2025 16:43:13 +0000 Subject: [PATCH 1/2] Update dependency org.springframework:spring-web to v7 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 37ae5b8..b7e2ae4 100644 --- a/pom.xml +++ b/pom.xml @@ -64,7 +64,7 @@ org.springframework spring-web - 5.1.1.RELEASE + 7.0.2 com.fasterxml.jackson.core From fcf465f9a912b65a35dcf151efc40acbf45fd14a Mon Sep 17 00:00:00 2001 From: CodeLogicAI Date: Mon, 29 Dec 2025 22:00:13 +0000 Subject: [PATCH 2/2] Upgrade Spring Framework from 5.1.1.RELEASE to 7.0.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Major changes implemented: - Updated Java version from 1.8 to 17 (required for Spring 7.x) - Migrated from javax.servlet to jakarta.servlet APIs - Replaced deprecated Spring Security OAuth2 classes with modern equivalents: - OAuth2RestOperations/OAuth2RestTemplate → OAuth2AuthorizedClientManager - AuthorizationCodeResourceDetails → ClientRegistration - OAuth2AccessToken moved from common to core package - Updated Jackson from 2.10.3 to 2.18.2 for compatibility - Fixed ResponseEntity.getStatusCodeValue() → getStatusCode().value() - Modernized OAuth2 client configuration approach 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4 --- pom.xml | 30 +++++++---- .../security/FusionAuthUserDetails.java | 2 +- ...penIDAuthorizationCodeResourceDetails.java | 23 -------- .../OpenIDConnectClientRegistration.java | 38 ++++++++++++++ .../security/OpenIDConnectFilter.java | 52 ++++++++++++------- 5 files changed, 92 insertions(+), 53 deletions(-) delete mode 100644 src/main/java/io/fusionauth/security/OpenIDAuthorizationCodeResourceDetails.java create mode 100644 src/main/java/io/fusionauth/security/OpenIDConnectClientRegistration.java diff --git a/pom.xml b/pom.xml index b7e2ae4..3390132 100644 --- a/pom.xml +++ b/pom.xml @@ -50,15 +50,27 @@ - 1.8 - 1.8 + 17 + 17 - org.springframework.security.oauth - spring-security-oauth2 - 2.3.5.RELEASE + org.springframework.security + spring-security-oauth2-client + 7.0.2 + + + + org.springframework.security + spring-security-core + 7.0.2 + + + + org.springframework.security + spring-security-web + 7.0.2 @@ -69,12 +81,12 @@ com.fasterxml.jackson.core jackson-databind - 2.10.3 + 2.18.2 - javax.servlet - javax.servlet-api - 3.1.0 + jakarta.servlet + jakarta.servlet-api + 6.0.0 diff --git a/src/main/java/io/fusionauth/security/FusionAuthUserDetails.java b/src/main/java/io/fusionauth/security/FusionAuthUserDetails.java index 8789461..fcb3469 100644 --- a/src/main/java/io/fusionauth/security/FusionAuthUserDetails.java +++ b/src/main/java/io/fusionauth/security/FusionAuthUserDetails.java @@ -8,7 +8,7 @@ import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.core.OAuth2AccessToken; /** * @author Tyler Scott diff --git a/src/main/java/io/fusionauth/security/OpenIDAuthorizationCodeResourceDetails.java b/src/main/java/io/fusionauth/security/OpenIDAuthorizationCodeResourceDetails.java deleted file mode 100644 index 9ef6e5b..0000000 --- a/src/main/java/io/fusionauth/security/OpenIDAuthorizationCodeResourceDetails.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.fusionauth.security; - -import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; - -/** - * Extend the {@link AuthorizationCodeResourceDetails} to add the OpenID Connect UserInfo endpoint as described - * in section 5.3 of OpenID Connect Core 1.0. - * - * @author Tyler Scott - * @see https://openid.net/specs/openid-connect-core-1_0.html#UserInfo - */ -public class OpenIDAuthorizationCodeResourceDetails extends AuthorizationCodeResourceDetails { - private String userInfoUri; - - public String getUserInfoUri() { - return userInfoUri; - } - - public void settUserInfoUri(String userInfoUri) { - this.userInfoUri = userInfoUri; - } - -} diff --git a/src/main/java/io/fusionauth/security/OpenIDConnectClientRegistration.java b/src/main/java/io/fusionauth/security/OpenIDConnectClientRegistration.java new file mode 100644 index 0000000..e240d00 --- /dev/null +++ b/src/main/java/io/fusionauth/security/OpenIDConnectClientRegistration.java @@ -0,0 +1,38 @@ +package io.fusionauth.security; + +import org.springframework.security.oauth2.client.registration.ClientRegistration; + +/** + * Configuration class for OpenID Connect that holds client registration details + * and the OpenID Connect UserInfo endpoint as described in section 5.3 + * of OpenID Connect Core 1.0. + * + * @author Tyler Scott + * @see https://openid.net/specs/openid-connect-core-1_0.html#UserInfo + */ +public class OpenIDConnectClientRegistration { + private ClientRegistration clientRegistration; + private String userInfoUri; + + public OpenIDConnectClientRegistration(ClientRegistration clientRegistration, String userInfoUri) { + this.clientRegistration = clientRegistration; + this.userInfoUri = userInfoUri; + } + + public ClientRegistration getClientRegistration() { + return clientRegistration; + } + + public void setClientRegistration(ClientRegistration clientRegistration) { + this.clientRegistration = clientRegistration; + } + + public String getUserInfoUri() { + return userInfoUri; + } + + public void setUserInfoUri(String userInfoUri) { + this.userInfoUri = userInfoUri; + } + +} diff --git a/src/main/java/io/fusionauth/security/OpenIDConnectFilter.java b/src/main/java/io/fusionauth/security/OpenIDConnectFilter.java index dc6b733..496f447 100644 --- a/src/main/java/io/fusionauth/security/OpenIDConnectFilter.java +++ b/src/main/java/io/fusionauth/security/OpenIDConnectFilter.java @@ -1,7 +1,7 @@ package io.fusionauth.security; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import com.fasterxml.jackson.databind.JsonNode; @@ -17,10 +17,11 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; -import org.springframework.security.oauth2.client.OAuth2RestOperations; -import org.springframework.security.oauth2.client.OAuth2RestTemplate; -import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager; +import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest; +import org.springframework.security.oauth2.core.OAuth2AccessToken; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; import org.springframework.web.client.RestTemplate; @@ -29,47 +30,58 @@ */ public class OpenIDConnectFilter extends AbstractAuthenticationProcessingFilter { @Autowired - private OpenIDAuthorizationCodeResourceDetails openIDResourceDetails; + private OpenIDConnectClientRegistration openIDClientRegistration; - private OAuth2RestOperations restTemplate; + private OAuth2AuthorizedClientManager authorizedClientManager; - public OpenIDConnectFilter(String defaultFilterProcessesUrl) { + public OpenIDConnectFilter(String defaultFilterProcessesUrl, OAuth2AuthorizedClientManager authorizedClientManager) { super(defaultFilterProcessesUrl); + this.authorizedClientManager = authorizedClientManager; setAuthenticationManager(new NoopAuthenticationManager()); } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { - OAuth2AccessToken accessToken; - try { - accessToken = restTemplate.getAccessToken(); - } catch (final OAuth2Exception e) { - throw new BadCredentialsException("Could not obtain access token", e); - } try { + // Create OAuth2AuthorizeRequest for the registered client + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(openIDClientRegistration.getClientRegistration().getRegistrationId()) + .principal("anonymous") // For client credentials or similar flows + .build(); + + // Get the authorized client using the manager + OAuth2AuthorizedClient authorizedClient = authorizedClientManager.authorize(authorizeRequest); + + if (authorizedClient == null) { + throw new BadCredentialsException("Could not authorize OAuth2 client"); + } + + OAuth2AccessToken accessToken = authorizedClient.getAccessToken(); FusionAuthUserDetails user = new FusionAuthUserDetails(getUserInfo(accessToken), accessToken); return new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities()); + } catch (OAuth2AuthenticationException e) { + throw new BadCredentialsException("Could not obtain access token", e); } catch (Exception e) { throw new BadCredentialsException("Failed to validate the token", e); } } - public void setRestTemplate(OAuth2RestTemplate restTemplate2) { - restTemplate = restTemplate2; + public void setAuthorizedClientManager(OAuth2AuthorizedClientManager authorizedClientManager) { + this.authorizedClientManager = authorizedClientManager; } private JsonNode getUserInfo(OAuth2AccessToken accessToken) throws IOException { HttpHeaders headers = new HttpHeaders(); - headers.set("Authorization", "Bearer " + accessToken.getValue()); + headers.set("Authorization", "Bearer " + accessToken.getTokenValue()); HttpEntity httpEntity = new HttpEntity<>(headers); - ResponseEntity response = new RestTemplate().exchange(openIDResourceDetails.getUserInfoUri(), HttpMethod.GET, httpEntity, String.class); + ResponseEntity response = new RestTemplate().exchange(openIDClientRegistration.getUserInfoUri(), HttpMethod.GET, httpEntity, String.class); if (response.getStatusCode() == HttpStatus.OK) { return new ObjectMapper().readTree(response.getBody()); } throw new BadCredentialsException("Failed to request user details from the UserInfo API. " + - "Status code [" + response.getStatusCodeValue() + "] Message [" + response.getBody() + "]"); + "Status code [" + response.getStatusCode().value() + "] Message [" + response.getBody() + "]"); } private static class NoopAuthenticationManager implements AuthenticationManager {