From f2805935664ee2714b5543342a85678a9fe07a25 Mon Sep 17 00:00:00 2001
From: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
Date: Thu, 3 Apr 2025 11:03:29 -0600
Subject: [PATCH] Move Preparation Steps
Closes gh-16873
---
docs/modules/ROOT/nav.adoc | 3 +
.../authentication.adoc | 0
.../authorization.adoc | 0
.../{migration => migration-7}/oauth2.adoc | 0
docs/modules/ROOT/pages/migration-7/web.adoc | 328 +++++++++++++++++
docs/modules/ROOT/pages/migration/web.adoc | 330 ------------------
6 files changed, 331 insertions(+), 330 deletions(-)
rename docs/modules/ROOT/pages/{migration => migration-7}/authentication.adoc (100%)
rename docs/modules/ROOT/pages/{migration => migration-7}/authorization.adoc (100%)
rename docs/modules/ROOT/pages/{migration => migration-7}/oauth2.adoc (100%)
delete mode 100644 docs/modules/ROOT/pages/migration/web.adoc
diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc
index 3fc74ae93d..d65fc977c0 100644
--- a/docs/modules/ROOT/nav.adoc
+++ b/docs/modules/ROOT/nav.adoc
@@ -3,8 +3,11 @@
* xref:community.adoc[Community]
* xref:whats-new.adoc[What's New]
* xref:migration-7/index.adoc[Preparing for 7.0]
+** xref:migration-7/authentication.adoc[Authentication]
+** xref:migration-7/authorization.adoc[Authorization]
** xref:migration-7/configuration.adoc[Configuration]
** xref:migration-7/ldap.adoc[LDAP]
+** xref:migration-7/oauth2.adoc[OAuth 2.0]
** xref:migration-7/web.adoc[Web]
* xref:migration/index.adoc[Migrating to 6]
* xref:getting-spring-security.adoc[Getting Spring Security]
diff --git a/docs/modules/ROOT/pages/migration/authentication.adoc b/docs/modules/ROOT/pages/migration-7/authentication.adoc
similarity index 100%
rename from docs/modules/ROOT/pages/migration/authentication.adoc
rename to docs/modules/ROOT/pages/migration-7/authentication.adoc
diff --git a/docs/modules/ROOT/pages/migration/authorization.adoc b/docs/modules/ROOT/pages/migration-7/authorization.adoc
similarity index 100%
rename from docs/modules/ROOT/pages/migration/authorization.adoc
rename to docs/modules/ROOT/pages/migration-7/authorization.adoc
diff --git a/docs/modules/ROOT/pages/migration/oauth2.adoc b/docs/modules/ROOT/pages/migration-7/oauth2.adoc
similarity index 100%
rename from docs/modules/ROOT/pages/migration/oauth2.adoc
rename to docs/modules/ROOT/pages/migration-7/oauth2.adoc
diff --git a/docs/modules/ROOT/pages/migration-7/web.adoc b/docs/modules/ROOT/pages/migration-7/web.adoc
index c3c201d5a1..aa898da4fd 100644
--- a/docs/modules/ROOT/pages/migration-7/web.adoc
+++ b/docs/modules/ROOT/pages/migration-7/web.adoc
@@ -145,3 +145,331 @@ Xml::
----
======
+[[use-path-pattern]]
+== Use PathPatternRequestMatcher by Default
+
+In Spring Security 7, `AntPathRequestMatcher` and `MvcRequestMatcher` are no longer supported and the Java DSL requires that all URIs be absolute (less any context root).
+At that time, Spring Security 7 will use `PathPatternRequestMatcher` by default.
+
+To check how prepared you are for this change, you can publish this bean:
+
+[tabs]
+======
+Java::
++
+[source,java,role="primary"]
+----
+@Bean
+PathPatternRequestMatcherBuilderFactoryBean requestMatcherBuilder() {
+ return new PathPatternRequestMatcherBuilderFactoryBean();
+}
+----
+
+Kotlin::
++
+[source,kotlin,role="secondary"]
+----
+@Bean
+fun requestMatcherBuilder(): PathPatternRequestMatcherBuilderFactoryBean {
+ return PathPatternRequestMatcherBuilderFactoryBean()
+}
+----
+
+Xml::
++
+[source,xml,role="secondary"]
+----
+
+----
+======
+
+This will tell the Spring Security DSL to use `PathPatternRequestMatcher` for all request matchers that it constructs.
+
+In the event that you are directly constructing an object (as opposed to having the DSL construct it) that has a `setRequestMatcher` method. you should also proactively specify a `PathPatternRequestMatcher` there as well.
+
+=== Migrate `exitUserUrl` and `switchUserUrl` Request Matchers in `SwitchUserFilter`
+
+`SwitchUserFilter`, constructs an `AntPathRequestMatcher` in its `setExitUserUrl` and `setSwitchUserUrl` methods.
+This will change to use `PathPatternRequestMatcher` in Spring Security 7.
+
+To prepare for this change, call `setExitUserMatcher` and `setSwithcUserMatcher` to provide this `PathPatternRequestMatcher` in advance.
+That is, change this:
+
+[tabs]
+======
+Java::
++
+[source,java,role="primary"]
+----
+SwitchUserFilter switchUser = new SwitchUserFilter();
+// ... other configuration
+switchUser.setExitUserUrl("/exit/impersonate");
+----
+
+Kotlin::
++
+[source,kotlin,role="secondary"]
+----
+val switchUser = SwitchUserFilter()
+// ... other configuration
+switchUser.setExitUserUrl("/exit/impersonate")
+----
+======
+
+to this:
+
+[tabs]
+======
+Java::
++
+[source,java,role="primary"]
+----
+SwitchUserFilter switchUser = new SwitchUserFilter();
+// ... other configuration
+switchUser.setExitUserMatcher(PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.POST, "/exit/impersonate"));
+----
+
+Kotlin::
++
+[source,kotlin,role="secondary"]
+----
+val switchUser = SwitchUserFilter()
+// ... other configuration
+switchUser.setExitUserMatcher(PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.POST, "/exit/impersonate"))
+----
+======
+
+=== Migrate `filterProcessingUrl` Request Matcher in `AbstractAuthenticationProcessingFilter` Implementations
+
+Spring Security 6 converts any processing endpoint configured through `setFilterProcessingUrl` to an `AntPathRequestMatcher`.
+In Spring Security 7, this will change to `PathPatternRequestMatcher`.
+
+If you are directly invoking `setFilterProcessingUrl` on a filter that extends `AbstractAuthenticationProcessingFilter`, like `UsernamePasswordAuthenticationFilter`, `OAuth2LoginAuthenticationFilter`, `Saml2WebSsoAuthenticationFilter`, `OneTimeTokenAuthenticationFilter`, or `WebAuthnAuthenticationFilter`, call `setRequiredAuthenticationRequestMatcher` instead to provide this `PathPatternRequestMatcher` in advance.
+
+That is, change this:
+[tabs]
+======
+Java::
++
+[source,java,role="primary"]
+----
+UsernamePasswordAuthenticationFilter usernamePassword = new UsernamePasswordAuthenticationFilter(authenticationManager);
+usernamePassword.setFilterProcessingUrl("/my/processing/url");
+----
+
+Kotlin::
++
+[source,kotlin,role="secondary"]
+----
+val usernamePassword = UsernamePasswordAuthenticationFilter(authenticationManager)
+usernamePassword.setFilterProcessingUrl("/my/processing/url")
+----
+======
+
+to this:
+
+[tabs]
+======
+Java::
++
+[source,java,role="primary"]
+----
+UsernamePasswordAuthenticationFilter usernamePassword = new UsernamePasswordAuthenticationFilter(authenticationManager);
+RequestMatcher requestMatcher = PathPatternRequestMatcher.withDefaults().matcher("/my/processing/url");
+usernamePassword.setRequest(requestMatcher);
+----
+
+Kotlin::
++
+[source,kotlin,role="secondary"]
+----
+val usernamePassword = UsernamePasswordAuthenticationFilter(authenticationManager)
+val requestMatcher = PathPatternRequestMatcher.withDefaults().matcher("/my/processing/url")
+usernamePassword.setRequest(requestMatcher)
+----
+======
+
+[NOTE]
+-----
+Most applications use the DSL instead of setting the `filterProcessingUrl` directly on a filter instance.
+-----
+
+=== Migrate CAS Proxy Receptor Request Matcher
+
+Spring Security 6 converts any configured `proxyReceptorUrl` to a request matcher that matches the end of the request, that is `/**/proxy/receptor`.
+In Spring Security 7, this pattern is not allowed and will change to using `PathPatternRequestMatcher`.
+Also in Spring Security 7m the URL should by absolute, excluding any context path, like so: `/proxy/receptor`.
+
+So to prepare for these change, you can use `setProxyReceptorRequestMatcher` instead of `setProxyReceptorUrl`.
+
+That is, change this:
+[tabs]
+======
+Java::
++
+[source,java,role="primary"]
+----
+casAuthentication.setProxyReceptorUrl("/proxy/receptor");
+----
+
+Kotlin::
++
+[source,kotlin,role="secondary"]
+----
+casAuthentication.setProxyReceptorUrl("/proxy/receptor")
+----
+======
+
+to this:
+
+[tabs]
+======
+Java::
++
+[source,java,role="primary"]
+----
+casAuthentication.setProxyReceptorUrl(PathPatternRequestMatcher.withDefaults().matcher("/proxy/receptor"));
+----
+
+Kotlin::
++
+[source,kotlin,role="secondary"]
+----
+casAuthentication.setProxyReceptorUrl(PathPatternRequestMatcher.withDefaults().matcher("/proxy/receptor"))
+----
+======
+
+== Include the Servlet Path Prefix in Authorization Rules
+
+For many applications <> will make no difference since most commonly all URIs listed are matched by the default servlet.
+
+However, if you have other servlets with servlet path prefixes, xref:servlet/authorization/authorize-http-requests.adoc[then these paths now need to be supplied separately].
+
+For example, if I have a Spring MVC controller with `@RequestMapping("/orders")` and my MVC application is deployed to `/mvc` (instead of the default servlet), then the URI for this endpoint is `/mvc/orders`.
+Historically, the Java DSL hasn't had a simple way to specify the servlet path prefix and Spring Security attempted to infer it.
+
+Over time, we learned that these inference would surprise developers.
+Instead of taking this responsibility away from developers, now it is simpler to specify the servlet path prefix like so:
+
+[method,java]
+----
+PathPatternRequestParser.Builder servlet = PathPatternRequestParser.servletPath("/mvc");
+http
+ .authorizeHttpRequests((authorize) -> authorize
+ .requestMatchers(servlet.pattern("/orders/**").matcher()).authenticated()
+ )
+----
+
+
+For paths that belong to the default servlet, use `PathPatternRequestParser.path()` instead:
+
+[method,java]
+----
+PathPatternRequestParser.Builder request = PathPatternRequestParser.path();
+http
+ .authorizeHttpRequests((authorize) -> authorize
+ .requestMatchers(request.pattern("/js/**").matcher()).authenticated()
+ )
+----
+
+Note that this doesn't address every kind of servlet since not all servlets have a path prefix.
+For example, expressions that match the JSP Servlet might use an ant pattern `/**/*.jsp`.
+
+There is not yet a general-purpose replacement for these, and so you are encouraged to use `RegexRequestMatcher`, like so: `regexMatcher("\\.jsp$")`.
+
+For many applications this will make no difference since most commonly all URIs listed are matched by the default servlet.
+
+[[use-redirect-to-https]]
+== Use RedirectToHttps Instead of Channel Security
+
+Years ago, HTTPS at large was enough of a performance and configuration concern that applications wanted to be able to decide which segments of an application would require HTTPS.
+
+`requires-channel` in XML and `requiresChannel` in Java Config allowed configurating an application with that in mind:
+
+[tabs]
+======
+Java::
++
+[source,java,role="primary"]
+----
+http
+ .requiresChannel((channel) -> channel
+ .requestMatchers("/secure/**").requiresSecureChannel()
+ .requestMatchers("/insecure/**").requiresInsecureChannel()
+ )
+----
+
+Kotlin::
++
+[source,kotlin,role="secondary"]
+----
+http {
+ requiresChannel {
+ secure("/secure/**")
+ seccure("/insecure/**", "REQUIRES_INSECURE_CHANNEL")
+ }
+}
+----
+
+Xml::
++
+[source,xml,role="secondary"]
+----
+
+
+
+
+----
+======
+
+Modern applications should either always require HTTPS.
+However, there are times, like when developing locally, when one would like the application to use HTTP.
+Or, you may have continuing circumstances that require part of your application to be HTTP.
+
+In any case, you can migrate to `redirect-to-https-request-matcher-ref` and `redirectToHttps` by first constructing a `RequestMatcher` that contains all circumstances where redirecting to HTTPS is needed.
+Then you can reference that request matcher like so:
+
+[tabs]
+======
+Java::
++
+[source,java,role="primary"]
+----
+http
+ .redirectToHttps((https) -> https.requestMatchers("/secure/**"))
+ // ...
+----
+
+Kotlin::
++
+[source,kotlin,role="secondary"]
+----
+var secure: RequestMatcher = PathPatternRequestMatcher.withDefaults().pattern("/secure/**")
+http {
+ redirectToHttps {
+ requestMatchers = secure
+ }
+ // ...
+}
+----
+
+Xml::
++
+[source,xml,role="secondary"]
+----
+
+
+
+
+
+
+
+
+
+----
+======
+
+[TIP]
+=====
+If you have several circumstances where HTTP is needed, consider using `OrRequestMatcher` to combine them into a single `RequestMatcher` instance.
+=====
diff --git a/docs/modules/ROOT/pages/migration/web.adoc b/docs/modules/ROOT/pages/migration/web.adoc
deleted file mode 100644
index 1ea4ecbfc7..0000000000
--- a/docs/modules/ROOT/pages/migration/web.adoc
+++ /dev/null
@@ -1,330 +0,0 @@
-= Web Migrations
-
-[[use-path-pattern]]
-== Use PathPatternRequestMatcher by Default
-
-In Spring Security 7, `AntPathRequestMatcher` and `MvcRequestMatcher` are no longer supported and the Java DSL requires that all URIs be absolute (less any context root).
-At that time, Spring Security 7 will use `PathPatternRequestMatcher` by default.
-
-To check how prepared you are for this change, you can publish this bean:
-
-[tabs]
-======
-Java::
-+
-[source,java,role="primary"]
-----
-@Bean
-PathPatternRequestMatcherBuilderFactoryBean requestMatcherBuilder() {
- return new PathPatternRequestMatcherBuilderFactoryBean();
-}
-----
-
-Kotlin::
-+
-[source,kotlin,role="secondary"]
-----
-@Bean
-fun requestMatcherBuilder(): PathPatternRequestMatcherBuilderFactoryBean {
- return PathPatternRequestMatcherBuilderFactoryBean()
-}
-----
-
-Xml::
-+
-[source,xml,role="secondary"]
-----
-
-----
-======
-
-This will tell the Spring Security DSL to use `PathPatternRequestMatcher` for all request matchers that it constructs.
-
-In the event that you are directly constructing an object (as opposed to having the DSL construct it) that has a `setRequestMatcher` method. you should also proactively specify a `PathPatternRequestMatcher` there as well.
-
-=== Migrate `exitUserUrl` and `switchUserUrl` Request Matchers in `SwitchUserFilter`
-
-`SwitchUserFilter`, constructs an `AntPathRequestMatcher` in its `setExitUserUrl` and `setSwitchUserUrl` methods.
-This will change to use `PathPatternRequestMatcher` in Spring Security 7.
-
-To prepare for this change, call `setExitUserMatcher` and `setSwithcUserMatcher` to provide this `PathPatternRequestMatcher` in advance.
-That is, change this:
-
-[tabs]
-======
-Java::
-+
-[source,java,role="primary"]
-----
-SwitchUserFilter switchUser = new SwitchUserFilter();
-// ... other configuration
-switchUser.setExitUserUrl("/exit/impersonate");
-----
-
-Kotlin::
-+
-[source,kotlin,role="secondary"]
-----
-val switchUser = SwitchUserFilter()
-// ... other configuration
-switchUser.setExitUserUrl("/exit/impersonate")
-----
-======
-
-to this:
-
-[tabs]
-======
-Java::
-+
-[source,java,role="primary"]
-----
-SwitchUserFilter switchUser = new SwitchUserFilter();
-// ... other configuration
-switchUser.setExitUserMatcher(PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.POST, "/exit/impersonate"));
-----
-
-Kotlin::
-+
-[source,kotlin,role="secondary"]
-----
-val switchUser = SwitchUserFilter()
-// ... other configuration
-switchUser.setExitUserMatcher(PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.POST, "/exit/impersonate"))
-----
-======
-
-=== Migrate `filterProcessingUrl` Request Matcher in `AbstractAuthenticationProcessingFilter` Implementations
-
-Spring Security 6 converts any processing endpoint configured through `setFilterProcessingUrl` to an `AntPathRequestMatcher`.
-In Spring Security 7, this will change to `PathPatternRequestMatcher`.
-
-If you are directly invoking `setFilterProcessingUrl` on a filter that extends `AbstractAuthenticationProcessingFilter`, like `UsernamePasswordAuthenticationFilter`, `OAuth2LoginAuthenticationFilter`, `Saml2WebSsoAuthenticationFilter`, `OneTimeTokenAuthenticationFilter`, or `WebAuthnAuthenticationFilter`, call `setRequiredAuthenticationRequestMatcher` instead to provide this `PathPatternRequestMatcher` in advance.
-
-That is, change this:
-[tabs]
-======
-Java::
-+
-[source,java,role="primary"]
-----
-UsernamePasswordAuthenticationFilter usernamePassword = new UsernamePasswordAuthenticationFilter(authenticationManager);
-usernamePassword.setFilterProcessingUrl("/my/processing/url");
-----
-
-Kotlin::
-+
-[source,kotlin,role="secondary"]
-----
-val usernamePassword = UsernamePasswordAuthenticationFilter(authenticationManager)
-usernamePassword.setFilterProcessingUrl("/my/processing/url")
-----
-======
-
-to this:
-
-[tabs]
-======
-Java::
-+
-[source,java,role="primary"]
-----
-UsernamePasswordAuthenticationFilter usernamePassword = new UsernamePasswordAuthenticationFilter(authenticationManager);
-RequestMatcher requestMatcher = PathPatternRequestMatcher.withDefaults().matcher("/my/processing/url");
-usernamePassword.setRequest(requestMatcher);
-----
-
-Kotlin::
-+
-[source,kotlin,role="secondary"]
-----
-val usernamePassword = UsernamePasswordAuthenticationFilter(authenticationManager)
-val requestMatcher = PathPatternRequestMatcher.withDefaults().matcher("/my/processing/url")
-usernamePassword.setRequest(requestMatcher)
-----
-======
-
-[NOTE]
------
-Most applications use the DSL instead of setting the `filterProcessingUrl` directly on a filter instance.
------
-
-=== Migrate CAS Proxy Receptor Request Matcher
-
-Spring Security 6 converts any configured `proxyReceptorUrl` to a request matcher that matches the end of the request, that is `/**/proxy/receptor`.
-In Spring Security 7, this pattern is not allowed and will change to using `PathPatternRequestMatcher`.
-Also in Spring Security 7m the URL should by absolute, excluding any context path, like so: `/proxy/receptor`.
-
-So to prepare for these change, you can use `setProxyReceptorRequestMatcher` instead of `setProxyReceptorUrl`.
-
-That is, change this:
-[tabs]
-======
-Java::
-+
-[source,java,role="primary"]
-----
-casAuthentication.setProxyReceptorUrl("/proxy/receptor");
-----
-
-Kotlin::
-+
-[source,kotlin,role="secondary"]
-----
-casAuthentication.setProxyReceptorUrl("/proxy/receptor")
-----
-======
-
-to this:
-
-[tabs]
-======
-Java::
-+
-[source,java,role="primary"]
-----
-casAuthentication.setProxyReceptorUrl(PathPatternRequestMatcher.withDefaults().matcher("/proxy/receptor"));
-----
-
-Kotlin::
-+
-[source,kotlin,role="secondary"]
-----
-casAuthentication.setProxyReceptorUrl(PathPatternRequestMatcher.withDefaults().matcher("/proxy/receptor"))
-----
-======
-
-== Include the Servlet Path Prefix in Authorization Rules
-
-For many applications <> will make no difference since most commonly all URIs listed are matched by the default servlet.
-
-However, if you have other servlets with servlet path prefixes, xref:servlet/authorization/authorize-http-requests.adoc[then these paths now need to be supplied separately].
-
-For example, if I have a Spring MVC controller with `@RequestMapping("/orders")` and my MVC application is deployed to `/mvc` (instead of the default servlet), then the URI for this endpoint is `/mvc/orders`.
-Historically, the Java DSL hasn't had a simple way to specify the servlet path prefix and Spring Security attempted to infer it.
-
-Over time, we learned that these inference would surprise developers.
-Instead of taking this responsibility away from developers, now it is simpler to specify the servlet path prefix like so:
-
-[method,java]
-----
-PathPatternRequestParser.Builder servlet = PathPatternRequestParser.servletPath("/mvc");
-http
- .authorizeHttpRequests((authorize) -> authorize
- .requestMatchers(servlet.pattern("/orders/**").matcher()).authenticated()
- )
-----
-
-
-For paths that belong to the default servlet, use `PathPatternRequestParser.path()` instead:
-
-[method,java]
-----
-PathPatternRequestParser.Builder request = PathPatternRequestParser.path();
-http
- .authorizeHttpRequests((authorize) -> authorize
- .requestMatchers(request.pattern("/js/**").matcher()).authenticated()
- )
-----
-
-Note that this doesn't address every kind of servlet since not all servlets have a path prefix.
-For example, expressions that match the JSP Servlet might use an ant pattern `/**/*.jsp`.
-
-There is not yet a general-purpose replacement for these, and so you are encouraged to use `RegexRequestMatcher`, like so: `regexMatcher("\\.jsp$")`.
-
-For many applications this will make no difference since most commonly all URIs listed are matched by the default servlet.
-
-[[use-redirect-to-https]]
-== Use RedirectToHttps Instead of Channel Security
-
-Years ago, HTTPS at large was enough of a performance and configuration concern that applications wanted to be able to decide which segments of an application would require HTTPS.
-
-`requires-channel` in XML and `requiresChannel` in Java Config allowed configurating an application with that in mind:
-
-[tabs]
-======
-Java::
-+
-[source,java,role="primary"]
-----
-http
- .requiresChannel((channel) -> channel
- .requestMatchers("/secure/**").requiresSecureChannel()
- .requestMatchers("/insecure/**").requiresInsecureChannel()
- )
-----
-
-Kotlin::
-+
-[source,kotlin,role="secondary"]
-----
-http {
- requiresChannel {
- secure("/secure/**")
- seccure("/insecure/**", "REQUIRES_INSECURE_CHANNEL")
- }
-}
-----
-
-Xml::
-+
-[source,xml,role="secondary"]
-----
-
-
-
-
-----
-======
-
-Modern applications should either always require HTTPS.
-However, there are times, like when developing locally, when one would like the application to use HTTP.
-Or, you may have continuing circumstances that require part of your application to be HTTP.
-
-In any case, you can migrate to `redirect-to-https-request-matcher-ref` and `redirectToHttps` by first constructing a `RequestMatcher` that contains all circumstances where redirecting to HTTPS is needed.
-Then you can reference that request matcher like so:
-
-[tabs]
-======
-Java::
-+
-[source,java,role="primary"]
-----
-http
- .redirectToHttps((https) -> https.requestMatchers("/secure/**"))
- // ...
-----
-
-Kotlin::
-+
-[source,kotlin,role="secondary"]
-----
-var secure: RequestMatcher = PathPatternRequestMatcher.withDefaults().pattern("/secure/**")
-http {
- redirectToHttps {
- requestMatchers = secure
- }
- // ...
-}
-----
-
-Xml::
-+
-[source,xml,role="secondary"]
-----
-
-
-
-
-
-
-
-
-
-----
-======
-
-[TIP]
-=====
-If you have several circumstances where HTTP is needed, consider using `OrRequestMatcher` to combine them into a single `RequestMatcher` instance.
-=====