diff --git a/samples/java/login-auth-code/pom.xml b/samples/java/login-auth-code/pom.xml
index 6b2d646..b5400d6 100644
--- a/samples/java/login-auth-code/pom.xml
+++ b/samples/java/login-auth-code/pom.xml
@@ -7,7 +7,7 @@
org.springframework.boot
spring-boot-starter-parent
- 3.4.1
+ 4.0.6
@@ -35,8 +35,8 @@
me.paulschwarz
- spring-dotenv
- 4.0.0
+ springboot4-dotenv
+ 5.1.0
@@ -44,6 +44,13 @@
spring-boot-starter-test
test
+
+
+ org.springframework.boot
+ spring-boot-webmvc-test
+ test
+
org.springframework.security
spring-security-test
@@ -60,7 +67,7 @@
org.codehaus.mojo
keytool-maven-plugin
- 1.7
+ 2.0.2
generate-dev-keystore
diff --git a/samples/java/login-auth-code/src/test/java/com/secureauth/quickstart/ApplicationTests.java b/samples/java/login-auth-code/src/test/java/com/secureauth/quickstart/ApplicationTests.java
index ffbcbce..11bc787 100644
--- a/samples/java/login-auth-code/src/test/java/com/secureauth/quickstart/ApplicationTests.java
+++ b/samples/java/login-auth-code/src/test/java/com/secureauth/quickstart/ApplicationTests.java
@@ -6,7 +6,7 @@
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
diff --git a/samples/java/saml-sp-login/pom.xml b/samples/java/saml-sp-login/pom.xml
index 51f2a8c..a09a06c 100644
--- a/samples/java/saml-sp-login/pom.xml
+++ b/samples/java/saml-sp-login/pom.xml
@@ -7,7 +7,7 @@
org.springframework.boot
spring-boot-starter-parent
- 3.4.1
+ 4.0.6
@@ -44,8 +44,8 @@
me.paulschwarz
- spring-dotenv
- 4.0.0
+ springboot4-dotenv
+ 5.1.0
@@ -53,6 +53,13 @@
spring-boot-starter-test
test
+
+
+ org.springframework.boot
+ spring-boot-webmvc-test
+ test
+
org.springframework.security
spring-security-test
@@ -69,7 +76,7 @@
org.codehaus.mojo
keytool-maven-plugin
- 1.7
+ 2.0.2
generate-dev-keystore
diff --git a/samples/java/saml-sp-login/src/main/java/com/secureauth/quickstart/Application.java b/samples/java/saml-sp-login/src/main/java/com/secureauth/quickstart/Application.java
index 4d701b6..fdb0292 100644
--- a/samples/java/saml-sp-login/src/main/java/com/secureauth/quickstart/Application.java
+++ b/samples/java/saml-sp-login/src/main/java/com/secureauth/quickstart/Application.java
@@ -23,7 +23,7 @@
import org.springframework.security.saml2.core.Saml2ErrorCodes;
import org.springframework.security.saml2.core.Saml2ResponseValidatorResult;
import org.springframework.security.saml2.core.Saml2X509Credential;
-import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider;
+import org.springframework.security.saml2.provider.service.authentication.OpenSaml5AuthenticationProvider;
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal;
import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
@@ -101,9 +101,9 @@ static class SecurityConfig {
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
- OpenSaml4AuthenticationProvider provider = new OpenSaml4AuthenticationProvider();
- Converter defaultValidator =
- OpenSaml4AuthenticationProvider.createDefaultResponseValidator();
+ OpenSaml5AuthenticationProvider provider = new OpenSaml5AuthenticationProvider();
+ Converter defaultValidator =
+ OpenSaml5AuthenticationProvider.createDefaultResponseValidator();
provider.setResponseValidator(token -> {
Saml2ResponseValidatorResult result = defaultValidator.convert(token);
List filtered = result.getErrors().stream()
@@ -138,7 +138,7 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
}
}
final String expectedInResponseTo = assertionInResponseTo;
- return OpenSaml4AuthenticationProvider.createDefaultAssertionValidatorWithParameters(
+ return OpenSaml5AuthenticationProvider.createDefaultAssertionValidatorWithParameters(
params -> {
params.put(
org.opensaml.saml.saml2.assertion.SAML2AssertionValidationParameters.SC_CHECK_ADDRESS,
@@ -162,7 +162,9 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// requires POST + CSRF; for a quickstart we let a simple
// link work directly).
.logout(l -> l
- .logoutRequestMatcher(new org.springframework.security.web.util.matcher.AntPathRequestMatcher("/logout"))
+ // Spring Security 7 dropped AntPathRequestMatcher; PathPatternRequestMatcher
+ // is the replacement. `.matcher(path)` (no HTTP method) matches any method.
+ .logoutRequestMatcher(org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.withDefaults().matcher("/logout"))
.logoutSuccessUrl("/"))
// Disable CSRF for the demo. SAML2 ACS endpoint is already exempt by the
// framework; this just removes the requirement on /logout. Production apps
diff --git a/samples/java/saml-sp-login/src/test/java/com/secureauth/quickstart/ApplicationTests.java b/samples/java/saml-sp-login/src/test/java/com/secureauth/quickstart/ApplicationTests.java
index c90e231..7e7d6bc 100644
--- a/samples/java/saml-sp-login/src/test/java/com/secureauth/quickstart/ApplicationTests.java
+++ b/samples/java/saml-sp-login/src/test/java/com/secureauth/quickstart/ApplicationTests.java
@@ -10,7 +10,7 @@
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.security.saml2.provider.service.authentication.DefaultSaml2AuthenticatedPrincipal;
diff --git a/samples/java/token-refresh/pom.xml b/samples/java/token-refresh/pom.xml
index 51050fc..a9c6ab1 100644
--- a/samples/java/token-refresh/pom.xml
+++ b/samples/java/token-refresh/pom.xml
@@ -7,7 +7,7 @@
org.springframework.boot
spring-boot-starter-parent
- 3.4.1
+ 4.0.6
@@ -35,8 +35,8 @@
me.paulschwarz
- spring-dotenv
- 4.0.0
+ springboot4-dotenv
+ 5.1.0
@@ -44,6 +44,13 @@
spring-boot-starter-test
test
+
+
+ org.springframework.boot
+ spring-boot-webmvc-test
+ test
+
org.springframework.security
spring-security-test
@@ -60,7 +67,7 @@
org.codehaus.mojo
keytool-maven-plugin
- 1.7
+ 2.0.2
generate-dev-keystore
diff --git a/samples/java/token-refresh/src/test/java/com/secureauth/quickstart/ApplicationTests.java b/samples/java/token-refresh/src/test/java/com/secureauth/quickstart/ApplicationTests.java
index 1966555..30bb700 100644
--- a/samples/java/token-refresh/src/test/java/com/secureauth/quickstart/ApplicationTests.java
+++ b/samples/java/token-refresh/src/test/java/com/secureauth/quickstart/ApplicationTests.java
@@ -10,7 +10,7 @@
import org.mockito.ArgumentMatchers;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
diff --git a/snippets.json b/snippets.json
index 2ba8a79..fb5c9e6 100644
--- a/snippets.json
+++ b/snippets.json
@@ -617,7 +617,7 @@
],
"framework": "java",
"lib": "spring-boot-starter-oauth2-client",
- "lib_version": "3.4.1",
+ "lib_version": "4.0.6",
"docs_url": "https://docs.spring.io/spring-security/reference/servlet/oauth2/login/index.html",
"install": "",
"repo_path": "samples/java/login-auth-code",
@@ -775,7 +775,7 @@
],
"framework": "java",
"lib": "spring-boot-starter-oauth2-client",
- "lib_version": "3.4.1",
+ "lib_version": "4.0.6",
"docs_url": "https://docs.spring.io/spring-security/reference/servlet/oauth2/login/index.html",
"install": "",
"repo_path": "samples/java/token-refresh",
@@ -885,10 +885,10 @@
{
"step": 2,
"description": "Enable saml2Login and accept unsolicited (IdP-initiated) responses",
- "code": " @Configuration\n static class SecurityConfig {\n\n @Bean\n SecurityFilterChain filterChain(HttpSecurity http) throws Exception {\n OpenSaml4AuthenticationProvider provider = new OpenSaml4AuthenticationProvider();\n Converter defaultValidator =\n OpenSaml4AuthenticationProvider.createDefaultResponseValidator();\n provider.setResponseValidator(token -> {\n Saml2ResponseValidatorResult result = defaultValidator.convert(token);\n List filtered = result.getErrors().stream()\n .filter(e -> !Saml2ErrorCodes.INVALID_IN_RESPONSE_TO.equals(e.getErrorCode()))\n .toList();\n return filtered.isEmpty()\n ? Saml2ResponseValidatorResult.success()\n : Saml2ResponseValidatorResult.failure(filtered);\n });\n // CIAM's SubjectConfirmation interacts badly with Spring Security's strict bearer\n // validator in two ways:\n // 1. The Address attribute is host:port form (e.g. \"[::1]:57370\") rather than\n // IP-only. Disabled via SC_CHECK_ADDRESS=false.\n // 2. The session-stored AuthnRequest used to validate InResponseTo is unreliable\n // across the cross-site POST from CIAM (cookie/session loss). Worked around by\n // feeding the assertion's own InResponseTo back as the expected value, which\n // makes the comparison pass vacuously.\n // Production-grade SPs should fix the upstream Address format and rely on session\n // state for InResponseTo. For a CIAM quickstart, this is acceptable: response-level\n // signature validation (against the IdP signing cert) still runs at the response\n // validator above, so we still confirm the assertion came from CIAM.\n provider.setAssertionValidator(assertionToken -> {\n String assertionInResponseTo = null;\n var subject = assertionToken.getAssertion().getSubject();\n if (subject != null) {\n for (var sc : subject.getSubjectConfirmations()) {\n var data = sc.getSubjectConfirmationData();\n if (data != null && data.getInResponseTo() != null) {\n assertionInResponseTo = data.getInResponseTo();\n break;\n }\n }\n }\n final String expectedInResponseTo = assertionInResponseTo;\n return OpenSaml4AuthenticationProvider.createDefaultAssertionValidatorWithParameters(\n params -> {\n params.put(\n org.opensaml.saml.saml2.assertion.SAML2AssertionValidationParameters.SC_CHECK_ADDRESS,\n Boolean.FALSE);\n if (expectedInResponseTo != null) {\n params.put(\n org.opensaml.saml.saml2.assertion.SAML2AssertionValidationParameters.SC_VALID_IN_RESPONSE_TO,\n expectedInResponseTo);\n }\n })\n .convert(assertionToken);\n });\n return http\n .authorizeHttpRequests(auth -> auth\n .requestMatchers(\"/\").permitAll()\n .anyRequest().authenticated())\n .saml2Login(saml -> saml\n .authenticationManager(new ProviderManager(provider))\n .defaultSuccessUrl(\"/\", true))\n // Accept GET on /logout (Spring Security 6.4's default confirmation page\n // requires POST + CSRF; for a quickstart we let a simple \n // link work directly).\n .logout(l -> l\n .logoutRequestMatcher(new org.springframework.security.web.util.matcher.AntPathRequestMatcher(\"/logout\"))\n .logoutSuccessUrl(\"/\"))\n // Disable CSRF for the demo. SAML2 ACS endpoint is already exempt by the\n // framework; this just removes the requirement on /logout. Production apps\n // with state-changing endpoints should re-enable CSRF.\n .csrf(c -> c.disable())\n .build();\n }\n }",
+ "code": " @Configuration\n static class SecurityConfig {\n\n @Bean\n SecurityFilterChain filterChain(HttpSecurity http) throws Exception {\n OpenSaml5AuthenticationProvider provider = new OpenSaml5AuthenticationProvider();\n Converter defaultValidator =\n OpenSaml5AuthenticationProvider.createDefaultResponseValidator();\n provider.setResponseValidator(token -> {\n Saml2ResponseValidatorResult result = defaultValidator.convert(token);\n List filtered = result.getErrors().stream()\n .filter(e -> !Saml2ErrorCodes.INVALID_IN_RESPONSE_TO.equals(e.getErrorCode()))\n .toList();\n return filtered.isEmpty()\n ? Saml2ResponseValidatorResult.success()\n : Saml2ResponseValidatorResult.failure(filtered);\n });\n // CIAM's SubjectConfirmation interacts badly with Spring Security's strict bearer\n // validator in two ways:\n // 1. The Address attribute is host:port form (e.g. \"[::1]:57370\") rather than\n // IP-only. Disabled via SC_CHECK_ADDRESS=false.\n // 2. The session-stored AuthnRequest used to validate InResponseTo is unreliable\n // across the cross-site POST from CIAM (cookie/session loss). Worked around by\n // feeding the assertion's own InResponseTo back as the expected value, which\n // makes the comparison pass vacuously.\n // Production-grade SPs should fix the upstream Address format and rely on session\n // state for InResponseTo. For a CIAM quickstart, this is acceptable: response-level\n // signature validation (against the IdP signing cert) still runs at the response\n // validator above, so we still confirm the assertion came from CIAM.\n provider.setAssertionValidator(assertionToken -> {\n String assertionInResponseTo = null;\n var subject = assertionToken.getAssertion().getSubject();\n if (subject != null) {\n for (var sc : subject.getSubjectConfirmations()) {\n var data = sc.getSubjectConfirmationData();\n if (data != null && data.getInResponseTo() != null) {\n assertionInResponseTo = data.getInResponseTo();\n break;\n }\n }\n }\n final String expectedInResponseTo = assertionInResponseTo;\n return OpenSaml5AuthenticationProvider.createDefaultAssertionValidatorWithParameters(\n params -> {\n params.put(\n org.opensaml.saml.saml2.assertion.SAML2AssertionValidationParameters.SC_CHECK_ADDRESS,\n Boolean.FALSE);\n if (expectedInResponseTo != null) {\n params.put(\n org.opensaml.saml.saml2.assertion.SAML2AssertionValidationParameters.SC_VALID_IN_RESPONSE_TO,\n expectedInResponseTo);\n }\n })\n .convert(assertionToken);\n });\n return http\n .authorizeHttpRequests(auth -> auth\n .requestMatchers(\"/\").permitAll()\n .anyRequest().authenticated())\n .saml2Login(saml -> saml\n .authenticationManager(new ProviderManager(provider))\n .defaultSuccessUrl(\"/\", true))\n // Accept GET on /logout (Spring Security 6.4's default confirmation page\n // requires POST + CSRF; for a quickstart we let a simple \n // link work directly).\n .logout(l -> l\n // Spring Security 7 dropped AntPathRequestMatcher; PathPatternRequestMatcher\n // is the replacement. `.matcher(path)` (no HTTP method) matches any method.\n .logoutRequestMatcher(org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.withDefaults().matcher(\"/logout\"))\n .logoutSuccessUrl(\"/\"))\n // Disable CSRF for the demo. SAML2 ACS endpoint is already exempt by the\n // framework; this just removes the requirement on /logout. Production apps\n // with state-changing endpoints should re-enable CSRF.\n .csrf(c -> c.disable())\n .build();\n }\n }",
"file": "src/main/java/com/secureauth/quickstart/Application.java",
"lang": "java",
- "lines": "97-173"
+ "lines": "97-175"
},
{
"step": 3,
@@ -896,12 +896,12 @@
"code": " @Controller\n static class HomeController {\n\n @GetMapping(\"/\")\n @ResponseBody\n String home(@AuthenticationPrincipal Saml2AuthenticatedPrincipal user) {\n if (user == null) {\n return \"\"\"\n \n SecureAuth Java SAML Demo\n \n SecureAuth Java SAML Demo
\n Sign in
\n \n \"\"\";\n }\n return \"\"\"\n \n SecureAuth Java SAML Demo\n \n SecureAuth Java SAML Demo
\n Welcome, %s
\n Sign out
\n \n \"\"\".formatted(esc(user.getName()));\n }\n\n private static String esc(String s) {\n if (s == null) return \"\";\n return s\n .replace(\"&\", \"&\")\n .replace(\"<\", \"<\")\n .replace(\">\", \">\")\n .replace(\"\\\"\", \""\")\n .replace(\"'\", \"'\");\n }\n }",
"file": "src/main/java/com/secureauth/quickstart/Application.java",
"lang": "java",
- "lines": "176-214"
+ "lines": "178-216"
}
],
"framework": "java",
"lib": "spring-security-saml2-service-provider",
- "lib_version": "3.4.1",
+ "lib_version": "4.0.6",
"docs_url": "https://docs.spring.io/spring-security/reference/servlet/saml2/login/index.html",
"install": "",
"repo_path": "samples/java/saml-sp-login",