소스 검색

Revert unnecessary commits from main

Issue gh-15016
Marcus Hert Da Coregio 1 년 전
부모
커밋
08f11f06ab
100개의 변경된 파일487개의 추가작업 그리고 12803개의 파일을 삭제
  1. 0 41
      .github/dependabot.template.yml
  2. 59 148
      .github/dependabot.yml
  3. 0 57
      .github/workflows/dependabot-auto-merge-forward.yml
  4. 1 1
      .github/workflows/release-scheduler.yml
  5. 0 36
      .github/workflows/update-dependabot.yml
  6. 1 1
      CONTRIBUTING.adoc
  7. 2 2
      README.adoc
  8. 1 21
      aspects/src/test/java/org/springframework/security/authorization/method/aspectj/PostAuthorizeAspectTests.java
  9. 1 19
      aspects/src/test/java/org/springframework/security/authorization/method/aspectj/PostFilterAspectTests.java
  10. 1 21
      aspects/src/test/java/org/springframework/security/authorization/method/aspectj/PreAuthorizeAspectTests.java
  11. 1 19
      aspects/src/test/java/org/springframework/security/authorization/method/aspectj/PreFilterAspectTests.java
  12. 1 1
      aspects/src/test/java/org/springframework/security/authorization/method/aspectj/SecuredAspectTests.java
  13. 3 15
      cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationEntryPoint.java
  14. 1 49
      cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java
  15. 0 126
      cas/src/main/java/org/springframework/security/cas/web/CasGatewayAuthenticationRedirectFilter.java
  16. 0 67
      cas/src/main/java/org/springframework/security/cas/web/CasGatewayResolverRequestMatcher.java
  17. 0 27
      cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationEntryPointTests.java
  18. 0 21
      cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationFilterTests.java
  19. 0 95
      cas/src/test/java/org/springframework/security/cas/web/CasGatewayAuthenticationRedirectFilterTests.java
  20. 0 74
      cas/src/test/java/org/springframework/security/cas/web/CasGatewayResolverRequestMatcherTests.java
  21. 2 2
      config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java
  22. 4 12
      config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/InitializeUserDetailsBeanManagerConfigurer.java
  23. 0 63
      config/src/main/java/org/springframework/security/config/annotation/method/configuration/AuthorizationProxyConfiguration.java
  24. 1 23
      config/src/main/java/org/springframework/security/config/annotation/method/configuration/DeferringObservationAuthorizationManager.java
  25. 1 23
      config/src/main/java/org/springframework/security/config/annotation/method/configuration/DeferringObservationReactiveAuthorizationManager.java
  26. 1 11
      config/src/main/java/org/springframework/security/config/annotation/method/configuration/EnableMethodSecurity.java
  27. 3 26
      config/src/main/java/org/springframework/security/config/annotation/method/configuration/Jsr250MethodSecurityConfiguration.java
  28. 0 1
      config/src/main/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityAdvisorRegistrar.java
  29. 1 2
      config/src/main/java/org/springframework/security/config/annotation/method/configuration/MethodSecuritySelector.java
  30. 47 97
      config/src/main/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfiguration.java
  31. 18 97
      config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveAuthorizationManagerMethodSecurityConfiguration.java
  32. 0 63
      config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveAuthorizationProxyConfiguration.java
  33. 1 3
      config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecuritySelector.java
  34. 3 26
      config/src/main/java/org/springframework/security/config/annotation/method/configuration/SecuredMethodSecurityConfiguration.java
  35. 1 29
      config/src/main/java/org/springframework/security/config/annotation/web/configuration/OAuth2ClientConfiguration.java
  36. 1 69
      config/src/main/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurer.java
  37. 5 3
      config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/DefaultOidcLogoutTokenValidatorFactory.java
  38. 0 413
      config/src/main/java/org/springframework/security/config/annotation/web/reactive/ReactiveOAuth2ClientConfiguration.java
  39. 96 5
      config/src/main/java/org/springframework/security/config/annotation/web/reactive/ReactiveOAuth2ClientImportSelector.java
  40. 0 9
      config/src/main/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfiguration.java
  41. 1 29
      config/src/main/java/org/springframework/security/config/http/OAuth2AuthorizedClientManagerRegistrar.java
  42. 2 7
      config/src/main/java/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParser.java
  43. 5 3
      config/src/main/java/org/springframework/security/config/web/server/DefaultOidcLogoutTokenValidatorFactory.java
  44. 12 422
      config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java
  45. 1 9
      config/src/main/kotlin/org/springframework/security/config/annotation/web/AuthorizeHttpRequestsDsl.kt
  46. 1 7
      config/src/main/kotlin/org/springframework/security/config/annotation/web/FormLoginDsl.kt
  47. 1 64
      config/src/main/kotlin/org/springframework/security/config/annotation/web/HttpSecurityDsl.kt
  48. 0 69
      config/src/main/kotlin/org/springframework/security/config/annotation/web/Saml2LogoutDsl.kt
  49. 0 53
      config/src/main/kotlin/org/springframework/security/config/annotation/web/saml2/LogoutRequestDsl.kt
  50. 0 47
      config/src/main/kotlin/org/springframework/security/config/annotation/web/saml2/LogoutResponseDsl.kt
  51. 0 26
      config/src/main/kotlin/org/springframework/security/config/annotation/web/saml2/Saml2SecurityMarker.kt
  52. 0 30
      config/src/main/kotlin/org/springframework/security/config/web/server/ServerHttpSecurityDsl.kt
  53. 0 48
      config/src/main/kotlin/org/springframework/security/config/web/server/ServerSessionConcurrencyDsl.kt
  54. 0 64
      config/src/main/kotlin/org/springframework/security/config/web/server/ServerSessionManagementDsl.kt
  55. 2 4
      config/src/main/resources/META-INF/spring.schemas
  56. 0 1349
      config/src/main/resources/org/springframework/security/config/spring-security-6.3.rnc
  57. 0 3821
      config/src/main/resources/org/springframework/security/config/spring-security-6.3.xsd
  58. 1 0
      config/src/test/java/org/springframework/security/SpringSecurityCoreVersionSerializableTests.java
  59. 0 137
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/AuthorizationProxyConfigurationTests.java
  60. 0 18
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/Authz.java
  61. 1 266
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityService.java
  62. 0 10
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityServiceConfig.java
  63. 1 92
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityServiceImpl.java
  64. 0 29
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/MyMasker.java
  65. 2 855
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfigurationTests.java
  66. 0 215
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/PrePostReactiveMethodSecurityConfigurationTests.java
  67. 9 289
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityConfigurationTests.java
  68. 0 255
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityService.java
  69. 0 91
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityServiceImpl.java
  70. 0 65
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/UserRecordWithEmailProtected.java
  71. 0 68
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/ApplicationConfig.java
  72. 0 50
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/Issue14637Tests.java
  73. 0 29
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/SecurityConfig.java
  74. 0 42
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/domain/Entry.java
  75. 0 31
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/repo/EntryRepository.java
  76. 2 88
      config/src/test/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfigurationTests.java
  77. 83 76
      config/src/test/java/org/springframework/security/config/annotation/web/configuration/OAuth2AuthorizedClientManagerConfigurationTests.java
  78. 0 51
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurerTests.java
  79. 0 589
      config/src/test/java/org/springframework/security/config/annotation/web/reactive/ReactiveOAuth2AuthorizedClientManagerConfigurationTests.java
  80. 0 175
      config/src/test/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfigurationTests.java
  81. 3 3
      config/src/test/java/org/springframework/security/config/doc/XsdDocumentedTests.java
  82. 51 72
      config/src/test/java/org/springframework/security/config/http/OAuth2AuthorizedClientManagerRegistrarTests.java
  83. 0 20
      config/src/test/java/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests.java
  84. 2 8
      config/src/test/java/org/springframework/security/config/web/server/ServerHttpSecurityTests.java
  85. 0 587
      config/src/test/java/org/springframework/security/config/web/server/SessionManagementSpecTests.java
  86. 0 37
      config/src/test/kotlin/org/springframework/security/config/annotation/web/AuthorizeHttpRequestsDslTests.kt
  87. 1 46
      config/src/test/kotlin/org/springframework/security/config/annotation/web/FormLoginDslTests.kt
  88. 0 126
      config/src/test/kotlin/org/springframework/security/config/annotation/web/Saml2LogoutDslTests.kt
  89. 0 282
      config/src/test/kotlin/org/springframework/security/config/web/server/ServerSessionManagementDslTests.kt
  90. 0 3
      config/src/test/resources/org/springframework/security/config/http/OAuth2AuthorizedClientManagerRegistrarTests-clients.xml
  91. 5 8
      config/src/test/resources/org/springframework/security/config/http/OAuth2AuthorizedClientManagerRegistrarTests-providers.xml
  92. 1 1
      config/src/test/resources/org/springframework/security/config/method-security.xml
  93. 5 5
      config/src/test/resources/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests-MultiRegistration.xml
  94. 0 58
      config/src/test/resources/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests-RelayStateResolver.xml
  95. 3 3
      config/src/test/resources/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests-SingleRegistration.xml
  96. 1 1
      core/src/main/java/org/springframework/security/access/expression/ExpressionUtils.java
  97. 3 3
      core/src/main/java/org/springframework/security/access/expression/SecurityExpressionOperations.java
  98. 29 147
      core/src/main/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyImpl.java
  99. 1 1
      core/src/main/java/org/springframework/security/access/prepost/PostAuthorize.java
  100. 1 1
      core/src/main/java/org/springframework/security/access/prepost/PreAuthorize.java

+ 0 - 41
.github/dependabot.template.yml

@@ -1,41 +0,0 @@
-version: 2
-
-registries:
-  spring-milestones:
-    type: maven-repository
-    url: https://repo.spring.io/milestone
-
-updates:
-
-  - package-ecosystem: "gradle"
-    target-branch: "main"
-    directory: "/"
-    schedule:
-      interval: "daily"
-      time: "03:00"
-      timezone: "Etc/UTC"
-    labels: [ "type: dependency-upgrade" ]
-    registries:
-      - "spring-milestones"
-    ignore:
-      - dependency-name: "com.nimbusds:nimbus-jose-jwt" # nimbus-jose-jwt gets updated when oauth2-oidc-sdk is updated to ensure consistency
-      - dependency-name: "org.python:jython" # jython updates break integration tests
-      - dependency-name: "org.apache.directory.server:*" # ApacheDS version > 1.5.5 contains break changes
-      - dependency-name: "org.junit:junit-bom"
-        update-types: [ "version-update:semver-major" ]
-      - dependency-name: "org.mockito:mockito-bom"
-        update-types: [ "version-update:semver-major" ]
-      - dependency-name: "*"
-        update-types: [ "version-update:semver-major", "version-update:semver-minor" ]
-
-  #    GitHub Actions
-
-  - package-ecosystem: github-actions
-    target-branch: "main"
-    directory: "/"
-    schedule:
-      interval: weekly
-    ignore:
-      - dependency-name: "sjohnr/*"
-      - dependency-name: "spring-io/*"
-      - dependency-name: "spring-security-release-tools/*"

+ 59 - 148
.github/dependabot.yml

@@ -1,161 +1,72 @@
 version: 2
+
 registries:
   spring-milestones:
     type: maven-repository
     url: https://repo.spring.io/milestone
+
 updates:
-  - package-ecosystem: gradle
-    target-branch: 5.8.x
-    directory: /
-    schedule:
-      interval: daily
-      time: '03:00'
-      timezone: Etc/UTC
-    labels:
-      - 'type: dependency-upgrade'
-    registries:
-      - spring-milestones
-    ignore:
-      - dependency-name: com.nimbusds:nimbus-jose-jwt
-      - dependency-name: org.python:jython
-      - dependency-name: org.apache.directory.server:*
-      - dependency-name: org.junit:junit-bom
-        update-types:
-          - version-update:semver-major
-      - dependency-name: org.mockito:mockito-bom
-        update-types:
-          - version-update:semver-major
-      - dependency-name: '*'
-        update-types:
-          - version-update:semver-major
-          - version-update:semver-minor
-  - package-ecosystem: gradle
-    target-branch: 6.1.x
-    directory: /
-    schedule:
-      interval: daily
-      time: '03:00'
-      timezone: Etc/UTC
-    labels:
-      - 'type: dependency-upgrade'
-    registries:
-      - spring-milestones
-    ignore:
-      - dependency-name: com.nimbusds:nimbus-jose-jwt
-      - dependency-name: org.python:jython
-      - dependency-name: org.apache.directory.server:*
-      - dependency-name: org.junit:junit-bom
-        update-types:
-          - version-update:semver-major
-      - dependency-name: org.mockito:mockito-bom
-        update-types:
-          - version-update:semver-major
-      - dependency-name: '*'
-        update-types:
-          - version-update:semver-major
-          - version-update:semver-minor
-  - package-ecosystem: gradle
-    target-branch: 6.2.x
-    directory: /
-    schedule:
-      interval: daily
-      time: '03:00'
-      timezone: Etc/UTC
-    labels:
-      - 'type: dependency-upgrade'
-    registries:
-      - spring-milestones
-    ignore:
-      - dependency-name: com.nimbusds:nimbus-jose-jwt
-      - dependency-name: org.python:jython
-      - dependency-name: org.apache.directory.server:*
-      - dependency-name: org.junit:junit-bom
-        update-types:
-          - version-update:semver-major
-      - dependency-name: org.mockito:mockito-bom
-        update-types:
-          - version-update:semver-major
-      - dependency-name: '*'
-        update-types:
-          - version-update:semver-major
-          - version-update:semver-minor
-  - package-ecosystem: gradle
-    target-branch: main
-    directory: /
+
+  - package-ecosystem: "gradle"
+    target-branch: "main"
+    milestone: 319 # 6.2.x
+    directory: "/"
     schedule:
-      interval: daily
-      time: '03:00'
-      timezone: Etc/UTC
-    labels:
-      - 'type: dependency-upgrade'
+      interval: "daily"
+      time: "03:00"
+      timezone: "Etc/UTC"
+    labels: [ "type: dependency-upgrade" ]
     registries:
-      - spring-milestones
-    ignore:
-      - dependency-name: com.nimbusds:nimbus-jose-jwt
-      - dependency-name: org.python:jython
-      - dependency-name: org.apache.directory.server:*
-      - dependency-name: org.junit:junit-bom
-        update-types:
-          - version-update:semver-major
-      - dependency-name: org.mockito:mockito-bom
-        update-types:
-          - version-update:semver-major
-      - dependency-name: com.gradle.enterprise
-        update-types:
-          - version-update:semver-major
-          - version-update:semver-minor
-      - dependency-name: '*'
-        update-types:
-          - version-update:semver-major
-          - version-update:semver-minor
-  - package-ecosystem: github-actions
-    target-branch: 5.8.x
-    directory: /
-    schedule:
-      interval: weekly
+      - "spring-milestones"
     ignore:
-      - dependency-name: sjohnr/*
-      - dependency-name: spring-io/*
-      - dependency-name: spring-security-release-tools/*
-  - package-ecosystem: github-actions
-    target-branch: 6.1.x
-    directory: /
-    schedule:
-      interval: weekly
-    ignore:
-      - dependency-name: sjohnr/*
-      - dependency-name: spring-io/*
-      - dependency-name: spring-security-release-tools/*
-  - package-ecosystem: github-actions
-    target-branch: 6.2.x
-    directory: /
-    schedule:
-      interval: weekly
-    ignore:
-      - dependency-name: sjohnr/*
-      - dependency-name: spring-io/*
-      - dependency-name: spring-security-release-tools/*
-  - package-ecosystem: github-actions
-    target-branch: main
-    directory: /
-    schedule:
-      interval: weekly
-    ignore:
-      - dependency-name: sjohnr/*
-      - dependency-name: spring-io/*
-      - dependency-name: spring-security-release-tools/*
-  - package-ecosystem: github-actions
-    target-branch: docs-build
-    directory: /
+      - dependency-name: "com.nimbusds:nimbus-jose-jwt" # nimbus-jose-jwt gets updated when oauth2-oidc-sdk is updated to ensure consistency
+      - dependency-name: "org.python:jython" # jython updates break integration tests
+      - dependency-name: "org.apache.directory.server:*" # ApacheDS version > 1.5.5 contains break changes
+      - dependency-name: "org.junit:junit-bom"
+        update-types: [ "version-update:semver-major" ]
+      - dependency-name: "org.mockito:mockito-bom"
+        update-types: [ "version-update:semver-major" ]
+      - dependency-name: "*"
+        update-types: [ "version-update:semver-major", "version-update:semver-minor" ]
+
+  - package-ecosystem: "gradle"
+    target-branch: "6.1.x"
+    milestone: 318 # 6.1.x
+    directory: "/"
     schedule:
-      interval: weekly
+      interval: "daily"
+      time: "03:00"
+      timezone: "Etc/UTC"
+    labels: [ "type: dependency-upgrade" ]
     ignore:
-      - dependency-name: sjohnr/*
-      - dependency-name: spring-io/*
-      - dependency-name: spring-security-release-tools/*
+      - dependency-name: "com.nimbusds:nimbus-jose-jwt" # nimbus-jose-jwt gets updated when oauth2-oidc-sdk is updated to ensure consistency
+      - dependency-name: "org.python:jython" # jython updates break integration tests
+      - dependency-name: "org.apache.directory.server:*" # ApacheDS version > 1.5.5 contains break changes
+      - dependency-name: "org.junit:junit-bom"
+        update-types: [ "version-update:semver-major" ]
+      - dependency-name: "org.mockito:mockito-bom"
+        update-types: [ "version-update:semver-major" ]
+      - dependency-name: "*"
+        update-types: [ "version-update:semver-major", "version-update:semver-minor" ]
 
-  - package-ecosystem: npm
-    target-branch: docs-build
-    directory: /
+  - package-ecosystem: "gradle"
+    target-branch: "5.8.x"
+    milestone: 246 # 5.8.x
+    directory: "/"
     schedule:
-      interval: weekly
+      interval: "daily"
+      time: "03:00"
+      timezone: "Etc/UTC"
+    labels: [ "type: dependency-upgrade" ]
+    ignore:
+      - dependency-name: "com.nimbusds:nimbus-jose-jwt" # nimbus-jose-jwt gets updated when oauth2-oidc-sdk is updated to ensure consistency
+      - dependency-name: "org.python:jython" # jython updates break integration tests
+      - dependency-name: "org.apache.directory.server:*" # ApacheDS version > 1.5.5 contains break changes
+      - dependency-name: "io.mockk:mockk" # mockk updates break tests
+      - dependency-name: "org.opensaml:*" # org.opensaml maintains two different versions, so it must be updated manually
+      - dependency-name: "org.junit:junit-bom"
+        update-types: [ "version-update:semver-major" ]
+      - dependency-name: "org.mockito:mockito-bom"
+        update-types: [ "version-update:semver-major" ]
+      - dependency-name: "*"
+        update-types: [ "version-update:semver-major", "version-update:semver-minor" ]

+ 0 - 57
.github/workflows/dependabot-auto-merge-forward.yml

@@ -1,57 +0,0 @@
-name: Auto Merge Forward Dependabot Commits
-
-on:
-  workflow_dispatch:
-
-permissions:
-  contents: read
-
-concurrency:
-  group: dependabot-auto-merge-forward
-
-jobs:
-  get-supported-branches:
-    uses: spring-io/spring-security-release-tools/.github/workflows/retrieve-spring-supported-versions.yml@actions-v1
-    with:
-      project: spring-security
-      type: oss
-      repository_name: spring-projects/spring-security
-
-  auto-merge-forward-dependabot:
-    name: Auto Merge Forward Dependabot Commits
-    runs-on: ubuntu-latest
-    needs: [get-supported-branches]
-    permissions:
-      contents: write
-    steps:
-      - name: Checkout
-        id: checkout
-        uses: actions/checkout@v4
-        with:
-          token: ${{ secrets.GH_ACTIONS_REPO_TOKEN }}
-      - name: Setup GitHub User
-        id: setup-gh-user
-        run: |
-          git config user.name 'github-actions[bot]'
-          git config user.email 'github-actions[bot]@users.noreply.github.com'
-      - name: Run Auto Merge Forward
-        id: run-auto-merge-forward
-        uses: spring-io/spring-security-release-tools/.github/actions/auto-merge-forward@actions-v1
-        with:
-          branches: ${{ needs.get-supported-branches.outputs.supported_versions }},main
-          from-author: dependabot[bot]
-  notify_result:
-    name: Check for failures
-    needs: [ auto-merge-forward-dependabot ]
-    if: failure()
-    runs-on: ubuntu-latest
-    permissions:
-      actions: read
-    steps:
-      - name: Send Slack message
-        uses: Gamesight/slack-workflow-status@v1.3.0
-        with:
-          repo_token: ${{ secrets.GITHUB_TOKEN }}
-          slack_webhook_url: ${{ secrets.SLACK_WEBHOOK_URL }}
-          channel: '#spring-security-ci'
-          name: 'CI Notifier'

+ 1 - 1
.github/workflows/release-scheduler.yml

@@ -11,7 +11,7 @@ jobs:
     strategy:
       matrix:
         # List of active maintenance branches.
-        branch: [ main, 6.2.x, 6.1.x, 5.8.x ]
+        branch: [ main, 6.1.x, 5.8.x ]
     runs-on: ubuntu-latest
     steps:
     - name: Checkout

+ 0 - 36
.github/workflows/update-dependabot.yml

@@ -1,36 +0,0 @@
-name: Update dependabot.yml
-
-on:
-  workflow_dispatch:
-
-permissions:
-  contents: read
-
-jobs:
-
-  get-supported-branches:
-    uses: spring-io/spring-security-release-tools/.github/workflows/retrieve-spring-supported-versions.yml@actions-v1
-    with:
-      project: spring-security
-      type: oss
-      repository_name: spring-projects/spring-security
-
-  main:
-    runs-on: ubuntu-latest
-    needs: [get-supported-branches]
-    if: ${{ (github.repository == 'spring-projects/spring-security') && (github.ref == 'refs/heads/main') }}
-    permissions:
-      contents: write
-    steps:
-      - uses: actions/checkout@v4
-        with:
-          fetch-depth: 1
-      - uses: spring-io/spring-security-release-tools/.github/actions/generate-dependabot-yml@actions-v1
-        name: Update dependabot.yml
-        with:
-          gradle-branches: ${{ needs.get-supported-branches.outputs.supported_versions }},main
-          github-actions-branches: ${{ needs.get-supported-branches.outputs.supported_versions }},main,docs-build
-          gh-token: ${{ secrets.GITHUB_TOKEN }}
-      - uses: stefanzweifel/git-auto-commit-action@v5
-        with:
-          commit_message: Update dependabot.yml

+ 1 - 1
CONTRIBUTING.adoc

@@ -105,7 +105,7 @@ Once merged, the fix will be forwarded-ported to applicable branches including `
 1. Create a local branch
 If this is for an issue, consider a branch name with the issue number, like `gh-22276`.
 [[write-tests]]
-1. Add documentation and JUnit Tests for your changes.
+1. Add JUnit Tests for your changes
 [[update-copyright]]
 1. In all files you edited, if the copyright header is of the form 2002-20xx, update the final copyright year to the current year.
 [[add-since]]

+ 2 - 2
README.adoc

@@ -1,8 +1,8 @@
 image::https://badges.gitter.im/Join%20Chat.svg[Gitter,link=https://gitter.im/spring-projects/spring-security?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge]
 
-image:https://github.com/spring-projects/spring-security/actions/workflows/continuous-integration-workflow.yml/badge.svg?branch=main["Build Status", link="https://github.com/spring-projects/spring-security/actions/workflows/continuous-integration-workflow.yml"]
+image:https://github.com/spring-projects/spring-security/workflows/CI/badge.svg?branch=main["Build Status", link="https://github.com/spring-projects/spring-security/actions?query=workflow%3ACI"]
 
-image:https://img.shields.io/badge/Revved%20up%20by-Develocity-06A0CE?logo=Gradle&labelColor=02303A["Revved up by Develocity", link="https://ge.spring.io/scans?search.rootProjectNames=spring-security"]
+image:https://img.shields.io/badge/Revved%20up%20by-Gradle%20Enterprise-06A0CE?logo=Gradle&labelColor=02303A["Revved up by Gradle Enterprise", link="https://ge.spring.io/scans?search.rootProjectNames=spring-security"]
 
 = Spring Security
 

+ 1 - 21
aspects/src/test/java/org/springframework/security/authorization/method/aspectj/PostAuthorizeAspectTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2022 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -103,13 +103,6 @@ public class PostAuthorizeAspectTests {
 		assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.prePostSecured::denyAllMethod);
 	}
 
-	@Test
-	public void nestedDenyAllPostAuthorizeDeniesAccess() {
-		SecurityContextHolder.getContext().setAuthentication(this.anne);
-		assertThatExceptionOfType(AccessDeniedException.class)
-			.isThrownBy(() -> this.secured.myObject().denyAllMethod());
-	}
-
 	interface SecuredInterface {
 
 		@PostAuthorize("hasRole('X')")
@@ -141,10 +134,6 @@ public class PostAuthorizeAspectTests {
 			privateMethod();
 		}
 
-		NestedObject myObject() {
-			return new NestedObject();
-		}
-
 	}
 
 	static class SecuredImplSubclass extends SecuredImpl {
@@ -168,13 +157,4 @@ public class PostAuthorizeAspectTests {
 
 	}
 
-	static class NestedObject {
-
-		@PostAuthorize("denyAll")
-		void denyAllMethod() {
-
-		}
-
-	}
-
 }

+ 1 - 19
aspects/src/test/java/org/springframework/security/authorization/method/aspectj/PostFilterAspectTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2022 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -54,11 +54,6 @@ public class PostFilterAspectTests {
 		assertThat(this.prePostSecured.postFilterMethod(objects)).containsExactly("apple", "aubergine");
 	}
 
-	@Test
-	public void nestedDenyAllPostFilterDeniesAccess() {
-		assertThat(this.prePostSecured.myObject().denyAllMethod()).isEmpty();
-	}
-
 	static class PrePostSecured {
 
 		@PostFilter("filterObject.startsWith('a')")
@@ -66,19 +61,6 @@ public class PostFilterAspectTests {
 			return objects;
 		}
 
-		NestedObject myObject() {
-			return new NestedObject();
-		}
-
-	}
-
-	static class NestedObject {
-
-		@PostFilter("filterObject == null")
-		List<String> denyAllMethod() {
-			return new ArrayList<>(List.of("deny"));
-		}
-
 	}
 
 }

+ 1 - 21
aspects/src/test/java/org/springframework/security/authorization/method/aspectj/PreAuthorizeAspectTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2022 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -103,13 +103,6 @@ public class PreAuthorizeAspectTests {
 		assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.prePostSecured::denyAllMethod);
 	}
 
-	@Test
-	public void nestedDenyAllPreAuthorizeDeniesAccess() {
-		SecurityContextHolder.getContext().setAuthentication(this.anne);
-		assertThatExceptionOfType(AccessDeniedException.class)
-			.isThrownBy(() -> this.secured.myObject().denyAllMethod());
-	}
-
 	interface SecuredInterface {
 
 		@PreAuthorize("hasRole('X')")
@@ -141,10 +134,6 @@ public class PreAuthorizeAspectTests {
 			privateMethod();
 		}
 
-		NestedObject myObject() {
-			return new NestedObject();
-		}
-
 	}
 
 	static class SecuredImplSubclass extends SecuredImpl {
@@ -168,13 +157,4 @@ public class PreAuthorizeAspectTests {
 
 	}
 
-	static class NestedObject {
-
-		@PreAuthorize("denyAll")
-		void denyAllMethod() {
-
-		}
-
-	}
-
 }

+ 1 - 19
aspects/src/test/java/org/springframework/security/authorization/method/aspectj/PreFilterAspectTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2022 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -54,11 +54,6 @@ public class PreFilterAspectTests {
 		assertThat(this.prePostSecured.preFilterMethod(objects)).containsExactly("apple", "aubergine");
 	}
 
-	@Test
-	public void nestedDenyAllPreFilterDeniesAccess() {
-		assertThat(this.prePostSecured.myObject().denyAllMethod(new ArrayList<>(List.of("deny")))).isEmpty();
-	}
-
 	static class PrePostSecured {
 
 		@PreFilter("filterObject.startsWith('a')")
@@ -66,19 +61,6 @@ public class PreFilterAspectTests {
 			return objects;
 		}
 
-		NestedObject myObject() {
-			return new NestedObject();
-		}
-
-	}
-
-	static class NestedObject {
-
-		@PreFilter("filterObject == null")
-		List<String> denyAllMethod(List<String> list) {
-			return list;
-		}
-
 	}
 
 }

+ 1 - 1
aspects/src/test/java/org/springframework/security/authorization/method/aspectj/SecuredAspectTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2022 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.

+ 3 - 15
cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationEntryPoint.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2023 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -28,7 +28,6 @@ import org.springframework.security.cas.ServiceProperties;
 import org.springframework.security.core.AuthenticationException;
 import org.springframework.security.web.AuthenticationEntryPoint;
 import org.springframework.security.web.DefaultRedirectStrategy;
-import org.springframework.security.web.RedirectStrategy;
 import org.springframework.util.Assert;
 
 /**
@@ -62,8 +61,6 @@ public class CasAuthenticationEntryPoint implements AuthenticationEntryPoint, In
 	 */
 	private boolean encodeServiceUrlWithSessionId = true;
 
-	private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
-
 	@Override
 	public void afterPropertiesSet() {
 		Assert.hasLength(this.loginUrl, "loginUrl must be specified");
@@ -77,7 +74,8 @@ public class CasAuthenticationEntryPoint implements AuthenticationEntryPoint, In
 		String urlEncodedService = createServiceUrl(servletRequest, response);
 		String redirectUrl = createRedirectUrl(urlEncodedService);
 		preCommence(servletRequest, response);
-		this.redirectStrategy.sendRedirect(servletRequest, response, redirectUrl);
+		new DefaultRedirectStrategy().sendRedirect(servletRequest, response, redirectUrl);
+		// response.sendRedirect(redirectUrl);
 	}
 
 	/**
@@ -151,14 +149,4 @@ public class CasAuthenticationEntryPoint implements AuthenticationEntryPoint, In
 		return this.encodeServiceUrlWithSessionId;
 	}
 
-	/**
-	 * Sets the {@link RedirectStrategy} to use
-	 * @param redirectStrategy the {@link RedirectStrategy} to use
-	 * @since 6.3
-	 */
-	public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
-		Assert.notNull(redirectStrategy, "redirectStrategy cannot be null");
-		this.redirectStrategy = redirectStrategy;
-	}
-
 }

+ 1 - 49
cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java

@@ -22,7 +22,6 @@ import jakarta.servlet.FilterChain;
 import jakarta.servlet.ServletException;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
-import jakarta.servlet.http.HttpSession;
 import org.apereo.cas.client.proxy.ProxyGrantingTicketStorage;
 import org.apereo.cas.client.util.WebUtils;
 import org.apereo.cas.client.validation.TicketValidator;
@@ -41,20 +40,14 @@ import org.springframework.security.core.AuthenticationException;
 import org.springframework.security.core.context.SecurityContext;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.core.context.SecurityContextHolderStrategy;
-import org.springframework.security.web.DefaultRedirectStrategy;
-import org.springframework.security.web.RedirectStrategy;
 import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
 import org.springframework.security.web.authentication.AuthenticationFailureHandler;
 import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
 import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
 import org.springframework.security.web.context.SecurityContextRepository;
-import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
-import org.springframework.security.web.savedrequest.RequestCache;
-import org.springframework.security.web.savedrequest.SavedRequest;
 import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
 import org.springframework.security.web.util.matcher.RequestMatcher;
 import org.springframework.util.Assert;
-import org.springframework.util.StringUtils;
 
 /**
  * Processes a CAS service ticket, obtains proxy granting tickets, and processes proxy
@@ -207,10 +200,6 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
 	private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
 		.getContextHolderStrategy();
 
-	private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
-
-	private RequestCache requestCache = new HttpSessionRequestCache();
-
 	private final AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
 
 	public CasAuthenticationFilter() {
@@ -251,22 +240,7 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
 			return null;
 		}
 		String serviceTicket = obtainArtifact(request);
-		if (!StringUtils.hasText(serviceTicket)) {
-			HttpSession session = request.getSession(false);
-			if (session != null && session
-				.getAttribute(CasGatewayAuthenticationRedirectFilter.CAS_GATEWAY_AUTHENTICATION_ATTR) != null) {
-				this.logger.debug("Failed authentication response from CAS gateway request");
-				session.removeAttribute(CasGatewayAuthenticationRedirectFilter.CAS_GATEWAY_AUTHENTICATION_ATTR);
-				SavedRequest savedRequest = this.requestCache.getRequest(request, response);
-				if (savedRequest != null) {
-					String redirectUrl = savedRequest.getRedirectUrl();
-					this.logger.debug(LogMessage.format("Redirecting to: %s", redirectUrl));
-					this.requestCache.removeRequest(request, response);
-					this.redirectStrategy.sendRedirect(request, response, redirectUrl);
-					return null;
-				}
-			}
-
+		if (serviceTicket == null) {
 			this.logger.debug("Failed to obtain an artifact (cas ticket)");
 			serviceTicket = "";
 		}
@@ -344,28 +318,6 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
 		this.securityContextHolderStrategy = securityContextHolderStrategy;
 	}
 
-	/**
-	 * Set the {@link RedirectStrategy} used to redirect to the saved request if there is
-	 * one saved. Defaults to {@link DefaultRedirectStrategy}.
-	 * @param redirectStrategy the redirect strategy to use
-	 * @since 6.3
-	 */
-	public final void setRedirectStrategy(RedirectStrategy redirectStrategy) {
-		Assert.notNull(redirectStrategy, "redirectStrategy cannot be null");
-		this.redirectStrategy = redirectStrategy;
-	}
-
-	/**
-	 * The {@link RequestCache} used to retrieve the saved request in failed gateway
-	 * authentication scenarios.
-	 * @param requestCache the request cache to use
-	 * @since 6.3
-	 */
-	public final void setRequestCache(RequestCache requestCache) {
-		Assert.notNull(requestCache, "requestCache cannot be null");
-		this.requestCache = requestCache;
-	}
-
 	/**
 	 * Indicates if the request is elgible to process a service ticket. This method exists
 	 * for readability.

+ 0 - 126
cas/src/main/java/org/springframework/security/cas/web/CasGatewayAuthenticationRedirectFilter.java

@@ -1,126 +0,0 @@
-/*
- * Copyright 2002-2023 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.cas.web;
-
-import java.io.IOException;
-
-import jakarta.servlet.FilterChain;
-import jakarta.servlet.ServletException;
-import jakarta.servlet.ServletRequest;
-import jakarta.servlet.ServletResponse;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import jakarta.servlet.http.HttpSession;
-import org.apereo.cas.client.util.CommonUtils;
-import org.apereo.cas.client.util.WebUtils;
-
-import org.springframework.security.cas.ServiceProperties;
-import org.springframework.security.web.DefaultRedirectStrategy;
-import org.springframework.security.web.RedirectStrategy;
-import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
-import org.springframework.security.web.savedrequest.RequestCache;
-import org.springframework.security.web.util.matcher.RequestMatcher;
-import org.springframework.util.Assert;
-import org.springframework.web.filter.GenericFilterBean;
-
-/**
- * Redirects the request to the CAS server appending {@code gateway=true} to the URL. Upon
- * redirection, the {@link ServiceProperties#isSendRenew()} is ignored and considered as
- * {@code false} to align with the specification says that the {@code sendRenew} parameter
- * is not compatible with the {@code gateway} parameter. See the <a href=
- * "https://apereo.github.io/cas/6.6.x/protocol/CAS-Protocol-V2-Specification.html#:~:text=This%20parameter%20is%20not%20compatible%20with%20the%20%E2%80%9Crenew%E2%80%9D%20parameter.%20Behavior%20is%20undefined%20if%20both%20are%20set.">CAS
- * Protocol Specification</a> for more details. To allow other filters to know if the
- * request is a gateway request, this filter creates a session and add an attribute with
- * name {@link #CAS_GATEWAY_AUTHENTICATION_ATTR} which can be checked by other filters if
- * needed. It is recommended that this filter is placed after
- * {@link CasAuthenticationFilter} if it is defined.
- *
- * @author Michael Remond
- * @author Jerome LELEU
- * @author Marcus da Coregio
- * @since 6.3
- */
-public final class CasGatewayAuthenticationRedirectFilter extends GenericFilterBean {
-
-	public static final String CAS_GATEWAY_AUTHENTICATION_ATTR = "CAS_GATEWAY_AUTHENTICATION";
-
-	private final String casLoginUrl;
-
-	private final ServiceProperties serviceProperties;
-
-	private RequestMatcher requestMatcher;
-
-	private RequestCache requestCache = new HttpSessionRequestCache();
-
-	private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
-
-	/**
-	 * Constructs a new instance of this class
-	 * @param serviceProperties the {@link ServiceProperties}
-	 */
-	public CasGatewayAuthenticationRedirectFilter(String casLoginUrl, ServiceProperties serviceProperties) {
-		Assert.hasText(casLoginUrl, "casLoginUrl cannot be null or empty");
-		Assert.notNull(serviceProperties, "serviceProperties cannot be null");
-		this.casLoginUrl = casLoginUrl;
-		this.serviceProperties = serviceProperties;
-		this.requestMatcher = new CasGatewayResolverRequestMatcher(this.serviceProperties);
-	}
-
-	@Override
-	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
-			throws IOException, ServletException {
-
-		HttpServletRequest request = (HttpServletRequest) req;
-		HttpServletResponse response = (HttpServletResponse) res;
-
-		if (!this.requestMatcher.matches(request)) {
-			chain.doFilter(request, response);
-			return;
-		}
-
-		this.requestCache.saveRequest(request, response);
-		HttpSession session = request.getSession(true);
-		session.setAttribute(CAS_GATEWAY_AUTHENTICATION_ATTR, true);
-		String urlEncodedService = WebUtils.constructServiceUrl(request, response, this.serviceProperties.getService(),
-				null, this.serviceProperties.getServiceParameter(), this.serviceProperties.getArtifactParameter(),
-				true);
-		String redirectUrl = CommonUtils.constructRedirectUrl(this.casLoginUrl,
-				this.serviceProperties.getServiceParameter(), urlEncodedService, false, true);
-		this.redirectStrategy.sendRedirect(request, response, redirectUrl);
-	}
-
-	/**
-	 * Sets the {@link RequestMatcher} used to trigger this filter. Defaults to
-	 * {@link CasGatewayResolverRequestMatcher}.
-	 * @param requestMatcher the {@link RequestMatcher} to use
-	 */
-	public void setRequestMatcher(RequestMatcher requestMatcher) {
-		Assert.notNull(requestMatcher, "requestMatcher cannot be null");
-		this.requestMatcher = requestMatcher;
-	}
-
-	/**
-	 * Sets the {@link RequestCache} used to store the current request to be replayed
-	 * after redirect from the CAS server. Defaults to {@link HttpSessionRequestCache}.
-	 * @param requestCache the {@link RequestCache} to use
-	 */
-	public void setRequestCache(RequestCache requestCache) {
-		Assert.notNull(requestCache, "requestCache cannot be null");
-		this.requestCache = requestCache;
-	}
-
-}

+ 0 - 67
cas/src/main/java/org/springframework/security/cas/web/CasGatewayResolverRequestMatcher.java

@@ -1,67 +0,0 @@
-/*
- * Copyright 2002-2023 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.cas.web;
-
-import jakarta.servlet.http.HttpServletRequest;
-import org.apereo.cas.client.authentication.DefaultGatewayResolverImpl;
-import org.apereo.cas.client.authentication.GatewayResolver;
-
-import org.springframework.security.cas.ServiceProperties;
-import org.springframework.security.web.util.matcher.RequestMatcher;
-import org.springframework.util.Assert;
-
-/**
- * A {@link RequestMatcher} implementation that delegates the check to an instance of
- * {@link GatewayResolver}. The request is marked as "gatewayed" using the configured
- * {@link GatewayResolver} to avoid infinite loop.
- *
- * @author Michael Remond
- * @author Marcus da Coregio
- * @since 6.3
- */
-public final class CasGatewayResolverRequestMatcher implements RequestMatcher {
-
-	private final ServiceProperties serviceProperties;
-
-	private GatewayResolver gatewayStorage = new DefaultGatewayResolverImpl();
-
-	public CasGatewayResolverRequestMatcher(ServiceProperties serviceProperties) {
-		Assert.notNull(serviceProperties, "serviceProperties cannot be null");
-		this.serviceProperties = serviceProperties;
-	}
-
-	@Override
-	public boolean matches(HttpServletRequest request) {
-		boolean wasGatewayed = this.gatewayStorage.hasGatewayedAlready(request, this.serviceProperties.getService());
-		if (!wasGatewayed) {
-			this.gatewayStorage.storeGatewayInformation(request, this.serviceProperties.getService());
-			return true;
-		}
-		return false;
-	}
-
-	/**
-	 * Sets the {@link GatewayResolver} to check if the request was already gatewayed.
-	 * Defaults to {@link DefaultGatewayResolverImpl}
-	 * @param gatewayStorage the {@link GatewayResolver} to use. Cannot be null.
-	 */
-	public void setGatewayStorage(GatewayResolver gatewayStorage) {
-		Assert.notNull(gatewayStorage, "gatewayStorage cannot be null");
-		this.gatewayStorage = gatewayStorage;
-	}
-
-}

+ 0 - 27
cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationEntryPointTests.java

@@ -16,22 +16,16 @@
 
 package org.springframework.security.cas.web;
 
-import java.io.IOException;
 import java.net.URLEncoder;
 
 import org.junit.jupiter.api.Test;
 
 import org.springframework.mock.web.MockHttpServletRequest;
 import org.springframework.mock.web.MockHttpServletResponse;
-import org.springframework.security.authentication.BadCredentialsException;
 import org.springframework.security.cas.ServiceProperties;
-import org.springframework.security.web.RedirectStrategy;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
 
 /**
  * Tests {@link CasAuthenticationEntryPoint}.
@@ -101,25 +95,4 @@ public class CasAuthenticationEntryPointTests {
 			.isEqualTo(response.getRedirectedUrl());
 	}
 
-	@Test
-	void setRedirectStrategyThenUses() throws IOException {
-		CasAuthenticationEntryPoint ep = new CasAuthenticationEntryPoint();
-		ServiceProperties sp = new ServiceProperties();
-
-		sp.setService("https://mycompany.com/login/cas");
-		ep.setServiceProperties(sp);
-		ep.setLoginUrl("https://cas/login");
-
-		RedirectStrategy redirectStrategy = mock();
-
-		ep.setRedirectStrategy(redirectStrategy);
-		MockHttpServletRequest req = new MockHttpServletRequest();
-		MockHttpServletResponse res = new MockHttpServletResponse();
-
-		ep.commence(req, res, new BadCredentialsException("bad credentials"));
-
-		verify(redirectStrategy).sendRedirect(eq(req), eq(res),
-				eq("https://cas/login?service=https%3A%2F%2Fmycompany.com%2Flogin%2Fcas"));
-	}
-
 }

+ 0 - 21
cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationFilterTests.java

@@ -20,7 +20,6 @@ import java.io.IOException;
 
 import jakarta.servlet.FilterChain;
 import jakarta.servlet.ServletException;
-import jakarta.servlet.http.HttpSession;
 import org.apereo.cas.client.proxy.ProxyGrantingTicketStorage;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Test;
@@ -42,7 +41,6 @@ import org.springframework.security.core.context.SecurityContextHolderStrategy;
 import org.springframework.security.core.context.SecurityContextImpl;
 import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
 import org.springframework.security.web.context.SecurityContextRepository;
-import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
 import org.springframework.test.util.ReflectionTestUtils;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -226,25 +224,6 @@ public class CasAuthenticationFilterTests {
 		verify(securityContextRepository).saveContext(any(SecurityContext.class), eq(request), eq(response));
 	}
 
-	@Test
-	public void attemptAuthenticationWhenNoServiceTicketAndIsGatewayRequestThenRedirectToSavedRequestAndClearAttribute()
-			throws Exception {
-		CasAuthenticationFilter filter = new CasAuthenticationFilter();
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		MockHttpServletResponse response = new MockHttpServletResponse();
-		HttpSession session = request.getSession(true);
-		session.setAttribute(CasGatewayAuthenticationRedirectFilter.CAS_GATEWAY_AUTHENTICATION_ATTR, true);
-
-		new HttpSessionRequestCache().saveRequest(request, response);
-
-		Authentication authn = filter.attemptAuthentication(request, response);
-		assertThat(authn).isNull();
-		assertThat(response.getStatus()).isEqualTo(302);
-		assertThat(response.getRedirectedUrl()).isEqualTo("http://localhost?continue");
-		assertThat(session.getAttribute(CasGatewayAuthenticationRedirectFilter.CAS_GATEWAY_AUTHENTICATION_ATTR))
-			.isNull();
-	}
-
 	@Test
 	void successfulAuthenticationWhenSecurityContextRepositorySetThenUses() throws ServletException, IOException {
 		SecurityContextRepository securityContextRepository = mock(SecurityContextRepository.class);

+ 0 - 95
cas/src/test/java/org/springframework/security/cas/web/CasGatewayAuthenticationRedirectFilterTests.java

@@ -1,95 +0,0 @@
-/*
- * Copyright 2002-2023 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.cas.web;
-
-import java.io.IOException;
-
-import jakarta.servlet.FilterChain;
-import jakarta.servlet.ServletException;
-import org.junit.jupiter.api.Test;
-
-import org.springframework.http.HttpStatus;
-import org.springframework.mock.web.MockFilterChain;
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.mock.web.MockHttpServletResponse;
-import org.springframework.security.cas.ServiceProperties;
-import org.springframework.security.web.savedrequest.RequestCache;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoInteractions;
-
-/**
- * Tests for {@link CasGatewayAuthenticationRedirectFilter}.
- *
- * @author Jerome LELEU
- * @author Marcus da Coregio
- */
-public class CasGatewayAuthenticationRedirectFilterTests {
-
-	private static final String CAS_LOGIN_URL = "http://mycasserver/login";
-
-	CasGatewayAuthenticationRedirectFilter filter = new CasGatewayAuthenticationRedirectFilter(CAS_LOGIN_URL,
-			serviceProperties());
-
-	@Test
-	void doFilterWhenMatchesThenSavesRequestAndSavesAttributeAndSendRedirect() throws IOException, ServletException {
-		RequestCache requestCache = mock();
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		MockHttpServletResponse response = new MockHttpServletResponse();
-		this.filter.setRequestMatcher((req) -> true);
-		this.filter.setRequestCache(requestCache);
-		this.filter.doFilter(request, response, new MockFilterChain());
-		assertThat(response.getStatus()).isEqualTo(HttpStatus.FOUND.value());
-		assertThat(response.getHeader("Location"))
-			.isEqualTo("http://mycasserver/login?service=http%3A%2F%2Flocalhost%2Flogin%2Fcas&gateway=true");
-		verify(requestCache).saveRequest(request, response);
-	}
-
-	@Test
-	void doFilterWhenNotMatchThenContinueFilter() throws ServletException, IOException {
-		this.filter.setRequestMatcher((req) -> false);
-		FilterChain chain = mock();
-		MockHttpServletResponse response = mock();
-		this.filter.doFilter(new MockHttpServletRequest(), response, chain);
-		verify(chain).doFilter(any(), any());
-		verifyNoInteractions(response);
-	}
-
-	@Test
-	void doFilterWhenSendRenewTrueThenIgnores() throws ServletException, IOException {
-		ServiceProperties serviceProperties = serviceProperties();
-		serviceProperties.setSendRenew(true);
-		this.filter = new CasGatewayAuthenticationRedirectFilter(CAS_LOGIN_URL, serviceProperties);
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		MockHttpServletResponse response = new MockHttpServletResponse();
-		this.filter.setRequestMatcher((req) -> true);
-		this.filter.doFilter(request, response, new MockFilterChain());
-		assertThat(response.getStatus()).isEqualTo(HttpStatus.FOUND.value());
-		assertThat(response.getHeader("Location"))
-			.isEqualTo("http://mycasserver/login?service=http%3A%2F%2Flocalhost%2Flogin%2Fcas&gateway=true");
-	}
-
-	private static ServiceProperties serviceProperties() {
-		ServiceProperties serviceProperties = new ServiceProperties();
-		serviceProperties.setService("http://localhost/login/cas");
-		return serviceProperties;
-	}
-
-}

+ 0 - 74
cas/src/test/java/org/springframework/security/cas/web/CasGatewayResolverRequestMatcherTests.java

@@ -1,74 +0,0 @@
-/*
- * Copyright 2002-2023 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.cas.web;
-
-import org.junit.jupiter.api.Test;
-
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.security.cas.ServiceProperties;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
-
-/**
- * Tests {@link CasGatewayResolverRequestMatcher}.
- *
- * @author Marcus da Coregio
- */
-class CasGatewayResolverRequestMatcherTests {
-
-	CasGatewayResolverRequestMatcher matcher = new CasGatewayResolverRequestMatcher(new ServiceProperties());
-
-	@Test
-	void constructorWhenServicePropertiesNullThenException() {
-		assertThatIllegalArgumentException().isThrownBy(() -> new CasGatewayResolverRequestMatcher(null))
-			.withMessage("serviceProperties cannot be null");
-	}
-
-	@Test
-	void matchesWhenAlreadyGatewayedThenReturnsFalse() {
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		request.getSession().setAttribute("_const_cas_gateway_", "yes");
-		boolean matches = this.matcher.matches(request);
-		assertThat(matches).isFalse();
-	}
-
-	@Test
-	void matchesWhenNotGatewayedThenReturnsTrue() {
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		boolean matches = this.matcher.matches(request);
-		assertThat(matches).isTrue();
-	}
-
-	@Test
-	void matchesWhenNoSessionThenReturnsTrue() {
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		request.setSession(null);
-		boolean matches = this.matcher.matches(request);
-		assertThat(matches).isTrue();
-	}
-
-	@Test
-	void matchesWhenNotGatewayedAndCheckedAgainThenSavesAsGatewayedAndReturnsFalse() {
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		boolean matches = this.matcher.matches(request);
-		boolean secondMatch = this.matcher.matches(request);
-		assertThat(matches).isTrue();
-		assertThat(secondMatch).isFalse();
-	}
-
-}

+ 2 - 2
config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java

@@ -96,7 +96,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
 			pc.getReaderContext()
 				.fatal("You cannot use a spring-security-2.0.xsd or spring-security-3.0.xsd or "
 						+ "spring-security-3.1.xsd schema or spring-security-3.2.xsd schema or spring-security-4.0.xsd schema "
-						+ "with Spring Security 6.3. Please update your schema declarations to the 6.3 schema.",
+						+ "with Spring Security 6.2. Please update your schema declarations to the 6.2 schema.",
 						element);
 		}
 		String name = pc.getDelegate().getLocalName(element);
@@ -221,7 +221,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
 
 	private boolean matchesVersionInternal(Element element) {
 		String schemaLocation = element.getAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation");
-		return schemaLocation.matches("(?m).*spring-security-6\\.3.*.xsd.*")
+		return schemaLocation.matches("(?m).*spring-security-6\\.2.*.xsd.*")
 				|| schemaLocation.matches("(?m).*spring-security.xsd.*")
 				|| !schemaLocation.matches("(?m).*spring-security.*");
 	}

+ 4 - 12
config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/InitializeUserDetailsBeanManagerConfigurer.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2019 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,7 +20,6 @@ import org.springframework.context.ApplicationContext;
 import org.springframework.core.Ordered;
 import org.springframework.core.annotation.Order;
 import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
-import org.springframework.security.authentication.password.CompromisedPasswordChecker;
 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
 import org.springframework.security.core.userdetails.UserDetailsPasswordService;
 import org.springframework.security.core.userdetails.UserDetailsService;
@@ -66,21 +65,14 @@ class InitializeUserDetailsBeanManagerConfigurer extends GlobalAuthenticationCon
 			}
 			PasswordEncoder passwordEncoder = getBeanOrNull(PasswordEncoder.class);
 			UserDetailsPasswordService passwordManager = getBeanOrNull(UserDetailsPasswordService.class);
-			CompromisedPasswordChecker passwordChecker = getBeanOrNull(CompromisedPasswordChecker.class);
-			DaoAuthenticationProvider provider;
+			DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
+			provider.setUserDetailsService(userDetailsService);
 			if (passwordEncoder != null) {
-				provider = new DaoAuthenticationProvider(passwordEncoder);
-			}
-			else {
-				provider = new DaoAuthenticationProvider();
+				provider.setPasswordEncoder(passwordEncoder);
 			}
-			provider.setUserDetailsService(userDetailsService);
 			if (passwordManager != null) {
 				provider.setUserDetailsPasswordService(passwordManager);
 			}
-			if (passwordChecker != null) {
-				provider.setCompromisedPasswordChecker(passwordChecker);
-			}
 			provider.afterPropertiesSet();
 			auth.authenticationProvider(provider);
 		}

+ 0 - 63
config/src/main/java/org/springframework/security/config/annotation/method/configuration/AuthorizationProxyConfiguration.java

@@ -1,63 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.config.annotation.method.configuration;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.aopalliance.intercept.MethodInterceptor;
-
-import org.springframework.aop.framework.AopInfrastructureBean;
-import org.springframework.beans.factory.ObjectProvider;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Role;
-import org.springframework.security.authorization.method.AuthorizationAdvisor;
-import org.springframework.security.authorization.method.AuthorizationAdvisorProxyFactory;
-import org.springframework.security.authorization.method.AuthorizeReturnObjectMethodInterceptor;
-import org.springframework.security.config.Customizer;
-
-@Configuration(proxyBeanMethods = false)
-final class AuthorizationProxyConfiguration implements AopInfrastructureBean {
-
-	@Bean
-	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-	static AuthorizationAdvisorProxyFactory authorizationProxyFactory(ObjectProvider<AuthorizationAdvisor> provider,
-			ObjectProvider<Customizer<AuthorizationAdvisorProxyFactory>> customizers) {
-		List<AuthorizationAdvisor> advisors = new ArrayList<>();
-		provider.forEach(advisors::add);
-		AuthorizationAdvisorProxyFactory factory = AuthorizationAdvisorProxyFactory.withDefaults();
-		customizers.forEach((c) -> c.customize(factory));
-		factory.setAdvisors(advisors);
-		return factory;
-	}
-
-	@Bean
-	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-	static MethodInterceptor authorizeReturnObjectMethodInterceptor(ObjectProvider<AuthorizationAdvisor> provider,
-			AuthorizationAdvisorProxyFactory authorizationProxyFactory) {
-		AuthorizeReturnObjectMethodInterceptor interceptor = new AuthorizeReturnObjectMethodInterceptor(
-				authorizationProxyFactory);
-		List<AuthorizationAdvisor> advisors = new ArrayList<>();
-		provider.forEach(advisors::add);
-		advisors.add(interceptor);
-		authorizationProxyFactory.setAdvisors(advisors);
-		return interceptor;
-	}
-
-}

+ 1 - 23
config/src/main/java/org/springframework/security/config/annotation/method/configuration/DeferringObservationAuthorizationManager.java

@@ -19,26 +19,18 @@ package org.springframework.security.config.annotation.method.configuration;
 import java.util.function.Supplier;
 
 import io.micrometer.observation.ObservationRegistry;
-import org.aopalliance.intercept.MethodInvocation;
 
 import org.springframework.beans.factory.ObjectProvider;
 import org.springframework.security.authorization.AuthorizationDecision;
 import org.springframework.security.authorization.AuthorizationManager;
-import org.springframework.security.authorization.AuthorizationResult;
 import org.springframework.security.authorization.ObservationAuthorizationManager;
-import org.springframework.security.authorization.method.MethodAuthorizationDeniedHandler;
-import org.springframework.security.authorization.method.MethodInvocationResult;
-import org.springframework.security.authorization.method.ThrowingMethodAuthorizationDeniedHandler;
 import org.springframework.security.core.Authentication;
 import org.springframework.util.function.SingletonSupplier;
 
-final class DeferringObservationAuthorizationManager<T>
-		implements AuthorizationManager<T>, MethodAuthorizationDeniedHandler {
+final class DeferringObservationAuthorizationManager<T> implements AuthorizationManager<T> {
 
 	private final Supplier<AuthorizationManager<T>> delegate;
 
-	private MethodAuthorizationDeniedHandler handler = new ThrowingMethodAuthorizationDeniedHandler();
-
 	DeferringObservationAuthorizationManager(ObjectProvider<ObservationRegistry> provider,
 			AuthorizationManager<T> delegate) {
 		this.delegate = SingletonSupplier.of(() -> {
@@ -48,9 +40,6 @@ final class DeferringObservationAuthorizationManager<T>
 			}
 			return new ObservationAuthorizationManager<>(registry, delegate);
 		});
-		if (delegate instanceof MethodAuthorizationDeniedHandler h) {
-			this.handler = h;
-		}
 	}
 
 	@Override
@@ -58,15 +47,4 @@ final class DeferringObservationAuthorizationManager<T>
 		return this.delegate.get().check(authentication, object);
 	}
 
-	@Override
-	public Object handleDeniedInvocation(MethodInvocation methodInvocation, AuthorizationResult authorizationResult) {
-		return this.handler.handleDeniedInvocation(methodInvocation, authorizationResult);
-	}
-
-	@Override
-	public Object handleDeniedInvocationResult(MethodInvocationResult methodInvocationResult,
-			AuthorizationResult authorizationResult) {
-		return this.handler.handleDeniedInvocationResult(methodInvocationResult, authorizationResult);
-	}
-
 }

+ 1 - 23
config/src/main/java/org/springframework/security/config/annotation/method/configuration/DeferringObservationReactiveAuthorizationManager.java

@@ -19,27 +19,19 @@ package org.springframework.security.config.annotation.method.configuration;
 import java.util.function.Supplier;
 
 import io.micrometer.observation.ObservationRegistry;
-import org.aopalliance.intercept.MethodInvocation;
 import reactor.core.publisher.Mono;
 
 import org.springframework.beans.factory.ObjectProvider;
 import org.springframework.security.authorization.AuthorizationDecision;
-import org.springframework.security.authorization.AuthorizationResult;
 import org.springframework.security.authorization.ObservationReactiveAuthorizationManager;
 import org.springframework.security.authorization.ReactiveAuthorizationManager;
-import org.springframework.security.authorization.method.MethodAuthorizationDeniedHandler;
-import org.springframework.security.authorization.method.MethodInvocationResult;
-import org.springframework.security.authorization.method.ThrowingMethodAuthorizationDeniedHandler;
 import org.springframework.security.core.Authentication;
 import org.springframework.util.function.SingletonSupplier;
 
-final class DeferringObservationReactiveAuthorizationManager<T>
-		implements ReactiveAuthorizationManager<T>, MethodAuthorizationDeniedHandler {
+final class DeferringObservationReactiveAuthorizationManager<T> implements ReactiveAuthorizationManager<T> {
 
 	private final Supplier<ReactiveAuthorizationManager<T>> delegate;
 
-	private MethodAuthorizationDeniedHandler handler = new ThrowingMethodAuthorizationDeniedHandler();
-
 	DeferringObservationReactiveAuthorizationManager(ObjectProvider<ObservationRegistry> provider,
 			ReactiveAuthorizationManager<T> delegate) {
 		this.delegate = SingletonSupplier.of(() -> {
@@ -49,9 +41,6 @@ final class DeferringObservationReactiveAuthorizationManager<T>
 			}
 			return new ObservationReactiveAuthorizationManager<>(registry, delegate);
 		});
-		if (delegate instanceof MethodAuthorizationDeniedHandler h) {
-			this.handler = h;
-		}
 	}
 
 	@Override
@@ -59,15 +48,4 @@ final class DeferringObservationReactiveAuthorizationManager<T>
 		return this.delegate.get().check(authentication, object);
 	}
 
-	@Override
-	public Object handleDeniedInvocation(MethodInvocation methodInvocation, AuthorizationResult authorizationResult) {
-		return this.handler.handleDeniedInvocation(methodInvocation, authorizationResult);
-	}
-
-	@Override
-	public Object handleDeniedInvocationResult(MethodInvocationResult methodInvocationResult,
-			AuthorizationResult authorizationResult) {
-		return this.handler.handleDeniedInvocationResult(methodInvocationResult, authorizationResult);
-	}
-
 }

+ 1 - 11
config/src/main/java/org/springframework/security/config/annotation/method/configuration/EnableMethodSecurity.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2023 the original author or authors.
+ * Copyright 2002-2021 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -87,14 +87,4 @@ public @interface EnableMethodSecurity {
 	 */
 	AdviceMode mode() default AdviceMode.PROXY;
 
-	/**
-	 * Indicate additional offset in the ordering of the execution of the security
-	 * interceptors when multiple advices are applied at a specific joinpoint. I.e.,
-	 * precedence of each security interceptor enabled by this annotation will be
-	 * calculated as sum of its default precedence and offset. The default is 0.
-	 * @return the offset in the order the security advisor should be applied
-	 * @since 6.3
-	 */
-	int offset() default 0;
-
 }

+ 3 - 26
config/src/main/java/org/springframework/security/config/annotation/method/configuration/Jsr250MethodSecurityConfiguration.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2023 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,18 +20,11 @@ import io.micrometer.observation.ObservationRegistry;
 import org.aopalliance.intercept.MethodInterceptor;
 import org.aopalliance.intercept.MethodInvocation;
 
-import org.springframework.aop.framework.AopInfrastructureBean;
 import org.springframework.beans.factory.ObjectProvider;
 import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.ImportAware;
 import org.springframework.context.annotation.Role;
-import org.springframework.core.type.AnnotationMetadata;
-import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy;
-import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
-import org.springframework.security.authorization.AuthoritiesAuthorizationManager;
-import org.springframework.security.authorization.AuthorizationEventPublisher;
 import org.springframework.security.authorization.AuthorizationManager;
 import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
 import org.springframework.security.authorization.method.Jsr250AuthorizationManager;
@@ -49,23 +42,15 @@ import org.springframework.security.core.context.SecurityContextHolderStrategy;
  */
 @Configuration(proxyBeanMethods = false)
 @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-final class Jsr250MethodSecurityConfiguration implements ImportAware, AopInfrastructureBean {
-
-	private int interceptorOrderOffset;
+final class Jsr250MethodSecurityConfiguration {
 
 	@Bean
 	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
 	static MethodInterceptor jsr250AuthorizationMethodInterceptor(
 			ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
 			ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
-			ObjectProvider<AuthorizationEventPublisher> eventPublisherProvider,
-			ObjectProvider<ObservationRegistry> registryProvider, ObjectProvider<RoleHierarchy> roleHierarchyProvider,
-			Jsr250MethodSecurityConfiguration configuration) {
+			ObjectProvider<ObservationRegistry> registryProvider) {
 		Jsr250AuthorizationManager jsr250 = new Jsr250AuthorizationManager();
-		AuthoritiesAuthorizationManager authoritiesAuthorizationManager = new AuthoritiesAuthorizationManager();
-		RoleHierarchy roleHierarchy = roleHierarchyProvider.getIfAvailable(NullRoleHierarchy::new);
-		authoritiesAuthorizationManager.setRoleHierarchy(roleHierarchy);
-		jsr250.setAuthoritiesAuthorizationManager(authoritiesAuthorizationManager);
 		defaultsProvider.ifAvailable((d) -> jsr250.setRolePrefix(d.getRolePrefix()));
 		SecurityContextHolderStrategy strategy = strategyProvider
 			.getIfAvailable(SecurityContextHolder::getContextHolderStrategy);
@@ -73,16 +58,8 @@ final class Jsr250MethodSecurityConfiguration implements ImportAware, AopInfrast
 				registryProvider, jsr250);
 		AuthorizationManagerBeforeMethodInterceptor interceptor = AuthorizationManagerBeforeMethodInterceptor
 			.jsr250(manager);
-		interceptor.setOrder(interceptor.getOrder() + configuration.interceptorOrderOffset);
 		interceptor.setSecurityContextHolderStrategy(strategy);
-		eventPublisherProvider.ifAvailable(interceptor::setAuthorizationEventPublisher);
 		return interceptor;
 	}
 
-	@Override
-	public void setImportMetadata(AnnotationMetadata importMetadata) {
-		EnableMethodSecurity annotation = importMetadata.getAnnotations().get(EnableMethodSecurity.class).synthesize();
-		this.interceptorOrderOffset = annotation.offset();
-	}
-
 }

+ 0 - 1
config/src/main/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityAdvisorRegistrar.java

@@ -33,7 +33,6 @@ class MethodSecurityAdvisorRegistrar implements ImportBeanDefinitionRegistrar {
 		registerAsAdvisor("postAuthorizeAuthorization", registry);
 		registerAsAdvisor("securedAuthorization", registry);
 		registerAsAdvisor("jsr250Authorization", registry);
-		registerAsAdvisor("authorizeReturnObject", registry);
 	}
 
 	private void registerAsAdvisor(String prefix, BeanDefinitionRegistry registry) {

+ 1 - 2
config/src/main/java/org/springframework/security/config/annotation/method/configuration/MethodSecuritySelector.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2023 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -56,7 +56,6 @@ final class MethodSecuritySelector implements ImportSelector {
 		if (annotation.jsr250Enabled()) {
 			imports.add(Jsr250MethodSecurityConfiguration.class.getName());
 		}
-		imports.add(AuthorizationProxyConfiguration.class.getName());
 		return imports.toArray(new String[0]);
 	}
 

+ 47 - 97
config/src/main/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfiguration.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2023 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,41 +16,33 @@
 
 package org.springframework.security.config.annotation.method.configuration;
 
-import java.util.function.Consumer;
 import java.util.function.Supplier;
 
 import io.micrometer.observation.ObservationRegistry;
-import org.aopalliance.aop.Advice;
 import org.aopalliance.intercept.MethodInterceptor;
 import org.aopalliance.intercept.MethodInvocation;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
-import org.springframework.aop.Pointcut;
-import org.springframework.aop.framework.AopInfrastructureBean;
 import org.springframework.beans.factory.ObjectProvider;
 import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.ImportAware;
 import org.springframework.context.annotation.Role;
-import org.springframework.core.type.AnnotationMetadata;
+import org.springframework.expression.EvaluationContext;
+import org.springframework.expression.Expression;
+import org.springframework.expression.ExpressionParser;
 import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
 import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
-import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy;
-import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
 import org.springframework.security.authorization.AuthorizationEventPublisher;
 import org.springframework.security.authorization.AuthorizationManager;
-import org.springframework.security.authorization.method.AuthorizationAdvisor;
 import org.springframework.security.authorization.method.AuthorizationManagerAfterMethodInterceptor;
 import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
 import org.springframework.security.authorization.method.PostAuthorizeAuthorizationManager;
 import org.springframework.security.authorization.method.PostFilterAuthorizationMethodInterceptor;
 import org.springframework.security.authorization.method.PreAuthorizeAuthorizationManager;
 import org.springframework.security.authorization.method.PreFilterAuthorizationMethodInterceptor;
-import org.springframework.security.authorization.method.PrePostTemplateDefaults;
 import org.springframework.security.config.core.GrantedAuthorityDefaults;
+import org.springframework.security.core.Authentication;
 import org.springframework.security.core.context.SecurityContextHolderStrategy;
 import org.springframework.util.function.SingletonSupplier;
 
@@ -64,102 +56,73 @@ import org.springframework.util.function.SingletonSupplier;
  */
 @Configuration(proxyBeanMethods = false)
 @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-final class PrePostMethodSecurityConfiguration implements ImportAware, AopInfrastructureBean {
-
-	private int interceptorOrderOffset;
+final class PrePostMethodSecurityConfiguration {
 
 	@Bean
 	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
 	static MethodInterceptor preFilterAuthorizationMethodInterceptor(
 			ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
-			ObjectProvider<PrePostTemplateDefaults> methodSecurityDefaultsProvider,
 			ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
-			ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
-			ObjectProvider<RoleHierarchy> roleHierarchyProvider, PrePostMethodSecurityConfiguration configuration,
-			ApplicationContext context) {
+			ObjectProvider<SecurityContextHolderStrategy> strategyProvider, ApplicationContext context) {
 		PreFilterAuthorizationMethodInterceptor preFilter = new PreFilterAuthorizationMethodInterceptor();
-		preFilter.setOrder(preFilter.getOrder() + configuration.interceptorOrderOffset);
-		return new DeferringMethodInterceptor<>(preFilter, (f) -> {
-			methodSecurityDefaultsProvider.ifAvailable(f::setTemplateDefaults);
-			f.setExpressionHandler(expressionHandlerProvider
-				.getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, roleHierarchyProvider, context)));
-			strategyProvider.ifAvailable(f::setSecurityContextHolderStrategy);
-		});
+		strategyProvider.ifAvailable(preFilter::setSecurityContextHolderStrategy);
+		preFilter.setExpressionHandler(
+				new DeferringMethodSecurityExpressionHandler(expressionHandlerProvider, defaultsProvider, context));
+		return preFilter;
 	}
 
 	@Bean
 	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
 	static MethodInterceptor preAuthorizeAuthorizationMethodInterceptor(
 			ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
-			ObjectProvider<PrePostTemplateDefaults> methodSecurityDefaultsProvider,
 			ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
 			ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
 			ObjectProvider<AuthorizationEventPublisher> eventPublisherProvider,
-			ObjectProvider<ObservationRegistry> registryProvider, ObjectProvider<RoleHierarchy> roleHierarchyProvider,
-			PrePostMethodSecurityConfiguration configuration, ApplicationContext context) {
+			ObjectProvider<ObservationRegistry> registryProvider, ApplicationContext context) {
 		PreAuthorizeAuthorizationManager manager = new PreAuthorizeAuthorizationManager();
-		manager.setApplicationContext(context);
+		manager.setExpressionHandler(
+				new DeferringMethodSecurityExpressionHandler(expressionHandlerProvider, defaultsProvider, context));
 		AuthorizationManagerBeforeMethodInterceptor preAuthorize = AuthorizationManagerBeforeMethodInterceptor
 			.preAuthorize(manager(manager, registryProvider));
-		preAuthorize.setOrder(preAuthorize.getOrder() + configuration.interceptorOrderOffset);
-		return new DeferringMethodInterceptor<>(preAuthorize, (f) -> {
-			methodSecurityDefaultsProvider.ifAvailable(manager::setTemplateDefaults);
-			manager.setExpressionHandler(expressionHandlerProvider
-				.getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, roleHierarchyProvider, context)));
-			strategyProvider.ifAvailable(f::setSecurityContextHolderStrategy);
-			eventPublisherProvider.ifAvailable(f::setAuthorizationEventPublisher);
-		});
+		strategyProvider.ifAvailable(preAuthorize::setSecurityContextHolderStrategy);
+		eventPublisherProvider.ifAvailable(preAuthorize::setAuthorizationEventPublisher);
+		return preAuthorize;
 	}
 
 	@Bean
 	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
 	static MethodInterceptor postAuthorizeAuthorizationMethodInterceptor(
 			ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
-			ObjectProvider<PrePostTemplateDefaults> methodSecurityDefaultsProvider,
 			ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
 			ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
 			ObjectProvider<AuthorizationEventPublisher> eventPublisherProvider,
-			ObjectProvider<ObservationRegistry> registryProvider, ObjectProvider<RoleHierarchy> roleHierarchyProvider,
-			PrePostMethodSecurityConfiguration configuration, ApplicationContext context) {
+			ObjectProvider<ObservationRegistry> registryProvider, ApplicationContext context) {
 		PostAuthorizeAuthorizationManager manager = new PostAuthorizeAuthorizationManager();
-		manager.setApplicationContext(context);
+		manager.setExpressionHandler(
+				new DeferringMethodSecurityExpressionHandler(expressionHandlerProvider, defaultsProvider, context));
 		AuthorizationManagerAfterMethodInterceptor postAuthorize = AuthorizationManagerAfterMethodInterceptor
 			.postAuthorize(manager(manager, registryProvider));
-		postAuthorize.setOrder(postAuthorize.getOrder() + configuration.interceptorOrderOffset);
-		return new DeferringMethodInterceptor<>(postAuthorize, (f) -> {
-			methodSecurityDefaultsProvider.ifAvailable(manager::setTemplateDefaults);
-			manager.setExpressionHandler(expressionHandlerProvider
-				.getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, roleHierarchyProvider, context)));
-			strategyProvider.ifAvailable(f::setSecurityContextHolderStrategy);
-			eventPublisherProvider.ifAvailable(f::setAuthorizationEventPublisher);
-		});
+		strategyProvider.ifAvailable(postAuthorize::setSecurityContextHolderStrategy);
+		eventPublisherProvider.ifAvailable(postAuthorize::setAuthorizationEventPublisher);
+		return postAuthorize;
 	}
 
 	@Bean
 	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
 	static MethodInterceptor postFilterAuthorizationMethodInterceptor(
 			ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
-			ObjectProvider<PrePostTemplateDefaults> methodSecurityDefaultsProvider,
 			ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
-			ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
-			ObjectProvider<RoleHierarchy> roleHierarchyProvider, PrePostMethodSecurityConfiguration configuration,
-			ApplicationContext context) {
+			ObjectProvider<SecurityContextHolderStrategy> strategyProvider, ApplicationContext context) {
 		PostFilterAuthorizationMethodInterceptor postFilter = new PostFilterAuthorizationMethodInterceptor();
-		postFilter.setOrder(postFilter.getOrder() + configuration.interceptorOrderOffset);
-		return new DeferringMethodInterceptor<>(postFilter, (f) -> {
-			methodSecurityDefaultsProvider.ifAvailable(f::setTemplateDefaults);
-			f.setExpressionHandler(expressionHandlerProvider
-				.getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, roleHierarchyProvider, context)));
-			strategyProvider.ifAvailable(f::setSecurityContextHolderStrategy);
-		});
+		strategyProvider.ifAvailable(postFilter::setSecurityContextHolderStrategy);
+		postFilter.setExpressionHandler(
+				new DeferringMethodSecurityExpressionHandler(expressionHandlerProvider, defaultsProvider, context));
+		return postFilter;
 	}
 
 	private static MethodSecurityExpressionHandler defaultExpressionHandler(
-			ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
-			ObjectProvider<RoleHierarchy> roleHierarchyProvider, ApplicationContext context) {
+			ObjectProvider<GrantedAuthorityDefaults> defaultsProvider, ApplicationContext context) {
 		DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler();
-		RoleHierarchy roleHierarchy = roleHierarchyProvider.getIfAvailable(NullRoleHierarchy::new);
-		handler.setRoleHierarchy(roleHierarchy);
 		defaultsProvider.ifAvailable((d) -> handler.setDefaultRolePrefix(d.getRolePrefix()));
 		handler.setApplicationContext(context);
 		return handler;
@@ -170,54 +133,41 @@ final class PrePostMethodSecurityConfiguration implements ImportAware, AopInfras
 		return new DeferringObservationAuthorizationManager<>(registryProvider, delegate);
 	}
 
-	@Override
-	public void setImportMetadata(AnnotationMetadata importMetadata) {
-		EnableMethodSecurity annotation = importMetadata.getAnnotations().get(EnableMethodSecurity.class).synthesize();
-		this.interceptorOrderOffset = annotation.offset();
-	}
-
-	private static final class DeferringMethodInterceptor<M extends AuthorizationAdvisor>
-			implements AuthorizationAdvisor {
-
-		private final Pointcut pointcut;
-
-		private final int order;
+	private static final class DeferringMethodSecurityExpressionHandler implements MethodSecurityExpressionHandler {
 
-		private final Supplier<M> delegate;
+		private final Supplier<MethodSecurityExpressionHandler> expressionHandler;
 
-		DeferringMethodInterceptor(M delegate, Consumer<M> supplier) {
-			this.pointcut = delegate.getPointcut();
-			this.order = delegate.getOrder();
-			this.delegate = SingletonSupplier.of(() -> {
-				supplier.accept(delegate);
-				return delegate;
-			});
+		private DeferringMethodSecurityExpressionHandler(
+				ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
+				ObjectProvider<GrantedAuthorityDefaults> defaultsProvider, ApplicationContext applicationContext) {
+			this.expressionHandler = SingletonSupplier.of(() -> expressionHandlerProvider
+				.getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, applicationContext)));
 		}
 
-		@Nullable
 		@Override
-		public Object invoke(@NotNull MethodInvocation invocation) throws Throwable {
-			return this.delegate.get().invoke(invocation);
+		public ExpressionParser getExpressionParser() {
+			return this.expressionHandler.get().getExpressionParser();
 		}
 
 		@Override
-		public Pointcut getPointcut() {
-			return this.pointcut;
+		public EvaluationContext createEvaluationContext(Authentication authentication, MethodInvocation invocation) {
+			return this.expressionHandler.get().createEvaluationContext(authentication, invocation);
 		}
 
 		@Override
-		public Advice getAdvice() {
-			return this;
+		public EvaluationContext createEvaluationContext(Supplier<Authentication> authentication,
+				MethodInvocation invocation) {
+			return this.expressionHandler.get().createEvaluationContext(authentication, invocation);
 		}
 
 		@Override
-		public int getOrder() {
-			return this.order;
+		public Object filter(Object filterTarget, Expression filterExpression, EvaluationContext ctx) {
+			return this.expressionHandler.get().filter(filterTarget, filterExpression, ctx);
 		}
 
 		@Override
-		public boolean isPerInstance() {
-			return true;
+		public void setReturnObject(Object returnObject, EvaluationContext ctx) {
+			this.expressionHandler.get().setReturnObject(returnObject, ctx);
 		}
 
 	}

+ 18 - 97
config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveAuthorizationManagerMethodSecurityConfiguration.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2023 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,22 +16,12 @@
 
 package org.springframework.security.config.annotation.method.configuration;
 
-import java.util.function.Consumer;
-import java.util.function.Supplier;
-
 import io.micrometer.observation.ObservationRegistry;
-import org.aopalliance.aop.Advice;
-import org.aopalliance.intercept.MethodInterceptor;
 import org.aopalliance.intercept.MethodInvocation;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
-import org.springframework.aop.Pointcut;
-import org.springframework.aop.framework.AopInfrastructureBean;
 import org.springframework.beans.factory.ObjectProvider;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Role;
@@ -39,7 +29,6 @@ import org.springframework.security.access.expression.method.DefaultMethodSecuri
 import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
 import org.springframework.security.authentication.ReactiveAuthenticationManager;
 import org.springframework.security.authorization.ReactiveAuthorizationManager;
-import org.springframework.security.authorization.method.AuthorizationAdvisor;
 import org.springframework.security.authorization.method.AuthorizationManagerAfterReactiveMethodInterceptor;
 import org.springframework.security.authorization.method.AuthorizationManagerBeforeReactiveMethodInterceptor;
 import org.springframework.security.authorization.method.MethodInvocationResult;
@@ -47,9 +36,7 @@ import org.springframework.security.authorization.method.PostAuthorizeReactiveAu
 import org.springframework.security.authorization.method.PostFilterAuthorizationReactiveMethodInterceptor;
 import org.springframework.security.authorization.method.PreAuthorizeReactiveAuthorizationManager;
 import org.springframework.security.authorization.method.PreFilterAuthorizationReactiveMethodInterceptor;
-import org.springframework.security.authorization.method.PrePostTemplateDefaults;
 import org.springframework.security.config.core.GrantedAuthorityDefaults;
-import org.springframework.util.function.SingletonSupplier;
 
 /**
  * Configuration for a {@link ReactiveAuthenticationManager} based Method Security.
@@ -58,58 +45,38 @@ import org.springframework.util.function.SingletonSupplier;
  * @since 5.8
  */
 @Configuration(proxyBeanMethods = false)
-final class ReactiveAuthorizationManagerMethodSecurityConfiguration implements AopInfrastructureBean {
+final class ReactiveAuthorizationManagerMethodSecurityConfiguration {
 
 	@Bean
 	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-	static MethodInterceptor preFilterAuthorizationMethodInterceptor(MethodSecurityExpressionHandler expressionHandler,
-			ObjectProvider<PrePostTemplateDefaults> defaultsObjectProvider) {
-		PreFilterAuthorizationReactiveMethodInterceptor interceptor = new PreFilterAuthorizationReactiveMethodInterceptor(
-				expressionHandler);
-		return new DeferringMethodInterceptor<>(interceptor,
-				(i) -> defaultsObjectProvider.ifAvailable(i::setTemplateDefaults));
+	static PreFilterAuthorizationReactiveMethodInterceptor preFilterInterceptor(
+			MethodSecurityExpressionHandler expressionHandler) {
+		return new PreFilterAuthorizationReactiveMethodInterceptor(expressionHandler);
 	}
 
 	@Bean
 	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-	static MethodInterceptor preAuthorizeAuthorizationMethodInterceptor(
-			MethodSecurityExpressionHandler expressionHandler,
-			ObjectProvider<PrePostTemplateDefaults> defaultsObjectProvider,
-			ObjectProvider<ObservationRegistry> registryProvider, ApplicationContext context) {
-		PreAuthorizeReactiveAuthorizationManager manager = new PreAuthorizeReactiveAuthorizationManager(
-				expressionHandler);
-		manager.setApplicationContext(context);
-		ReactiveAuthorizationManager<MethodInvocation> authorizationManager = manager(manager, registryProvider);
-		AuthorizationAdvisor interceptor = AuthorizationManagerBeforeReactiveMethodInterceptor
-			.preAuthorize(authorizationManager);
-		return new DeferringMethodInterceptor<>(interceptor,
-				(i) -> defaultsObjectProvider.ifAvailable(manager::setTemplateDefaults));
+	static AuthorizationManagerBeforeReactiveMethodInterceptor preAuthorizeInterceptor(
+			MethodSecurityExpressionHandler expressionHandler, ObjectProvider<ObservationRegistry> registryProvider) {
+		ReactiveAuthorizationManager<MethodInvocation> authorizationManager = manager(
+				new PreAuthorizeReactiveAuthorizationManager(expressionHandler), registryProvider);
+		return AuthorizationManagerBeforeReactiveMethodInterceptor.preAuthorize(authorizationManager);
 	}
 
 	@Bean
 	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-	static MethodInterceptor postFilterAuthorizationMethodInterceptor(MethodSecurityExpressionHandler expressionHandler,
-			ObjectProvider<PrePostTemplateDefaults> defaultsObjectProvider) {
-		PostFilterAuthorizationReactiveMethodInterceptor interceptor = new PostFilterAuthorizationReactiveMethodInterceptor(
-				expressionHandler);
-		return new DeferringMethodInterceptor<>(interceptor,
-				(i) -> defaultsObjectProvider.ifAvailable(i::setTemplateDefaults));
+	static PostFilterAuthorizationReactiveMethodInterceptor postFilterInterceptor(
+			MethodSecurityExpressionHandler expressionHandler) {
+		return new PostFilterAuthorizationReactiveMethodInterceptor(expressionHandler);
 	}
 
 	@Bean
 	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-	static MethodInterceptor postAuthorizeAuthorizationMethodInterceptor(
-			MethodSecurityExpressionHandler expressionHandler,
-			ObjectProvider<PrePostTemplateDefaults> defaultsObjectProvider,
-			ObjectProvider<ObservationRegistry> registryProvider, ApplicationContext context) {
-		PostAuthorizeReactiveAuthorizationManager manager = new PostAuthorizeReactiveAuthorizationManager(
-				expressionHandler);
-		manager.setApplicationContext(context);
-		ReactiveAuthorizationManager<MethodInvocationResult> authorizationManager = manager(manager, registryProvider);
-		AuthorizationAdvisor interceptor = AuthorizationManagerAfterReactiveMethodInterceptor
-			.postAuthorize(authorizationManager);
-		return new DeferringMethodInterceptor<>(interceptor,
-				(i) -> defaultsObjectProvider.ifAvailable(manager::setTemplateDefaults));
+	static AuthorizationManagerAfterReactiveMethodInterceptor postAuthorizeInterceptor(
+			MethodSecurityExpressionHandler expressionHandler, ObjectProvider<ObservationRegistry> registryProvider) {
+		ReactiveAuthorizationManager<MethodInvocationResult> authorizationManager = manager(
+				new PostAuthorizeReactiveAuthorizationManager(expressionHandler), registryProvider);
+		return AuthorizationManagerAfterReactiveMethodInterceptor.postAuthorize(authorizationManager);
 	}
 
 	@Bean
@@ -128,50 +95,4 @@ final class ReactiveAuthorizationManagerMethodSecurityConfiguration implements A
 		return new DeferringObservationReactiveAuthorizationManager<>(registryProvider, delegate);
 	}
 
-	private static final class DeferringMethodInterceptor<M extends AuthorizationAdvisor>
-			implements AuthorizationAdvisor {
-
-		private final Pointcut pointcut;
-
-		private final int order;
-
-		private final Supplier<M> delegate;
-
-		DeferringMethodInterceptor(M delegate, Consumer<M> supplier) {
-			this.pointcut = delegate.getPointcut();
-			this.order = delegate.getOrder();
-			this.delegate = SingletonSupplier.of(() -> {
-				supplier.accept(delegate);
-				return delegate;
-			});
-		}
-
-		@Nullable
-		@Override
-		public Object invoke(@NotNull MethodInvocation invocation) throws Throwable {
-			return this.delegate.get().invoke(invocation);
-		}
-
-		@Override
-		public Pointcut getPointcut() {
-			return this.pointcut;
-		}
-
-		@Override
-		public Advice getAdvice() {
-			return this;
-		}
-
-		@Override
-		public int getOrder() {
-			return this.order;
-		}
-
-		@Override
-		public boolean isPerInstance() {
-			return true;
-		}
-
-	}
-
 }

+ 0 - 63
config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveAuthorizationProxyConfiguration.java

@@ -1,63 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.config.annotation.method.configuration;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.aopalliance.intercept.MethodInterceptor;
-
-import org.springframework.aop.framework.AopInfrastructureBean;
-import org.springframework.beans.factory.ObjectProvider;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Role;
-import org.springframework.security.authorization.method.AuthorizationAdvisor;
-import org.springframework.security.authorization.method.AuthorizationAdvisorProxyFactory;
-import org.springframework.security.authorization.method.AuthorizeReturnObjectMethodInterceptor;
-import org.springframework.security.config.Customizer;
-
-@Configuration(proxyBeanMethods = false)
-final class ReactiveAuthorizationProxyConfiguration implements AopInfrastructureBean {
-
-	@Bean
-	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-	static AuthorizationAdvisorProxyFactory authorizationProxyFactory(ObjectProvider<AuthorizationAdvisor> provider,
-			ObjectProvider<Customizer<AuthorizationAdvisorProxyFactory>> customizers) {
-		List<AuthorizationAdvisor> advisors = new ArrayList<>();
-		provider.forEach(advisors::add);
-		AuthorizationAdvisorProxyFactory factory = AuthorizationAdvisorProxyFactory.withReactiveDefaults();
-		customizers.forEach((c) -> c.customize(factory));
-		factory.setAdvisors(advisors);
-		return factory;
-	}
-
-	@Bean
-	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-	static MethodInterceptor authorizeReturnObjectMethodInterceptor(ObjectProvider<AuthorizationAdvisor> provider,
-			AuthorizationAdvisorProxyFactory authorizationProxyFactory) {
-		AuthorizeReturnObjectMethodInterceptor interceptor = new AuthorizeReturnObjectMethodInterceptor(
-				authorizationProxyFactory);
-		List<AuthorizationAdvisor> advisors = new ArrayList<>();
-		provider.forEach(advisors::add);
-		advisors.add(interceptor);
-		authorizationProxyFactory.setAdvisors(advisors);
-		return interceptor;
-	}
-
-}

+ 1 - 3
config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecuritySelector.java

@@ -51,15 +51,13 @@ class ReactiveMethodSecuritySelector implements ImportSelector {
 		else {
 			imports.add(ReactiveMethodSecurityConfiguration.class.getName());
 		}
-		imports.add(ReactiveAuthorizationProxyConfiguration.class.getName());
 		return imports.toArray(new String[0]);
 	}
 
 	private static final class AutoProxyRegistrarSelector
 			extends AdviceModeImportSelector<EnableReactiveMethodSecurity> {
 
-		private static final String[] IMPORTS = new String[] { AutoProxyRegistrar.class.getName(),
-				MethodSecurityAdvisorRegistrar.class.getName() };
+		private static final String[] IMPORTS = new String[] { AutoProxyRegistrar.class.getName() };
 
 		@Override
 		protected String[] selectImports(@NonNull AdviceMode adviceMode) {

+ 3 - 26
config/src/main/java/org/springframework/security/config/annotation/method/configuration/SecuredMethodSecurityConfiguration.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2023 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,19 +20,12 @@ import io.micrometer.observation.ObservationRegistry;
 import org.aopalliance.intercept.MethodInterceptor;
 import org.aopalliance.intercept.MethodInvocation;
 
-import org.springframework.aop.framework.AopInfrastructureBean;
 import org.springframework.beans.factory.ObjectProvider;
 import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.ImportAware;
 import org.springframework.context.annotation.Role;
-import org.springframework.core.type.AnnotationMetadata;
 import org.springframework.security.access.annotation.Secured;
-import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy;
-import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
-import org.springframework.security.authorization.AuthoritiesAuthorizationManager;
-import org.springframework.security.authorization.AuthorizationEventPublisher;
 import org.springframework.security.authorization.AuthorizationManager;
 import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
 import org.springframework.security.authorization.method.SecuredAuthorizationManager;
@@ -49,38 +42,22 @@ import org.springframework.security.core.context.SecurityContextHolderStrategy;
  */
 @Configuration(proxyBeanMethods = false)
 @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-final class SecuredMethodSecurityConfiguration implements ImportAware, AopInfrastructureBean {
-
-	private int interceptorOrderOffset;
+final class SecuredMethodSecurityConfiguration {
 
 	@Bean
 	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
 	static MethodInterceptor securedAuthorizationMethodInterceptor(
 			ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
-			ObjectProvider<AuthorizationEventPublisher> eventPublisherProvider,
-			ObjectProvider<ObservationRegistry> registryProvider, ObjectProvider<RoleHierarchy> roleHierarchyProvider,
-			SecuredMethodSecurityConfiguration configuration) {
+			ObjectProvider<ObservationRegistry> registryProvider) {
 		SecuredAuthorizationManager secured = new SecuredAuthorizationManager();
-		AuthoritiesAuthorizationManager authoritiesAuthorizationManager = new AuthoritiesAuthorizationManager();
-		RoleHierarchy roleHierarchy = roleHierarchyProvider.getIfAvailable(NullRoleHierarchy::new);
-		authoritiesAuthorizationManager.setRoleHierarchy(roleHierarchy);
-		secured.setAuthoritiesAuthorizationManager(authoritiesAuthorizationManager);
 		SecurityContextHolderStrategy strategy = strategyProvider
 			.getIfAvailable(SecurityContextHolder::getContextHolderStrategy);
 		AuthorizationManager<MethodInvocation> manager = new DeferringObservationAuthorizationManager<>(
 				registryProvider, secured);
 		AuthorizationManagerBeforeMethodInterceptor interceptor = AuthorizationManagerBeforeMethodInterceptor
 			.secured(manager);
-		interceptor.setOrder(interceptor.getOrder() + configuration.interceptorOrderOffset);
 		interceptor.setSecurityContextHolderStrategy(strategy);
-		eventPublisherProvider.ifAvailable(interceptor::setAuthorizationEventPublisher);
 		return interceptor;
 	}
 
-	@Override
-	public void setImportMetadata(AnnotationMetadata importMetadata) {
-		EnableMethodSecurity annotation = importMetadata.getAnnotations().get(EnableMethodSecurity.class).synthesize();
-		this.interceptorOrderOffset = annotation.offset();
-	}
-
 }

+ 1 - 29
config/src/main/java/org/springframework/security/config/annotation/web/configuration/OAuth2ClientConfiguration.java

@@ -51,13 +51,11 @@ import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
 import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider;
 import org.springframework.security.oauth2.client.PasswordOAuth2AuthorizedClientProvider;
 import org.springframework.security.oauth2.client.RefreshTokenOAuth2AuthorizedClientProvider;
-import org.springframework.security.oauth2.client.TokenExchangeOAuth2AuthorizedClientProvider;
 import org.springframework.security.oauth2.client.endpoint.JwtBearerGrantRequest;
 import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
 import org.springframework.security.oauth2.client.endpoint.OAuth2ClientCredentialsGrantRequest;
 import org.springframework.security.oauth2.client.endpoint.OAuth2PasswordGrantRequest;
 import org.springframework.security.oauth2.client.endpoint.OAuth2RefreshTokenGrantRequest;
-import org.springframework.security.oauth2.client.endpoint.TokenExchangeGrantRequest;
 import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
 import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager;
 import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
@@ -185,8 +183,7 @@ final class OAuth2ClientConfiguration {
 				RefreshTokenOAuth2AuthorizedClientProvider.class,
 				ClientCredentialsOAuth2AuthorizedClientProvider.class,
 				PasswordOAuth2AuthorizedClientProvider.class,
-				JwtBearerOAuth2AuthorizedClientProvider.class,
-				TokenExchangeOAuth2AuthorizedClientProvider.class
+				JwtBearerOAuth2AuthorizedClientProvider.class
 		);
 		// @formatter:on
 
@@ -258,12 +255,6 @@ final class OAuth2ClientConfiguration {
 					authorizedClientProviders.add(jwtBearerAuthorizedClientProvider);
 				}
 
-				OAuth2AuthorizedClientProvider tokenExchangeAuthorizedClientProvider = getTokenExchangeAuthorizedClientProvider(
-						authorizedClientProviderBeans);
-				if (tokenExchangeAuthorizedClientProvider != null) {
-					authorizedClientProviders.add(tokenExchangeAuthorizedClientProvider);
-				}
-
 				authorizedClientProviders.addAll(getAdditionalAuthorizedClientProviders(authorizedClientProviderBeans));
 				authorizedClientProvider = new DelegatingOAuth2AuthorizedClientProvider(authorizedClientProviders);
 			}
@@ -373,25 +364,6 @@ final class OAuth2ClientConfiguration {
 			return authorizedClientProvider;
 		}
 
-		private OAuth2AuthorizedClientProvider getTokenExchangeAuthorizedClientProvider(
-				Collection<OAuth2AuthorizedClientProvider> authorizedClientProviders) {
-			TokenExchangeOAuth2AuthorizedClientProvider authorizedClientProvider = getAuthorizedClientProviderByType(
-					authorizedClientProviders, TokenExchangeOAuth2AuthorizedClientProvider.class);
-
-			OAuth2AccessTokenResponseClient<TokenExchangeGrantRequest> accessTokenResponseClient = getBeanOfType(
-					ResolvableType.forClassWithGenerics(OAuth2AccessTokenResponseClient.class,
-							TokenExchangeGrantRequest.class));
-			if (accessTokenResponseClient != null) {
-				if (authorizedClientProvider == null) {
-					authorizedClientProvider = new TokenExchangeOAuth2AuthorizedClientProvider();
-				}
-
-				authorizedClientProvider.setAccessTokenResponseClient(accessTokenResponseClient);
-			}
-
-			return authorizedClientProvider;
-		}
-
 		private List<OAuth2AuthorizedClientProvider> getAdditionalAuthorizedClientProviders(
 				Collection<OAuth2AuthorizedClientProvider> authorizedClientProviders) {
 			List<OAuth2AuthorizedClientProvider> additionalAuthorizedClientProviders = new ArrayList<>(

+ 1 - 69
config/src/main/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurer.java

@@ -17,7 +17,6 @@
 package org.springframework.security.config.annotation.web.configurers;
 
 import java.util.List;
-import java.util.function.Function;
 import java.util.function.Supplier;
 
 import io.micrometer.observation.ObservationRegistry;
@@ -31,14 +30,12 @@ import org.springframework.security.authorization.AuthorityAuthorizationManager;
 import org.springframework.security.authorization.AuthorizationDecision;
 import org.springframework.security.authorization.AuthorizationEventPublisher;
 import org.springframework.security.authorization.AuthorizationManager;
-import org.springframework.security.authorization.AuthorizationManagers;
 import org.springframework.security.authorization.ObservationAuthorizationManager;
 import org.springframework.security.authorization.SpringAuthorizationEventPublisher;
 import org.springframework.security.config.annotation.ObjectPostProcessor;
 import org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry;
 import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
 import org.springframework.security.config.core.GrantedAuthorityDefaults;
-import org.springframework.security.core.Authentication;
 import org.springframework.security.web.access.intercept.AuthorizationFilter;
 import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
 import org.springframework.security.web.access.intercept.RequestMatcherDelegatingAuthorizationManager;
@@ -247,14 +244,11 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
 	 * {@link RequestMatcher}s.
 	 *
 	 * @author Evgeniy Cheban
-	 * @author Josh Cummings
 	 */
 	public class AuthorizedUrl {
 
 		private final List<? extends RequestMatcher> matchers;
 
-		private boolean not;
-
 		/**
 		 * Creates an instance.
 		 * @param matchers the {@link RequestMatcher} instances to map
@@ -267,16 +261,6 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
 			return this.matchers;
 		}
 
-		/**
-		 * Negates the following authorization rule.
-		 * @return the {@link AuthorizedUrl} for further customization
-		 * @since 6.3
-		 */
-		public AuthorizedUrl not() {
-			this.not = true;
-			return this;
-		}
-
 		/**
 		 * Specify that URLs are allowed by anyone.
 		 * @return the {@link AuthorizationManagerRequestMatcherRegistry} for further
@@ -389,21 +373,6 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
 			return access(AuthenticatedAuthorizationManager.anonymous());
 		}
 
-		/**
-		 * Specify that a path variable in URL to be compared.
-		 *
-		 * <p>
-		 * For example, <pre>
-		 * requestMatchers("/user/{username}").hasVariable("username").equalTo(Authentication::getName)
-		 * </pre>
-		 * @param variable the variable in URL template to compare.
-		 * @return {@link AuthorizedUrlVariable} for further customization.
-		 * @since 6.3
-		 */
-		public AuthorizedUrlVariable hasVariable(String variable) {
-			return new AuthorizedUrlVariable(variable);
-		}
-
 		/**
 		 * Allows specifying a custom {@link AuthorizationManager}.
 		 * @param manager the {@link AuthorizationManager} to use
@@ -413,44 +382,7 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
 		public AuthorizationManagerRequestMatcherRegistry access(
 				AuthorizationManager<RequestAuthorizationContext> manager) {
 			Assert.notNull(manager, "manager cannot be null");
-			return (this.not)
-					? AuthorizeHttpRequestsConfigurer.this.addMapping(this.matchers, AuthorizationManagers.not(manager))
-					: AuthorizeHttpRequestsConfigurer.this.addMapping(this.matchers, manager);
-		}
-
-		/**
-		 * An object that allows configuring {@link RequestMatcher}s with URI path
-		 * variables
-		 *
-		 * @author Taehong Kim
-		 * @since 6.3
-		 */
-		public final class AuthorizedUrlVariable {
-
-			private final String variable;
-
-			private AuthorizedUrlVariable(String variable) {
-				this.variable = variable;
-			}
-
-			/**
-			 * Compares the value of a path variable in the URI with an `Authentication`
-			 * attribute
-			 * <p>
-			 * For example, <pre>
-			 * requestMatchers("/user/{username}").hasVariable("username").equalTo(Authentication::getName));
-			 * </pre>
-			 * @param function a function to get value from {@link Authentication}.
-			 * @return the {@link AuthorizationManagerRequestMatcherRegistry} for further
-			 * customization.
-			 */
-			public AuthorizationManagerRequestMatcherRegistry equalTo(Function<Authentication, String> function) {
-				return access((auth, requestContext) -> {
-					String value = requestContext.getVariables().get(this.variable);
-					return new AuthorizationDecision(function.apply(auth.get()).equals(value));
-				});
-			}
-
+			return AuthorizeHttpRequestsConfigurer.this.addMapping(this.matchers, manager);
 		}
 
 	}

+ 5 - 3
config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/DefaultOidcLogoutTokenValidatorFactory.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2023 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,15 +19,17 @@ package org.springframework.security.config.annotation.web.configurers.oauth2.cl
 import java.util.function.Function;
 
 import org.springframework.security.oauth2.client.registration.ClientRegistration;
+import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
 import org.springframework.security.oauth2.core.OAuth2TokenValidator;
 import org.springframework.security.oauth2.jwt.Jwt;
-import org.springframework.security.oauth2.jwt.JwtValidators;
+import org.springframework.security.oauth2.jwt.JwtTimestampValidator;
 
 final class DefaultOidcLogoutTokenValidatorFactory implements Function<ClientRegistration, OAuth2TokenValidator<Jwt>> {
 
 	@Override
 	public OAuth2TokenValidator<Jwt> apply(ClientRegistration clientRegistration) {
-		return JwtValidators.createDefaultWithValidators(new OidcBackChannelLogoutTokenValidator(clientRegistration));
+		return new DelegatingOAuth2TokenValidator<>(new JwtTimestampValidator(),
+				new OidcBackChannelLogoutTokenValidator(clientRegistration));
 	}
 
 }

+ 0 - 413
config/src/main/java/org/springframework/security/config/annotation/web/reactive/ReactiveOAuth2ClientConfiguration.java

@@ -1,413 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.config.annotation.web.reactive;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-import java.util.function.Consumer;
-
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.BeanFactory;
-import org.springframework.beans.factory.BeanFactoryAware;
-import org.springframework.beans.factory.BeanFactoryUtils;
-import org.springframework.beans.factory.BeanInitializationException;
-import org.springframework.beans.factory.ListableBeanFactory;
-import org.springframework.beans.factory.NoSuchBeanDefinitionException;
-import org.springframework.beans.factory.ObjectProvider;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
-import org.springframework.context.annotation.AnnotationBeanNameGenerator;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Import;
-import org.springframework.core.ResolvableType;
-import org.springframework.security.oauth2.client.AuthorizationCodeReactiveOAuth2AuthorizedClientProvider;
-import org.springframework.security.oauth2.client.ClientCredentialsReactiveOAuth2AuthorizedClientProvider;
-import org.springframework.security.oauth2.client.DelegatingReactiveOAuth2AuthorizedClientProvider;
-import org.springframework.security.oauth2.client.JwtBearerReactiveOAuth2AuthorizedClientProvider;
-import org.springframework.security.oauth2.client.PasswordReactiveOAuth2AuthorizedClientProvider;
-import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientManager;
-import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProvider;
-import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientService;
-import org.springframework.security.oauth2.client.RefreshTokenReactiveOAuth2AuthorizedClientProvider;
-import org.springframework.security.oauth2.client.TokenExchangeReactiveOAuth2AuthorizedClientProvider;
-import org.springframework.security.oauth2.client.endpoint.JwtBearerGrantRequest;
-import org.springframework.security.oauth2.client.endpoint.OAuth2ClientCredentialsGrantRequest;
-import org.springframework.security.oauth2.client.endpoint.OAuth2PasswordGrantRequest;
-import org.springframework.security.oauth2.client.endpoint.OAuth2RefreshTokenGrantRequest;
-import org.springframework.security.oauth2.client.endpoint.ReactiveOAuth2AccessTokenResponseClient;
-import org.springframework.security.oauth2.client.endpoint.TokenExchangeGrantRequest;
-import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
-import org.springframework.security.oauth2.client.web.DefaultReactiveOAuth2AuthorizedClientManager;
-import org.springframework.security.oauth2.client.web.reactive.result.method.annotation.OAuth2AuthorizedClientArgumentResolver;
-import org.springframework.security.oauth2.client.web.server.AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository;
-import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository;
-import org.springframework.web.reactive.config.WebFluxConfigurer;
-import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer;
-
-/**
- * {@link Configuration} for OAuth 2.0 Client support.
- *
- * <p>
- * This {@code Configuration} is conditionally imported by
- * {@link ReactiveOAuth2ClientImportSelector} when the
- * {@code spring-security-oauth2-client} module is present on the classpath.
- *
- * @author Steve Riesenberg
- * @since 6.3
- * @see ReactiveOAuth2ClientImportSelector
- */
-@Import({ ReactiveOAuth2ClientConfiguration.ReactiveOAuth2AuthorizedClientManagerConfiguration.class,
-		ReactiveOAuth2ClientConfiguration.OAuth2ClientWebFluxSecurityConfiguration.class })
-final class ReactiveOAuth2ClientConfiguration {
-
-	@Configuration(proxyBeanMethods = false)
-	static class ReactiveOAuth2AuthorizedClientManagerConfiguration {
-
-		@Bean(name = ReactiveOAuth2AuthorizedClientManagerRegistrar.BEAN_NAME)
-		ReactiveOAuth2AuthorizedClientManagerRegistrar authorizedClientManagerRegistrar() {
-			return new ReactiveOAuth2AuthorizedClientManagerRegistrar();
-		}
-
-	}
-
-	@Configuration(proxyBeanMethods = false)
-	static class OAuth2ClientWebFluxSecurityConfiguration implements WebFluxConfigurer {
-
-		private ReactiveOAuth2AuthorizedClientManager authorizedClientManager;
-
-		private ReactiveOAuth2AuthorizedClientManagerRegistrar authorizedClientManagerRegistrar;
-
-		@Override
-		public void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
-			ReactiveOAuth2AuthorizedClientManager authorizedClientManager = getAuthorizedClientManager();
-			if (authorizedClientManager != null) {
-				configurer.addCustomResolver(new OAuth2AuthorizedClientArgumentResolver(authorizedClientManager));
-			}
-		}
-
-		@Autowired(required = false)
-		void setAuthorizedClientManager(List<ReactiveOAuth2AuthorizedClientManager> authorizedClientManager) {
-			if (authorizedClientManager.size() == 1) {
-				this.authorizedClientManager = authorizedClientManager.get(0);
-			}
-		}
-
-		@Autowired
-		void setAuthorizedClientManagerRegistrar(
-				ReactiveOAuth2AuthorizedClientManagerRegistrar authorizedClientManagerRegistrar) {
-			this.authorizedClientManagerRegistrar = authorizedClientManagerRegistrar;
-		}
-
-		private ReactiveOAuth2AuthorizedClientManager getAuthorizedClientManager() {
-			if (this.authorizedClientManager != null) {
-				return this.authorizedClientManager;
-			}
-			return this.authorizedClientManagerRegistrar.getAuthorizedClientManagerIfAvailable();
-		}
-
-	}
-
-	/**
-	 * A registrar for registering the default
-	 * {@link ReactiveOAuth2AuthorizedClientManager} bean definition, if not already
-	 * present.
-	 */
-	static final class ReactiveOAuth2AuthorizedClientManagerRegistrar
-			implements BeanDefinitionRegistryPostProcessor, BeanFactoryAware {
-
-		static final String BEAN_NAME = "authorizedClientManagerRegistrar";
-
-		static final String FACTORY_METHOD_NAME = "getAuthorizedClientManager";
-
-		// @formatter:off
-		private static final Set<Class<?>> KNOWN_AUTHORIZED_CLIENT_PROVIDERS = Set.of(
-				AuthorizationCodeReactiveOAuth2AuthorizedClientProvider.class,
-				RefreshTokenReactiveOAuth2AuthorizedClientProvider.class,
-				ClientCredentialsReactiveOAuth2AuthorizedClientProvider.class,
-				PasswordReactiveOAuth2AuthorizedClientProvider.class,
-				JwtBearerReactiveOAuth2AuthorizedClientProvider.class,
-				TokenExchangeReactiveOAuth2AuthorizedClientProvider.class
-		);
-		// @formatter:on
-
-		private final AnnotationBeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
-
-		private ListableBeanFactory beanFactory;
-
-		@Override
-		public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
-			if (getBeanNamesForType(ReactiveOAuth2AuthorizedClientManager.class).length != 0
-					|| getBeanNamesForType(ReactiveClientRegistrationRepository.class).length != 1
-					|| getBeanNamesForType(ServerOAuth2AuthorizedClientRepository.class).length != 1
-							&& getBeanNamesForType(ReactiveOAuth2AuthorizedClientService.class).length != 1) {
-				return;
-			}
-
-			BeanDefinition beanDefinition = BeanDefinitionBuilder
-				.rootBeanDefinition(ReactiveOAuth2AuthorizedClientManager.class)
-				.setFactoryMethodOnBean(FACTORY_METHOD_NAME, BEAN_NAME)
-				.getBeanDefinition();
-
-			registry.registerBeanDefinition(this.beanNameGenerator.generateBeanName(beanDefinition, registry),
-					beanDefinition);
-		}
-
-		@Override
-		public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
-			this.beanFactory = (ListableBeanFactory) beanFactory;
-		}
-
-		ReactiveOAuth2AuthorizedClientManager getAuthorizedClientManagerIfAvailable() {
-			if (getBeanNamesForType(ReactiveClientRegistrationRepository.class).length != 1
-					|| getBeanNamesForType(ServerOAuth2AuthorizedClientRepository.class).length != 1
-							&& getBeanNamesForType(ReactiveOAuth2AuthorizedClientService.class).length != 1) {
-				return null;
-			}
-			return getAuthorizedClientManager();
-		}
-
-		ReactiveOAuth2AuthorizedClientManager getAuthorizedClientManager() {
-			ReactiveClientRegistrationRepository clientRegistrationRepository = BeanFactoryUtils
-				.beanOfTypeIncludingAncestors(this.beanFactory, ReactiveClientRegistrationRepository.class, true, true);
-
-			ServerOAuth2AuthorizedClientRepository authorizedClientRepository;
-			try {
-				authorizedClientRepository = BeanFactoryUtils.beanOfTypeIncludingAncestors(this.beanFactory,
-						ServerOAuth2AuthorizedClientRepository.class, true, true);
-			}
-			catch (NoSuchBeanDefinitionException ex) {
-				ReactiveOAuth2AuthorizedClientService authorizedClientService = BeanFactoryUtils
-					.beanOfTypeIncludingAncestors(this.beanFactory, ReactiveOAuth2AuthorizedClientService.class, true,
-							true);
-				authorizedClientRepository = new AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository(
-						authorizedClientService);
-			}
-
-			Collection<ReactiveOAuth2AuthorizedClientProvider> authorizedClientProviderBeans = BeanFactoryUtils
-				.beansOfTypeIncludingAncestors(this.beanFactory, ReactiveOAuth2AuthorizedClientProvider.class, true,
-						true)
-				.values();
-
-			ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider;
-			if (hasDelegatingAuthorizedClientProvider(authorizedClientProviderBeans)) {
-				authorizedClientProvider = authorizedClientProviderBeans.iterator().next();
-			}
-			else {
-				List<ReactiveOAuth2AuthorizedClientProvider> authorizedClientProviders = new ArrayList<>();
-				authorizedClientProviders
-					.add(getAuthorizationCodeAuthorizedClientProvider(authorizedClientProviderBeans));
-				authorizedClientProviders.add(getRefreshTokenAuthorizedClientProvider(authorizedClientProviderBeans));
-				authorizedClientProviders
-					.add(getClientCredentialsAuthorizedClientProvider(authorizedClientProviderBeans));
-				authorizedClientProviders.add(getPasswordAuthorizedClientProvider(authorizedClientProviderBeans));
-
-				ReactiveOAuth2AuthorizedClientProvider jwtBearerAuthorizedClientProvider = getJwtBearerAuthorizedClientProvider(
-						authorizedClientProviderBeans);
-				if (jwtBearerAuthorizedClientProvider != null) {
-					authorizedClientProviders.add(jwtBearerAuthorizedClientProvider);
-				}
-
-				ReactiveOAuth2AuthorizedClientProvider tokenExchangeAuthorizedClientProvider = getTokenExchangeAuthorizedClientProvider(
-						authorizedClientProviderBeans);
-				if (tokenExchangeAuthorizedClientProvider != null) {
-					authorizedClientProviders.add(tokenExchangeAuthorizedClientProvider);
-				}
-
-				authorizedClientProviders.addAll(getAdditionalAuthorizedClientProviders(authorizedClientProviderBeans));
-				authorizedClientProvider = new DelegatingReactiveOAuth2AuthorizedClientProvider(
-						authorizedClientProviders);
-			}
-
-			DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager = new DefaultReactiveOAuth2AuthorizedClientManager(
-					clientRegistrationRepository, authorizedClientRepository);
-			authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
-
-			Consumer<DefaultReactiveOAuth2AuthorizedClientManager> authorizedClientManagerConsumer = getBeanOfType(
-					ResolvableType.forClassWithGenerics(Consumer.class,
-							DefaultReactiveOAuth2AuthorizedClientManager.class));
-			if (authorizedClientManagerConsumer != null) {
-				authorizedClientManagerConsumer.accept(authorizedClientManager);
-			}
-
-			return authorizedClientManager;
-		}
-
-		private boolean hasDelegatingAuthorizedClientProvider(
-				Collection<ReactiveOAuth2AuthorizedClientProvider> authorizedClientProviders) {
-			if (authorizedClientProviders.size() != 1) {
-				return false;
-			}
-			return authorizedClientProviders.iterator()
-				.next() instanceof DelegatingReactiveOAuth2AuthorizedClientProvider;
-		}
-
-		private ReactiveOAuth2AuthorizedClientProvider getAuthorizationCodeAuthorizedClientProvider(
-				Collection<ReactiveOAuth2AuthorizedClientProvider> authorizedClientProviders) {
-			AuthorizationCodeReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = getAuthorizedClientProviderByType(
-					authorizedClientProviders, AuthorizationCodeReactiveOAuth2AuthorizedClientProvider.class);
-			if (authorizedClientProvider == null) {
-				authorizedClientProvider = new AuthorizationCodeReactiveOAuth2AuthorizedClientProvider();
-			}
-
-			return authorizedClientProvider;
-		}
-
-		private ReactiveOAuth2AuthorizedClientProvider getRefreshTokenAuthorizedClientProvider(
-				Collection<ReactiveOAuth2AuthorizedClientProvider> authorizedClientProviders) {
-			RefreshTokenReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = getAuthorizedClientProviderByType(
-					authorizedClientProviders, RefreshTokenReactiveOAuth2AuthorizedClientProvider.class);
-			if (authorizedClientProvider == null) {
-				authorizedClientProvider = new RefreshTokenReactiveOAuth2AuthorizedClientProvider();
-			}
-
-			ReactiveOAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> accessTokenResponseClient = getBeanOfType(
-					ResolvableType.forClassWithGenerics(ReactiveOAuth2AccessTokenResponseClient.class,
-							OAuth2RefreshTokenGrantRequest.class));
-			if (accessTokenResponseClient != null) {
-				authorizedClientProvider.setAccessTokenResponseClient(accessTokenResponseClient);
-			}
-
-			return authorizedClientProvider;
-		}
-
-		private ReactiveOAuth2AuthorizedClientProvider getClientCredentialsAuthorizedClientProvider(
-				Collection<ReactiveOAuth2AuthorizedClientProvider> authorizedClientProviders) {
-			ClientCredentialsReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = getAuthorizedClientProviderByType(
-					authorizedClientProviders, ClientCredentialsReactiveOAuth2AuthorizedClientProvider.class);
-			if (authorizedClientProvider == null) {
-				authorizedClientProvider = new ClientCredentialsReactiveOAuth2AuthorizedClientProvider();
-			}
-
-			ReactiveOAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> accessTokenResponseClient = getBeanOfType(
-					ResolvableType.forClassWithGenerics(ReactiveOAuth2AccessTokenResponseClient.class,
-							OAuth2ClientCredentialsGrantRequest.class));
-			if (accessTokenResponseClient != null) {
-				authorizedClientProvider.setAccessTokenResponseClient(accessTokenResponseClient);
-			}
-
-			return authorizedClientProvider;
-		}
-
-		private ReactiveOAuth2AuthorizedClientProvider getPasswordAuthorizedClientProvider(
-				Collection<ReactiveOAuth2AuthorizedClientProvider> authorizedClientProviders) {
-			PasswordReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = getAuthorizedClientProviderByType(
-					authorizedClientProviders, PasswordReactiveOAuth2AuthorizedClientProvider.class);
-			if (authorizedClientProvider == null) {
-				authorizedClientProvider = new PasswordReactiveOAuth2AuthorizedClientProvider();
-			}
-
-			ReactiveOAuth2AccessTokenResponseClient<OAuth2PasswordGrantRequest> accessTokenResponseClient = getBeanOfType(
-					ResolvableType.forClassWithGenerics(ReactiveOAuth2AccessTokenResponseClient.class,
-							OAuth2PasswordGrantRequest.class));
-			if (accessTokenResponseClient != null) {
-				authorizedClientProvider.setAccessTokenResponseClient(accessTokenResponseClient);
-			}
-
-			return authorizedClientProvider;
-		}
-
-		private ReactiveOAuth2AuthorizedClientProvider getJwtBearerAuthorizedClientProvider(
-				Collection<ReactiveOAuth2AuthorizedClientProvider> authorizedClientProviders) {
-			JwtBearerReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = getAuthorizedClientProviderByType(
-					authorizedClientProviders, JwtBearerReactiveOAuth2AuthorizedClientProvider.class);
-
-			ReactiveOAuth2AccessTokenResponseClient<JwtBearerGrantRequest> accessTokenResponseClient = getBeanOfType(
-					ResolvableType.forClassWithGenerics(ReactiveOAuth2AccessTokenResponseClient.class,
-							JwtBearerGrantRequest.class));
-			if (accessTokenResponseClient != null) {
-				if (authorizedClientProvider == null) {
-					authorizedClientProvider = new JwtBearerReactiveOAuth2AuthorizedClientProvider();
-				}
-
-				authorizedClientProvider.setAccessTokenResponseClient(accessTokenResponseClient);
-			}
-
-			return authorizedClientProvider;
-		}
-
-		private ReactiveOAuth2AuthorizedClientProvider getTokenExchangeAuthorizedClientProvider(
-				Collection<ReactiveOAuth2AuthorizedClientProvider> authorizedClientProviders) {
-			TokenExchangeReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = getAuthorizedClientProviderByType(
-					authorizedClientProviders, TokenExchangeReactiveOAuth2AuthorizedClientProvider.class);
-
-			ReactiveOAuth2AccessTokenResponseClient<TokenExchangeGrantRequest> accessTokenResponseClient = getBeanOfType(
-					ResolvableType.forClassWithGenerics(ReactiveOAuth2AccessTokenResponseClient.class,
-							TokenExchangeGrantRequest.class));
-			if (accessTokenResponseClient != null) {
-				if (authorizedClientProvider == null) {
-					authorizedClientProvider = new TokenExchangeReactiveOAuth2AuthorizedClientProvider();
-				}
-
-				authorizedClientProvider.setAccessTokenResponseClient(accessTokenResponseClient);
-			}
-
-			return authorizedClientProvider;
-		}
-
-		private List<ReactiveOAuth2AuthorizedClientProvider> getAdditionalAuthorizedClientProviders(
-				Collection<ReactiveOAuth2AuthorizedClientProvider> authorizedClientProviders) {
-			List<ReactiveOAuth2AuthorizedClientProvider> additionalAuthorizedClientProviders = new ArrayList<>(
-					authorizedClientProviders);
-			additionalAuthorizedClientProviders
-				.removeIf((provider) -> KNOWN_AUTHORIZED_CLIENT_PROVIDERS.contains(provider.getClass()));
-			return additionalAuthorizedClientProviders;
-		}
-
-		private <T extends ReactiveOAuth2AuthorizedClientProvider> T getAuthorizedClientProviderByType(
-				Collection<ReactiveOAuth2AuthorizedClientProvider> authorizedClientProviders, Class<T> providerClass) {
-			T authorizedClientProvider = null;
-			for (ReactiveOAuth2AuthorizedClientProvider current : authorizedClientProviders) {
-				if (providerClass.isInstance(current)) {
-					assertAuthorizedClientProviderIsNull(authorizedClientProvider);
-					authorizedClientProvider = providerClass.cast(current);
-				}
-			}
-			return authorizedClientProvider;
-		}
-
-		private static void assertAuthorizedClientProviderIsNull(
-				ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider) {
-			if (authorizedClientProvider != null) {
-				// @formatter:off
-				throw new BeanInitializationException(String.format(
-						"Unable to create a %s bean. Expected one bean of type %s, but found multiple. " +
-						"Please consider defining only a single bean of this type, or define a %s bean yourself.",
-						ReactiveOAuth2AuthorizedClientManager.class.getName(),
-						authorizedClientProvider.getClass().getName(),
-						ReactiveOAuth2AuthorizedClientManager.class.getName()));
-				// @formatter:on
-			}
-		}
-
-		private <T> String[] getBeanNamesForType(Class<T> beanClass) {
-			return BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, beanClass, true, true);
-		}
-
-		private <T> T getBeanOfType(ResolvableType resolvableType) {
-			ObjectProvider<T> objectProvider = this.beanFactory.getBeanProvider(resolvableType, true);
-			return objectProvider.getIfAvailable();
-		}
-
-	}
-
-}

+ 96 - 5
config/src/main/java/org/springframework/security/config/annotation/web/reactive/ReactiveOAuth2ClientImportSelector.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2022 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,13 +16,27 @@
 
 package org.springframework.security.config.annotation.web.reactive;
 
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.ImportSelector;
 import org.springframework.core.type.AnnotationMetadata;
+import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientManager;
+import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProvider;
+import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProviderBuilder;
+import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientService;
+import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
+import org.springframework.security.oauth2.client.web.DefaultReactiveOAuth2AuthorizedClientManager;
+import org.springframework.security.oauth2.client.web.reactive.result.method.annotation.OAuth2AuthorizedClientArgumentResolver;
+import org.springframework.security.oauth2.client.web.server.AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository;
+import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository;
 import org.springframework.util.ClassUtils;
+import org.springframework.web.reactive.config.WebFluxConfigurer;
+import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer;
 
 /**
- * Used by {@link EnableWebFluxSecurity} to conditionally import
- * {@link ReactiveOAuth2ClientConfiguration}.
+ * {@link Configuration} for OAuth 2.0 Client support.
  *
  * <p>
  * This {@code Configuration} is imported by {@link EnableWebFluxSecurity}
@@ -46,8 +60,85 @@ final class ReactiveOAuth2ClientImportSelector implements ImportSelector {
 		if (!oauth2ClientPresent) {
 			return new String[0];
 		}
-		return new String[] {
-				"org.springframework.security.config.annotation.web.reactive.ReactiveOAuth2ClientConfiguration" };
+		return new String[] { "org.springframework.security.config.annotation.web.reactive."
+				+ "ReactiveOAuth2ClientImportSelector$OAuth2ClientWebFluxSecurityConfiguration" };
+	}
+
+	@Configuration(proxyBeanMethods = false)
+	static class OAuth2ClientWebFluxSecurityConfiguration implements WebFluxConfigurer {
+
+		private ReactiveClientRegistrationRepository clientRegistrationRepository;
+
+		private ServerOAuth2AuthorizedClientRepository authorizedClientRepository;
+
+		private ReactiveOAuth2AuthorizedClientService authorizedClientService;
+
+		private ReactiveOAuth2AuthorizedClientManager authorizedClientManager;
+
+		@Override
+		public void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
+			ReactiveOAuth2AuthorizedClientManager authorizedClientManager = getAuthorizedClientManager();
+			if (authorizedClientManager != null) {
+				configurer.addCustomResolver(new OAuth2AuthorizedClientArgumentResolver(authorizedClientManager));
+			}
+		}
+
+		@Autowired(required = false)
+		void setClientRegistrationRepository(ReactiveClientRegistrationRepository clientRegistrationRepository) {
+			this.clientRegistrationRepository = clientRegistrationRepository;
+		}
+
+		@Autowired(required = false)
+		void setAuthorizedClientRepository(ServerOAuth2AuthorizedClientRepository authorizedClientRepository) {
+			this.authorizedClientRepository = authorizedClientRepository;
+		}
+
+		@Autowired(required = false)
+		void setAuthorizedClientService(List<ReactiveOAuth2AuthorizedClientService> authorizedClientService) {
+			if (authorizedClientService.size() == 1) {
+				this.authorizedClientService = authorizedClientService.get(0);
+			}
+		}
+
+		@Autowired(required = false)
+		void setAuthorizedClientManager(List<ReactiveOAuth2AuthorizedClientManager> authorizedClientManager) {
+			if (authorizedClientManager.size() == 1) {
+				this.authorizedClientManager = authorizedClientManager.get(0);
+			}
+		}
+
+		private ServerOAuth2AuthorizedClientRepository getAuthorizedClientRepository() {
+			if (this.authorizedClientRepository != null) {
+				return this.authorizedClientRepository;
+			}
+			if (this.authorizedClientService != null) {
+				return new AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository(this.authorizedClientService);
+			}
+			return null;
+		}
+
+		private ReactiveOAuth2AuthorizedClientManager getAuthorizedClientManager() {
+			if (this.authorizedClientManager != null) {
+				return this.authorizedClientManager;
+			}
+			ReactiveOAuth2AuthorizedClientManager authorizedClientManager = null;
+			if (this.authorizedClientRepository != null && this.clientRegistrationRepository != null) {
+				ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder
+					.builder()
+					.authorizationCode()
+					.refreshToken()
+					.clientCredentials()
+					.password()
+					.build();
+				DefaultReactiveOAuth2AuthorizedClientManager defaultReactiveOAuth2AuthorizedClientManager = new DefaultReactiveOAuth2AuthorizedClientManager(
+						this.clientRegistrationRepository, getAuthorizedClientRepository());
+				defaultReactiveOAuth2AuthorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
+				authorizedClientManager = defaultReactiveOAuth2AuthorizedClientManager;
+			}
+
+			return authorizedClientManager;
+		}
+
 	}
 
 }

+ 0 - 9
config/src/main/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfiguration.java

@@ -32,7 +32,6 @@ import org.springframework.core.ReactiveAdapterRegistry;
 import org.springframework.security.authentication.ObservationReactiveAuthenticationManager;
 import org.springframework.security.authentication.ReactiveAuthenticationManager;
 import org.springframework.security.authentication.UserDetailsRepositoryReactiveAuthenticationManager;
-import org.springframework.security.authentication.password.ReactiveCompromisedPasswordChecker;
 import org.springframework.security.config.web.server.ServerHttpSecurity;
 import org.springframework.security.core.userdetails.ReactiveUserDetailsPasswordService;
 import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
@@ -64,8 +63,6 @@ class ServerHttpSecurityConfiguration {
 
 	private ReactiveUserDetailsPasswordService userDetailsPasswordService;
 
-	private ReactiveCompromisedPasswordChecker compromisedPasswordChecker;
-
 	private ObservationRegistry observationRegistry = ObservationRegistry.NOOP;
 
 	@Autowired(required = false)
@@ -101,11 +98,6 @@ class ServerHttpSecurityConfiguration {
 		this.observationRegistry = observationRegistry;
 	}
 
-	@Autowired(required = false)
-	void setCompromisedPasswordChecker(ReactiveCompromisedPasswordChecker compromisedPasswordChecker) {
-		this.compromisedPasswordChecker = compromisedPasswordChecker;
-	}
-
 	@Bean
 	static WebFluxConfigurer authenticationPrincipalArgumentResolverConfigurer(
 			ObjectProvider<AuthenticationPrincipalArgumentResolver> authenticationPrincipalArgumentResolver) {
@@ -161,7 +153,6 @@ class ServerHttpSecurityConfiguration {
 				manager.setPasswordEncoder(this.passwordEncoder);
 			}
 			manager.setUserDetailsPasswordService(this.userDetailsPasswordService);
-			manager.setCompromisedPasswordChecker(this.compromisedPasswordChecker);
 			if (!this.observationRegistry.isNoop()) {
 				return new ObservationReactiveAuthenticationManager(this.observationRegistry, manager);
 			}

+ 1 - 29
config/src/main/java/org/springframework/security/config/http/OAuth2AuthorizedClientManagerRegistrar.java

@@ -44,13 +44,11 @@ import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
 import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider;
 import org.springframework.security.oauth2.client.PasswordOAuth2AuthorizedClientProvider;
 import org.springframework.security.oauth2.client.RefreshTokenOAuth2AuthorizedClientProvider;
-import org.springframework.security.oauth2.client.TokenExchangeOAuth2AuthorizedClientProvider;
 import org.springframework.security.oauth2.client.endpoint.JwtBearerGrantRequest;
 import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
 import org.springframework.security.oauth2.client.endpoint.OAuth2ClientCredentialsGrantRequest;
 import org.springframework.security.oauth2.client.endpoint.OAuth2PasswordGrantRequest;
 import org.springframework.security.oauth2.client.endpoint.OAuth2RefreshTokenGrantRequest;
-import org.springframework.security.oauth2.client.endpoint.TokenExchangeGrantRequest;
 import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
 import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager;
 import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
@@ -78,8 +76,7 @@ final class OAuth2AuthorizedClientManagerRegistrar implements BeanDefinitionRegi
 			RefreshTokenOAuth2AuthorizedClientProvider.class,
 			ClientCredentialsOAuth2AuthorizedClientProvider.class,
 			PasswordOAuth2AuthorizedClientProvider.class,
-			JwtBearerOAuth2AuthorizedClientProvider.class,
-			TokenExchangeOAuth2AuthorizedClientProvider.class
+			JwtBearerOAuth2AuthorizedClientProvider.class
 	);
 	// @formatter:on
 
@@ -140,12 +137,6 @@ final class OAuth2AuthorizedClientManagerRegistrar implements BeanDefinitionRegi
 				authorizedClientProviders.add(jwtBearerAuthorizedClientProvider);
 			}
 
-			OAuth2AuthorizedClientProvider tokenExchangeAuthorizedClientProvider = getTokenExchangeAuthorizedClientProvider(
-					authorizedClientProviderBeans);
-			if (tokenExchangeAuthorizedClientProvider != null) {
-				authorizedClientProviders.add(tokenExchangeAuthorizedClientProvider);
-			}
-
 			authorizedClientProviders.addAll(getAdditionalAuthorizedClientProviders(authorizedClientProviderBeans));
 			authorizedClientProvider = new DelegatingOAuth2AuthorizedClientProvider(authorizedClientProviders);
 		}
@@ -254,25 +245,6 @@ final class OAuth2AuthorizedClientManagerRegistrar implements BeanDefinitionRegi
 		return authorizedClientProvider;
 	}
 
-	private OAuth2AuthorizedClientProvider getTokenExchangeAuthorizedClientProvider(
-			Collection<OAuth2AuthorizedClientProvider> authorizedClientProviders) {
-		TokenExchangeOAuth2AuthorizedClientProvider authorizedClientProvider = getAuthorizedClientProviderByType(
-				authorizedClientProviders, TokenExchangeOAuth2AuthorizedClientProvider.class);
-
-		OAuth2AccessTokenResponseClient<TokenExchangeGrantRequest> accessTokenResponseClient = getBeanOfType(
-				ResolvableType.forClassWithGenerics(OAuth2AccessTokenResponseClient.class,
-						TokenExchangeGrantRequest.class));
-		if (accessTokenResponseClient != null) {
-			if (authorizedClientProvider == null) {
-				authorizedClientProvider = new TokenExchangeOAuth2AuthorizedClientProvider();
-			}
-
-			authorizedClientProvider.setAccessTokenResponseClient(accessTokenResponseClient);
-		}
-
-		return authorizedClientProvider;
-	}
-
 	private List<OAuth2AuthorizedClientProvider> getAdditionalAuthorizedClientProviders(
 			Collection<OAuth2AuthorizedClientProvider> authorizedClientProviders) {
 		List<OAuth2AuthorizedClientProvider> additionalAuthorizedClientProviders = new ArrayList<>(

+ 2 - 7
config/src/main/java/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParser.java

@@ -64,8 +64,6 @@ public final class RelyingPartyRegistrationsBeanDefinitionParser implements Bean
 
 	private static final String ELT_ENCRYPTION_CREDENTIAL = "encryption-credential";
 
-	private static final String ATT_ID = "id";
-
 	private static final String ATT_REGISTRATION_ID = "registration-id";
 
 	private static final String ATT_ASSERTING_PARTY_ID = "asserting-party-id";
@@ -110,11 +108,8 @@ public final class RelyingPartyRegistrationsBeanDefinitionParser implements Bean
 			.rootBeanDefinition(InMemoryRelyingPartyRegistrationRepository.class)
 			.addConstructorArgValue(relyingPartyRegistrations)
 			.getBeanDefinition();
-		String relyingPartyRegistrationRepositoryId = element.getAttribute(ATT_ID);
-		if (!StringUtils.hasText(relyingPartyRegistrationRepositoryId)) {
-			relyingPartyRegistrationRepositoryId = parserContext.getReaderContext()
-				.generateBeanName(relyingPartyRegistrationRepositoryBean);
-		}
+		String relyingPartyRegistrationRepositoryId = parserContext.getReaderContext()
+			.generateBeanName(relyingPartyRegistrationRepositoryBean);
 		parserContext.registerBeanComponent(new BeanComponentDefinition(relyingPartyRegistrationRepositoryBean,
 				relyingPartyRegistrationRepositoryId));
 		parserContext.popAndRegisterContainingComponent();

+ 5 - 3
config/src/main/java/org/springframework/security/config/web/server/DefaultOidcLogoutTokenValidatorFactory.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2023 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,15 +19,17 @@ package org.springframework.security.config.web.server;
 import java.util.function.Function;
 
 import org.springframework.security.oauth2.client.registration.ClientRegistration;
+import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
 import org.springframework.security.oauth2.core.OAuth2TokenValidator;
 import org.springframework.security.oauth2.jwt.Jwt;
-import org.springframework.security.oauth2.jwt.JwtValidators;
+import org.springframework.security.oauth2.jwt.JwtTimestampValidator;
 
 final class DefaultOidcLogoutTokenValidatorFactory implements Function<ClientRegistration, OAuth2TokenValidator<Jwt>> {
 
 	@Override
 	public OAuth2TokenValidator<Jwt> apply(ClientRegistration clientRegistration) {
-		return JwtValidators.createDefaultWithValidators(new OidcBackChannelLogoutTokenValidator(clientRegistration));
+		return new DelegatingOAuth2TokenValidator<>(new JwtTimestampValidator(),
+				new OidcBackChannelLogoutTokenValidator(clientRegistration));
 	}
 
 }

+ 12 - 422
config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java

@@ -63,7 +63,6 @@ import org.springframework.security.core.Authentication;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.authority.AuthorityUtils;
 import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
-import org.springframework.security.core.session.ReactiveSessionRegistry;
 import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
 import org.springframework.security.oauth2.client.InMemoryReactiveOAuth2AuthorizedClientService;
 import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientService;
@@ -127,26 +126,19 @@ import org.springframework.security.web.server.WebFilterExchange;
 import org.springframework.security.web.server.authentication.AnonymousAuthenticationWebFilter;
 import org.springframework.security.web.server.authentication.AuthenticationConverterServerWebExchangeMatcher;
 import org.springframework.security.web.server.authentication.AuthenticationWebFilter;
-import org.springframework.security.web.server.authentication.ConcurrentSessionControlServerAuthenticationSuccessHandler;
-import org.springframework.security.web.server.authentication.DelegatingServerAuthenticationSuccessHandler;
 import org.springframework.security.web.server.authentication.HttpBasicServerAuthenticationEntryPoint;
 import org.springframework.security.web.server.authentication.HttpStatusServerEntryPoint;
-import org.springframework.security.web.server.authentication.InvalidateLeastUsedServerMaximumSessionsExceededHandler;
 import org.springframework.security.web.server.authentication.ReactivePreAuthenticatedAuthenticationManager;
 import org.springframework.security.web.server.authentication.RedirectServerAuthenticationEntryPoint;
 import org.springframework.security.web.server.authentication.RedirectServerAuthenticationFailureHandler;
 import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler;
-import org.springframework.security.web.server.authentication.RegisterSessionServerAuthenticationSuccessHandler;
 import org.springframework.security.web.server.authentication.ServerAuthenticationConverter;
 import org.springframework.security.web.server.authentication.ServerAuthenticationEntryPointFailureHandler;
 import org.springframework.security.web.server.authentication.ServerAuthenticationFailureHandler;
 import org.springframework.security.web.server.authentication.ServerAuthenticationSuccessHandler;
 import org.springframework.security.web.server.authentication.ServerFormLoginAuthenticationConverter;
 import org.springframework.security.web.server.authentication.ServerHttpBasicAuthenticationConverter;
-import org.springframework.security.web.server.authentication.ServerMaximumSessionsExceededHandler;
 import org.springframework.security.web.server.authentication.ServerX509AuthenticationConverter;
-import org.springframework.security.web.server.authentication.SessionLimit;
-import org.springframework.security.web.server.authentication.WebFilterChainServerAuthenticationSuccessHandler;
 import org.springframework.security.web.server.authentication.logout.DelegatingServerLogoutHandler;
 import org.springframework.security.web.server.authentication.logout.LogoutWebFilter;
 import org.springframework.security.web.server.authentication.logout.SecurityContextServerLogoutHandler;
@@ -216,8 +208,6 @@ import org.springframework.web.server.ServerWebExchangeDecorator;
 import org.springframework.web.server.WebFilter;
 import org.springframework.web.server.WebFilterChain;
 import org.springframework.web.server.WebSession;
-import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
-import org.springframework.web.server.session.DefaultWebSessionManager;
 import org.springframework.web.util.pattern.PathPatternParser;
 
 /**
@@ -324,8 +314,6 @@ public class ServerHttpSecurity {
 
 	private LoginPageSpec loginPage = new LoginPageSpec();
 
-	private SessionManagementSpec sessionManagement;
-
 	private ReactiveAuthenticationManager authenticationManager;
 
 	private ServerSecurityContextRepository securityContextRepository;
@@ -374,7 +362,6 @@ public class ServerHttpSecurity {
 	}
 
 	/**
-	 *
 	 * Adds a {@link WebFilter} before specific position.
 	 * @param webFilter the {@link WebFilter} to add
 	 * @param order the place before which to insert the {@link WebFilter}
@@ -758,36 +745,6 @@ public class ServerHttpSecurity {
 		return this;
 	}
 
-	/**
-	 * Configures Session Management. An example configuration is provided below:
-	 * <pre class="code">
-	 *  &#064;Bean
-	 *  SecurityWebFilterChain filterChain(ServerHttpSecurity http, ReactiveSessionRegistry sessionRegistry) {
-	 *      http
-	 *          // ...
-	 *          .sessionManagement((sessionManagement) -> sessionManagement
-	 *              .concurrentSessions((concurrentSessions) -> concurrentSessions
-	 *                  .maxSessions(1)
-	 *                  .maxSessionsPreventsLogin(true)
-	 *                  .sessionRegistry(sessionRegistry)
-	 *              )
-	 *          );
-	 *      return http.build();
-	 *  }
-	 * </pre>
-	 * @param customizer the {@link Customizer} to provide more options for the
-	 * {@link SessionManagementSpec}
-	 * @return the {@link ServerHttpSecurity} to continue configuring
-	 * @since 6.3
-	 */
-	public ServerHttpSecurity sessionManagement(Customizer<SessionManagementSpec> customizer) {
-		if (this.sessionManagement == null) {
-			this.sessionManagement = new SessionManagementSpec();
-		}
-		customizer.customize(this.sessionManagement);
-		return this;
-	}
-
 	/**
 	 * Configures password management. An example configuration is provided below:
 	 *
@@ -1562,9 +1519,6 @@ public class ServerHttpSecurity {
 		}
 		WebFilter securityContextRepositoryWebFilter = securityContextRepositoryWebFilter();
 		this.webFilters.add(securityContextRepositoryWebFilter);
-		if (this.sessionManagement != null) {
-			this.sessionManagement.configure(this);
-		}
 		if (this.httpsRedirectSpec != null) {
 			this.httpsRedirectSpec.configure(this);
 		}
@@ -1955,270 +1909,6 @@ public class ServerHttpSecurity {
 
 	}
 
-	/**
-	 * Configures how sessions are managed.
-	 */
-	public class SessionManagementSpec {
-
-		private ConcurrentSessionsSpec concurrentSessions;
-
-		private ServerAuthenticationSuccessHandler authenticationSuccessHandler;
-
-		private ReactiveSessionRegistry sessionRegistry;
-
-		private SessionLimit sessionLimit = SessionLimit.UNLIMITED;
-
-		private ServerMaximumSessionsExceededHandler maximumSessionsExceededHandler;
-
-		/**
-		 * Configures how many sessions are allowed for a given user.
-		 * @param customizer the customizer to provide more options
-		 * @return the {@link SessionManagementSpec} to customize
-		 */
-		public SessionManagementSpec concurrentSessions(Customizer<ConcurrentSessionsSpec> customizer) {
-			if (this.concurrentSessions == null) {
-				this.concurrentSessions = new ConcurrentSessionsSpec();
-			}
-			customizer.customize(this.concurrentSessions);
-			return this;
-		}
-
-		void configure(ServerHttpSecurity http) {
-			if (this.concurrentSessions != null) {
-				ReactiveSessionRegistry reactiveSessionRegistry = getSessionRegistry();
-				ConcurrentSessionControlServerAuthenticationSuccessHandler concurrentSessionControlStrategy = new ConcurrentSessionControlServerAuthenticationSuccessHandler(
-						reactiveSessionRegistry, getMaximumSessionsExceededHandler());
-				concurrentSessionControlStrategy.setSessionLimit(this.sessionLimit);
-				RegisterSessionServerAuthenticationSuccessHandler registerSessionAuthenticationStrategy = new RegisterSessionServerAuthenticationSuccessHandler(
-						reactiveSessionRegistry);
-				this.authenticationSuccessHandler = new DelegatingServerAuthenticationSuccessHandler(
-						concurrentSessionControlStrategy, registerSessionAuthenticationStrategy);
-				SessionRegistryWebFilter sessionRegistryWebFilter = new SessionRegistryWebFilter(
-						reactiveSessionRegistry);
-				configureSuccessHandlerOnAuthenticationFilters();
-				http.addFilterAfter(sessionRegistryWebFilter, SecurityWebFiltersOrder.HTTP_HEADERS_WRITER);
-			}
-		}
-
-		private ServerMaximumSessionsExceededHandler getMaximumSessionsExceededHandler() {
-			if (this.maximumSessionsExceededHandler != null) {
-				return this.maximumSessionsExceededHandler;
-			}
-			DefaultWebSessionManager webSessionManager = getBeanOrNull(
-					WebHttpHandlerBuilder.WEB_SESSION_MANAGER_BEAN_NAME, DefaultWebSessionManager.class);
-			if (webSessionManager != null) {
-				this.maximumSessionsExceededHandler = new InvalidateLeastUsedServerMaximumSessionsExceededHandler(
-						webSessionManager.getSessionStore());
-			}
-			if (this.maximumSessionsExceededHandler == null) {
-				throw new IllegalStateException(
-						"Could not create a default ServerMaximumSessionsExceededHandler. Please provide "
-								+ "a ServerMaximumSessionsExceededHandler via DSL");
-			}
-			return this.maximumSessionsExceededHandler;
-		}
-
-		private void configureSuccessHandlerOnAuthenticationFilters() {
-			if (ServerHttpSecurity.this.formLogin != null) {
-				ServerHttpSecurity.this.formLogin.defaultSuccessHandlers.add(0, this.authenticationSuccessHandler);
-			}
-			if (ServerHttpSecurity.this.oauth2Login != null) {
-				ServerHttpSecurity.this.oauth2Login.defaultSuccessHandlers.add(0, this.authenticationSuccessHandler);
-			}
-			if (ServerHttpSecurity.this.httpBasic != null) {
-				ServerHttpSecurity.this.httpBasic.defaultSuccessHandlers.add(0, this.authenticationSuccessHandler);
-			}
-		}
-
-		private ReactiveSessionRegistry getSessionRegistry() {
-			if (this.sessionRegistry == null) {
-				this.sessionRegistry = getBeanOrNull(ReactiveSessionRegistry.class);
-			}
-			if (this.sessionRegistry == null) {
-				throw new IllegalStateException(
-						"A ReactiveSessionRegistry is needed for concurrent session management");
-			}
-			return this.sessionRegistry;
-		}
-
-		/**
-		 * Configures how many sessions are allowed for a given user.
-		 */
-		public class ConcurrentSessionsSpec {
-
-			/**
-			 * Sets the {@link ReactiveSessionRegistry} to use.
-			 * @param reactiveSessionRegistry the {@link ReactiveSessionRegistry} to use
-			 * @return the {@link ConcurrentSessionsSpec} to continue customizing
-			 */
-			public ConcurrentSessionsSpec sessionRegistry(ReactiveSessionRegistry reactiveSessionRegistry) {
-				SessionManagementSpec.this.sessionRegistry = reactiveSessionRegistry;
-				return this;
-			}
-
-			/**
-			 * Sets the maximum number of sessions allowed for any user. You can use
-			 * {@link SessionLimit#of(int)} to specify a positive integer or
-			 * {@link SessionLimit#UNLIMITED} to allow unlimited sessions. To customize
-			 * the maximum number of sessions on a per-user basis, you can provide a
-			 * custom {@link SessionLimit} implementation, like so: <pre>
-			 *     http
-			 *         .sessionManagement((sessions) -> sessions
-			 *             .concurrentSessions((concurrency) -> concurrency
-			 *                 .maximumSessions((authentication) -> {
-			 *                     if (authentication.getName().equals("admin")) {
-			 *                         return Mono.empty() // unlimited sessions for admin
-			 *                     }
-			 *                     return Mono.just(1); // one session for every other user
-			 *                 })
-			 *             )
-			 *         )
-			 * </pre>
-			 * @param sessionLimit the maximum number of sessions allowed for any user
-			 * @return the {@link ConcurrentSessionsSpec} to continue customizing
-			 */
-			public ConcurrentSessionsSpec maximumSessions(SessionLimit sessionLimit) {
-				Assert.notNull(sessionLimit, "sessionLimit cannot be null");
-				SessionManagementSpec.this.sessionLimit = sessionLimit;
-				return this;
-			}
-
-			/**
-			 * Sets the {@link ServerMaximumSessionsExceededHandler} to use when the
-			 * maximum number of sessions is exceeded.
-			 * @param maximumSessionsExceededHandler the
-			 * {@link ServerMaximumSessionsExceededHandler} to use
-			 * @return the {@link ConcurrentSessionsSpec} to continue customizing
-			 */
-			public ConcurrentSessionsSpec maximumSessionsExceededHandler(
-					ServerMaximumSessionsExceededHandler maximumSessionsExceededHandler) {
-				Assert.notNull(maximumSessionsExceededHandler, "maximumSessionsExceededHandler cannot be null");
-				SessionManagementSpec.this.maximumSessionsExceededHandler = maximumSessionsExceededHandler;
-				return this;
-			}
-
-		}
-
-		private static final class SessionRegistryWebFilter implements WebFilter {
-
-			private final ReactiveSessionRegistry sessionRegistry;
-
-			private SessionRegistryWebFilter(ReactiveSessionRegistry sessionRegistry) {
-				Assert.notNull(sessionRegistry, "sessionRegistry cannot be null");
-				this.sessionRegistry = sessionRegistry;
-			}
-
-			@Override
-			public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
-				return chain.filter(new SessionRegistryWebExchange(exchange));
-			}
-
-			private final class SessionRegistryWebExchange extends ServerWebExchangeDecorator {
-
-				private final Mono<WebSession> sessionMono;
-
-				private SessionRegistryWebExchange(ServerWebExchange delegate) {
-					super(delegate);
-					this.sessionMono = delegate.getSession()
-						.flatMap((session) -> SessionRegistryWebFilter.this.sessionRegistry
-							.updateLastAccessTime(session.getId())
-							.thenReturn(session))
-						.map(SessionRegistryWebSession::new);
-				}
-
-				@Override
-				public Mono<WebSession> getSession() {
-					return this.sessionMono;
-				}
-
-			}
-
-			private final class SessionRegistryWebSession implements WebSession {
-
-				private final WebSession session;
-
-				private SessionRegistryWebSession(WebSession session) {
-					this.session = session;
-				}
-
-				@Override
-				public String getId() {
-					return this.session.getId();
-				}
-
-				@Override
-				public Map<String, Object> getAttributes() {
-					return this.session.getAttributes();
-				}
-
-				@Override
-				public void start() {
-					this.session.start();
-				}
-
-				@Override
-				public boolean isStarted() {
-					return this.session.isStarted();
-				}
-
-				@Override
-				public Mono<Void> changeSessionId() {
-					String currentId = this.session.getId();
-					return this.session.changeSessionId()
-						.then(Mono.defer(
-								() -> SessionRegistryWebFilter.this.sessionRegistry.removeSessionInformation(currentId)
-									.flatMap((information) -> {
-										information = information.withSessionId(this.session.getId());
-										return SessionRegistryWebFilter.this.sessionRegistry
-											.saveSessionInformation(information);
-									})));
-				}
-
-				@Override
-				public Mono<Void> invalidate() {
-					String currentId = this.session.getId();
-					return this.session.invalidate()
-						.then(Mono.defer(() -> SessionRegistryWebFilter.this.sessionRegistry
-							.removeSessionInformation(currentId)))
-						.then();
-				}
-
-				@Override
-				public Mono<Void> save() {
-					return this.session.save();
-				}
-
-				@Override
-				public boolean isExpired() {
-					return this.session.isExpired();
-				}
-
-				@Override
-				public Instant getCreationTime() {
-					return this.session.getCreationTime();
-				}
-
-				@Override
-				public Instant getLastAccessTime() {
-					return this.session.getLastAccessTime();
-				}
-
-				@Override
-				public void setMaxIdleTime(Duration maxIdleTime) {
-					this.session.setMaxIdleTime(maxIdleTime);
-				}
-
-				@Override
-				public Duration getMaxIdleTime() {
-					return this.session.getMaxIdleTime();
-				}
-
-			}
-
-		}
-
-	}
-
 	/**
 	 * Configures HTTPS redirection rules
 	 *
@@ -2523,11 +2213,6 @@ public class ServerHttpSecurity {
 
 		private ServerAuthenticationFailureHandler authenticationFailureHandler;
 
-		private final List<ServerAuthenticationSuccessHandler> defaultSuccessHandlers = new ArrayList<>(
-				List.of(new WebFilterChainServerAuthenticationSuccessHandler()));
-
-		private List<ServerAuthenticationSuccessHandler> authenticationSuccessHandlers = new ArrayList<>();
-
 		private HttpBasicSpec() {
 			List<DelegateEntry> entryPoints = new ArrayList<>();
 			entryPoints
@@ -2538,40 +2223,6 @@ public class ServerHttpSecurity {
 			this.entryPoint = defaultEntryPoint;
 		}
 
-		/**
-		 * The {@link ServerAuthenticationSuccessHandler} used after authentication
-		 * success. Defaults to {@link WebFilterChainServerAuthenticationSuccessHandler}.
-		 * Note that this method clears previously added success handlers via
-		 * {@link #authenticationSuccessHandler(Consumer)}
-		 * @param authenticationSuccessHandler the success handler to use
-		 * @return the {@link HttpBasicSpec} to continue configuring
-		 * @since 6.3
-		 */
-		public HttpBasicSpec authenticationSuccessHandler(
-				ServerAuthenticationSuccessHandler authenticationSuccessHandler) {
-			Assert.notNull(authenticationSuccessHandler, "authenticationSuccessHandler cannot be null");
-			authenticationSuccessHandler((handlers) -> {
-				handlers.clear();
-				handlers.add(authenticationSuccessHandler);
-			});
-			return this;
-		}
-
-		/**
-		 * Allows customizing the list of {@link ServerAuthenticationSuccessHandler}. The
-		 * default list contains a
-		 * {@link WebFilterChainServerAuthenticationSuccessHandler}.
-		 * @param handlersConsumer the handlers consumer
-		 * @return the {@link HttpBasicSpec} to continue configuring
-		 * @since 6.3
-		 */
-		public HttpBasicSpec authenticationSuccessHandler(
-				Consumer<List<ServerAuthenticationSuccessHandler>> handlersConsumer) {
-			Assert.notNull(handlersConsumer, "handlersConsumer cannot be null");
-			handlersConsumer.accept(this.authenticationSuccessHandlers);
-			return this;
-		}
-
 		/**
 		 * The {@link ReactiveAuthenticationManager} used to authenticate. Defaults to
 		 * {@link ServerHttpSecurity#authenticationManager(ReactiveAuthenticationManager)}.
@@ -2657,17 +2308,9 @@ public class ServerHttpSecurity {
 			authenticationFilter.setAuthenticationFailureHandler(authenticationFailureHandler());
 			authenticationFilter.setAuthenticationConverter(new ServerHttpBasicAuthenticationConverter());
 			authenticationFilter.setSecurityContextRepository(this.securityContextRepository);
-			authenticationFilter.setAuthenticationSuccessHandler(getAuthenticationSuccessHandler(http));
 			http.addFilterAt(authenticationFilter, SecurityWebFiltersOrder.HTTP_BASIC);
 		}
 
-		private ServerAuthenticationSuccessHandler getAuthenticationSuccessHandler(ServerHttpSecurity http) {
-			if (this.authenticationSuccessHandlers.isEmpty()) {
-				return new DelegatingServerAuthenticationSuccessHandler(this.defaultSuccessHandlers);
-			}
-			return new DelegatingServerAuthenticationSuccessHandler(this.authenticationSuccessHandlers);
-		}
-
 		private ServerAuthenticationFailureHandler authenticationFailureHandler() {
 			if (this.authenticationFailureHandler != null) {
 				return this.authenticationFailureHandler;
@@ -2739,9 +2382,6 @@ public class ServerHttpSecurity {
 		private final RedirectServerAuthenticationSuccessHandler defaultSuccessHandler = new RedirectServerAuthenticationSuccessHandler(
 				"/");
 
-		private final List<ServerAuthenticationSuccessHandler> defaultSuccessHandlers = new ArrayList<>(
-				List.of(this.defaultSuccessHandler));
-
 		private RedirectServerAuthenticationEntryPoint defaultEntryPoint;
 
 		private ReactiveAuthenticationManager authenticationManager;
@@ -2756,7 +2396,7 @@ public class ServerHttpSecurity {
 
 		private ServerAuthenticationFailureHandler authenticationFailureHandler;
 
-		private List<ServerAuthenticationSuccessHandler> authenticationSuccessHandlers = new ArrayList<>();
+		private ServerAuthenticationSuccessHandler authenticationSuccessHandler = this.defaultSuccessHandler;
 
 		private FormLoginSpec() {
 		}
@@ -2774,34 +2414,14 @@ public class ServerHttpSecurity {
 
 		/**
 		 * The {@link ServerAuthenticationSuccessHandler} used after authentication
-		 * success. Defaults to {@link RedirectServerAuthenticationSuccessHandler}. Note
-		 * that this method clears previously added success handlers via
-		 * {@link #authenticationSuccessHandler(Consumer)}
+		 * success. Defaults to {@link RedirectServerAuthenticationSuccessHandler}.
 		 * @param authenticationSuccessHandler the success handler to use
 		 * @return the {@link FormLoginSpec} to continue configuring
 		 */
 		public FormLoginSpec authenticationSuccessHandler(
 				ServerAuthenticationSuccessHandler authenticationSuccessHandler) {
 			Assert.notNull(authenticationSuccessHandler, "authenticationSuccessHandler cannot be null");
-			authenticationSuccessHandler((handlers) -> {
-				handlers.clear();
-				handlers.add(authenticationSuccessHandler);
-			});
-			return this;
-		}
-
-		/**
-		 * Allows customizing the list of {@link ServerAuthenticationSuccessHandler}. The
-		 * default list contains a {@link RedirectServerAuthenticationSuccessHandler} that
-		 * redirects to "/".
-		 * @param handlersConsumer the handlers consumer
-		 * @return the {@link FormLoginSpec} to continue configuring
-		 * @since 6.3
-		 */
-		public FormLoginSpec authenticationSuccessHandler(
-				Consumer<List<ServerAuthenticationSuccessHandler>> handlersConsumer) {
-			Assert.notNull(handlersConsumer, "handlersConsumer cannot be null");
-			handlersConsumer.accept(this.authenticationSuccessHandlers);
+			this.authenticationSuccessHandler = authenticationSuccessHandler;
 			return this;
 		}
 
@@ -2934,18 +2554,11 @@ public class ServerHttpSecurity {
 			authenticationFilter.setRequiresAuthenticationMatcher(this.requiresAuthenticationMatcher);
 			authenticationFilter.setAuthenticationFailureHandler(this.authenticationFailureHandler);
 			authenticationFilter.setAuthenticationConverter(new ServerFormLoginAuthenticationConverter());
-			authenticationFilter.setAuthenticationSuccessHandler(getAuthenticationSuccessHandler(http));
+			authenticationFilter.setAuthenticationSuccessHandler(this.authenticationSuccessHandler);
 			authenticationFilter.setSecurityContextRepository(this.securityContextRepository);
 			http.addFilterAt(authenticationFilter, SecurityWebFiltersOrder.FORM_LOGIN);
 		}
 
-		private ServerAuthenticationSuccessHandler getAuthenticationSuccessHandler(ServerHttpSecurity http) {
-			if (this.authenticationSuccessHandlers.isEmpty()) {
-				return new DelegatingServerAuthenticationSuccessHandler(this.defaultSuccessHandlers);
-			}
-			return new DelegatingServerAuthenticationSuccessHandler(this.authenticationSuccessHandlers);
-		}
-
 	}
 
 	private final class LoginPageSpec {
@@ -4124,12 +3737,7 @@ public class ServerHttpSecurity {
 
 		private ReactiveOidcSessionRegistry oidcSessionRegistry;
 
-		private final RedirectServerAuthenticationSuccessHandler defaultAuthenticationSuccessHandler = new RedirectServerAuthenticationSuccessHandler();
-
-		private final List<ServerAuthenticationSuccessHandler> defaultSuccessHandlers = new ArrayList<>(
-				List.of(this.defaultAuthenticationSuccessHandler));
-
-		private List<ServerAuthenticationSuccessHandler> authenticationSuccessHandlers = new ArrayList<>();
+		private ServerAuthenticationSuccessHandler authenticationSuccessHandler;
 
 		private ServerAuthenticationFailureHandler authenticationFailureHandler;
 
@@ -4177,8 +3785,7 @@ public class ServerHttpSecurity {
 		/**
 		 * The {@link ServerAuthenticationSuccessHandler} used after authentication
 		 * success. Defaults to {@link RedirectServerAuthenticationSuccessHandler}
-		 * redirecting to "/". Note that this method clears previously added success
-		 * handlers via {@link #authenticationSuccessHandler(Consumer)}
+		 * redirecting to "/".
 		 * @param authenticationSuccessHandler the success handler to use
 		 * @return the {@link OAuth2LoginSpec} to customize
 		 * @since 5.2
@@ -4186,25 +3793,7 @@ public class ServerHttpSecurity {
 		public OAuth2LoginSpec authenticationSuccessHandler(
 				ServerAuthenticationSuccessHandler authenticationSuccessHandler) {
 			Assert.notNull(authenticationSuccessHandler, "authenticationSuccessHandler cannot be null");
-			authenticationSuccessHandler((handlers) -> {
-				handlers.clear();
-				handlers.add(authenticationSuccessHandler);
-			});
-			return this;
-		}
-
-		/**
-		 * Allows customizing the list of {@link ServerAuthenticationSuccessHandler}. The
-		 * default list contains a {@link RedirectServerAuthenticationSuccessHandler} that
-		 * redirects to "/".
-		 * @param handlersConsumer the handlers consumer
-		 * @return the {@link OAuth2LoginSpec} to continue configuring
-		 * @since 6.3
-		 */
-		public OAuth2LoginSpec authenticationSuccessHandler(
-				Consumer<List<ServerAuthenticationSuccessHandler>> handlersConsumer) {
-			Assert.notNull(handlersConsumer, "handlersConsumer cannot be null");
-			handlersConsumer.accept(this.authenticationSuccessHandlers);
+			this.authenticationSuccessHandler = authenticationSuccessHandler;
 			return this;
 		}
 
@@ -4461,11 +4050,12 @@ public class ServerHttpSecurity {
 		}
 
 		private ServerAuthenticationSuccessHandler getAuthenticationSuccessHandler(ServerHttpSecurity http) {
-			this.defaultAuthenticationSuccessHandler.setRequestCache(http.requestCache.requestCache);
-			if (this.authenticationSuccessHandlers.isEmpty()) {
-				return new DelegatingServerAuthenticationSuccessHandler(this.defaultSuccessHandlers);
+			if (this.authenticationSuccessHandler == null) {
+				RedirectServerAuthenticationSuccessHandler handler = new RedirectServerAuthenticationSuccessHandler();
+				handler.setRequestCache(http.requestCache.requestCache);
+				this.authenticationSuccessHandler = handler;
 			}
-			return new DelegatingServerAuthenticationSuccessHandler(this.authenticationSuccessHandlers);
+			return this.authenticationSuccessHandler;
 		}
 
 		private ServerAuthenticationFailureHandler getAuthenticationFailureHandler() {

+ 1 - 9
config/src/main/kotlin/org/springframework/security/config/annotation/web/AuthorizeHttpRequestsDsl.kt

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2023 the original author or authors.
+ * Copyright 2002-2022 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -26,7 +26,6 @@ import org.springframework.security.config.annotation.web.configurers.AuthorizeH
 import org.springframework.security.core.Authentication
 import org.springframework.security.web.access.intercept.AuthorizationFilter
 import org.springframework.security.web.access.intercept.RequestAuthorizationContext
-import org.springframework.security.web.access.IpAddressAuthorizationManager
 import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher
 import org.springframework.security.web.util.matcher.AnyRequestMatcher
 import org.springframework.security.web.util.matcher.RequestMatcher
@@ -223,13 +222,6 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl() {
         return AuthorityAuthorizationManager.hasAnyRole(*roles)
     }
 
-    /**
-     * Require a specific IP or range of IP addresses.
-     * @since 6.3
-     */
-    fun hasIpAddress(ipAddress: String): AuthorizationManager<RequestAuthorizationContext> =
-        IpAddressAuthorizationManager.hasIpAddress(ipAddress)
-
     /**
      * Specify that URLs are allowed by anyone.
      */

+ 1 - 7
config/src/main/kotlin/org/springframework/security/config/annotation/web/FormLoginDsl.kt

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2023 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -38,8 +38,6 @@ import jakarta.servlet.http.HttpServletRequest
  * @property loginProcessingUrl the URL to validate the credentials
  * @property permitAll whether to grant access to the urls for [failureUrl] as well as
  * for the [HttpSecurityBuilder], the [loginPage] and [loginProcessingUrl] for every user
- * @property usernameParameter the HTTP parameter to look for the username when performing authentication
- * @property passwordParameter the HTTP parameter to look for the password when performing authentication
  */
 @SecurityMarker
 class FormLoginDsl {
@@ -50,8 +48,6 @@ class FormLoginDsl {
     var loginProcessingUrl: String? = null
     var permitAll: Boolean? = null
     var authenticationDetailsSource: AuthenticationDetailsSource<HttpServletRequest, *>? = null
-    var usernameParameter: String? = null
-    var passwordParameter: String? = null
 
     private var defaultSuccessUrlOption: Pair<String, Boolean>? = null
 
@@ -99,8 +95,6 @@ class FormLoginDsl {
             authenticationSuccessHandler?.also { login.successHandler(authenticationSuccessHandler) }
             authenticationFailureHandler?.also { login.failureHandler(authenticationFailureHandler) }
             authenticationDetailsSource?.also { login.authenticationDetailsSource(authenticationDetailsSource) }
-            usernameParameter?.also { login.usernameParameter(usernameParameter) }
-            passwordParameter?.also { login.passwordParameter(passwordParameter) }
             if (disabled) {
                 login.disable()
             }

+ 1 - 64
config/src/main/kotlin/org/springframework/security/config/annotation/web/HttpSecurityDsl.kt

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2023 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -707,69 +707,6 @@ class HttpSecurityDsl(private val http: HttpSecurity, private val init: HttpSecu
         this.http.saml2Login(saml2LoginCustomizer)
     }
 
-    /**
-     * Configures logout support for a SAML 2.0 Service Provider. <br>
-     * <br>
-     *
-     * Implements the <b>Single Logout Profile, using POST and REDIRECT bindings</b>, as
-     * documented in the
-     * <a target="_blank" href="https://docs.oasis-open.org/security/saml/">SAML V2.0
-     * Core, Profiles and Bindings</a> specifications. <br>
-     * <br>
-     *
-     * As a prerequisite to using this feature, is that you have a SAML v2.0 Asserting
-     * Party to send a logout request to. The representation of the relying party and the
-     * asserting party is contained within [RelyingPartyRegistration]. <br>
-     * <br>
-     *
-     * [RelyingPartyRegistration] (s) are composed within a
-     * [RelyingPartyRegistrationRepository], which is <b>required</b> and must be
-     * registered with the [ApplicationContext] or configured via
-     * [HttpSecurityDsl.saml2Login].<br>
-     * <br>
-     *
-     * The default configuration provides an auto-generated logout endpoint at
-     * `/logout` and redirects to `/login?logout` when
-     * logout completes. <br>
-     * <br>
-     *
-     * <p>
-     * <h2>Example Configuration</h2>
-     *
-     * The following example shows the minimal configuration required, using a
-     * hypothetical asserting party.
-     *
-     * Example:
-     *
-     * ```
-     * @Configuration
-     * @EnableWebSecurity
-     * class SecurityConfig {
-     *
-     *     @Bean
-     *     fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
-     *         http {
-     *             saml2Login {
-     *                 relyingPartyRegistration = getSaml2RelyingPartyRegistration()
-     *             }
-     *             saml2Logout { }
-     *         }
-     *         return http.build()
-     *     }
-     * }
-     * ```
-     *
-     * <p>
-     * @param saml2LogoutConfiguration custom configuration to configure the
-     * SAML 2.0 service provider
-     * @since 6.3
-     * @see [Saml2LogoutDsl]
-     */
-    fun saml2Logout(saml2LogoutConfiguration: Saml2LogoutDsl.() -> Unit) {
-        val saml2LogoutCustomizer = Saml2LogoutDsl().apply(saml2LogoutConfiguration).get()
-        this.http.saml2Logout(saml2LogoutCustomizer)
-    }
-
 	/**
 	 * Configures a SAML 2.0 relying party metadata endpoint.
 	 *

+ 0 - 69
config/src/main/kotlin/org/springframework/security/config/annotation/web/Saml2LogoutDsl.kt

@@ -1,69 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.config.annotation.web
-
-import org.springframework.security.config.annotation.web.builders.HttpSecurity
-import org.springframework.security.config.annotation.web.configurers.saml2.Saml2LogoutConfigurer
-import org.springframework.security.config.annotation.web.saml2.LogoutRequestDsl
-import org.springframework.security.config.annotation.web.saml2.LogoutResponseDsl
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository
-
-/**
- * A Kotlin DSL to configure [HttpSecurity] SAML2 logout using idiomatic Kotlin code.
- *
- * @author Josh Cummings
- * @since 6.3
- * @property relyingPartyRegistrationRepository the [RelyingPartyRegistrationRepository] of relying parties,
- * each party representing a service provider, SP and this host, and identity provider, IDP pair that
- * communicate with each other.
- * @property logoutUrl the logout page to begin the SLO redirect flow
- */
-@SecurityMarker
-class Saml2LogoutDsl {
-    var relyingPartyRegistrationRepository: RelyingPartyRegistrationRepository? = null
-    var logoutUrl: String? = null
-
-    private var logoutRequest: ((Saml2LogoutConfigurer<HttpSecurity>.LogoutRequestConfigurer) -> Unit)? = null
-    private var logoutResponse: ((Saml2LogoutConfigurer<HttpSecurity>.LogoutResponseConfigurer) -> Unit)? = null
-
-    /**
-     * Configures SAML 2.0 Logout Request components
-     * @param logoutRequestConfig the {@link Customizer} to provide more
-     * options for the {@link LogoutRequestConfigurer}
-     */
-    fun logoutRequest(logoutRequestConfig: LogoutRequestDsl.() -> Unit) {
-        this.logoutRequest = LogoutRequestDsl().apply(logoutRequestConfig).get()
-    }
-
-    /**
-     * Configures SAML 2.0 Logout Response components
-     * @param logoutResponseConfig the {@link Customizer} to provide more
-     * options for the {@link LogoutResponseConfigurer}
-     */
-    fun logoutResponse(logoutResponseConfig: LogoutResponseDsl.() -> Unit) {
-        this.logoutResponse = LogoutResponseDsl().apply(logoutResponseConfig).get()
-    }
-
-    internal fun get(): (Saml2LogoutConfigurer<HttpSecurity>) -> Unit {
-        return { saml2Logout ->
-            relyingPartyRegistrationRepository?.also { saml2Logout.relyingPartyRegistrationRepository(relyingPartyRegistrationRepository) }
-            logoutUrl?.also { saml2Logout.logoutUrl(logoutUrl) }
-            logoutRequest?.also { saml2Logout.logoutRequest(logoutRequest) }
-            logoutResponse?.also { saml2Logout.logoutResponse(logoutResponse) }
-        }
-    }
-}

+ 0 - 53
config/src/main/kotlin/org/springframework/security/config/annotation/web/saml2/LogoutRequestDsl.kt

@@ -1,53 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.config.annotation.web.saml2
-
-import org.springframework.security.config.annotation.web.builders.HttpSecurity
-import org.springframework.security.config.annotation.web.configurers.saml2.Saml2LogoutConfigurer
-import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequestValidator
-import org.springframework.security.saml2.provider.service.web.authentication.logout.HttpSessionLogoutRequestRepository
-import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutRequestRepository
-import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutRequestResolver
-
-/**
- * A Kotlin DSL to configure SAML 2.0 Logout Request components using idiomatic Kotlin code.
- *
- * @author Josh Cummings
- * @since 6.3
- * @property logoutUrl The URL by which the asserting party can send a SAML 2.0 Logout Request.
- * The Asserting Party should use whatever HTTP method specified in {@link RelyingPartyRegistration#getSingleLogoutServiceBindings()}.
- * @property logoutRequestValidator the [Saml2LogoutRequestValidator] to use for validating incoming {@code LogoutRequest}s.
- * @property logoutRequestResolver the [Saml2LogoutRequestResolver] to use for generating outgoing {@code LogoutRequest}s.
- * @property logoutRequestRepository the [Saml2LogoutRequestRepository] to use for storing outgoing {@code LogoutRequest}s for
- * linking to the corresponding {@code LogoutResponse} from the asserting party
- */
-@Saml2SecurityMarker
-class LogoutRequestDsl {
-    var logoutUrl = "/logout/saml2/slo"
-    var logoutRequestValidator: Saml2LogoutRequestValidator? = null
-    var logoutRequestResolver: Saml2LogoutRequestResolver? = null
-    var logoutRequestRepository: Saml2LogoutRequestRepository = HttpSessionLogoutRequestRepository()
-
-    internal fun get(): (Saml2LogoutConfigurer<HttpSecurity>.LogoutRequestConfigurer) -> Unit {
-        return { logoutRequest ->
-            logoutUrl.also { logoutRequest.logoutUrl(logoutUrl) }
-            logoutRequestValidator?.also { logoutRequest.logoutRequestValidator(logoutRequestValidator) }
-            logoutRequestResolver?.also { logoutRequest.logoutRequestResolver(logoutRequestResolver) }
-            logoutRequestRepository.also { logoutRequest.logoutRequestRepository(logoutRequestRepository) }
-        }
-    }
-}

+ 0 - 47
config/src/main/kotlin/org/springframework/security/config/annotation/web/saml2/LogoutResponseDsl.kt

@@ -1,47 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.config.annotation.web.saml2
-
-import org.springframework.security.config.annotation.web.builders.HttpSecurity
-import org.springframework.security.config.annotation.web.configurers.saml2.Saml2LogoutConfigurer
-import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutResponseValidator
-import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutResponseResolver
-
-/**
- * A Kotlin DSL to configure SAML 2.0 Logout Response components using idiomatic Kotlin code.
- *
- * @author Josh Cummings
- * @since 6.3
- * @property logoutUrl The URL by which the asserting party can send a SAML 2.0 Logout Response.
- * The Asserting Party should use whatever HTTP method specified in {@link RelyingPartyRegistration#getSingleLogoutServiceBindings()}.
- * @property logoutResponseValidator the [Saml2LogoutResponseValidator] to use for validating incoming {@code LogoutResponse}s.
- * @property logoutResponseResolver the [Saml2LogoutResponseResolver] to use for generating outgoing {@code LogoutResponse}s.
- */
-@Saml2SecurityMarker
-class LogoutResponseDsl {
-    var logoutUrl = "/logout/saml2/slo"
-    var logoutResponseValidator: Saml2LogoutResponseValidator? = null
-    var logoutResponseResolver: Saml2LogoutResponseResolver? = null
-
-    internal fun get(): (Saml2LogoutConfigurer<HttpSecurity>.LogoutResponseConfigurer) -> Unit {
-        return { logoutResponse ->
-            logoutUrl.also { logoutResponse.logoutUrl(logoutUrl) }
-            logoutResponseValidator?.also { logoutResponse.logoutResponseValidator(logoutResponseValidator) }
-            logoutResponseResolver?.also { logoutResponse.logoutResponseResolver(logoutResponseResolver) }
-        }
-    }
-}

+ 0 - 26
config/src/main/kotlin/org/springframework/security/config/annotation/web/saml2/Saml2SecurityMarker.kt

@@ -1,26 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.config.annotation.web.saml2
-
-/**
- * Marker annotation indicating that the annotated class is part of the SAML 2.0 logout security DSL.
- *
- * @author Josh Cummings
- * @since 6.3
- */
-@DslMarker
-annotation class Saml2SecurityMarker

+ 0 - 30
config/src/main/kotlin/org/springframework/security/config/web/server/ServerHttpSecurityDsl.kt

@@ -682,36 +682,6 @@ class ServerHttpSecurityDsl(private val http: ServerHttpSecurity, private val in
         this.http.oidcLogout(oidcLogoutCustomizer)
     }
 
-    /**
-     * Configures Session Management support.
-     *
-     * Example:
-     *
-     * ```
-     * @Configuration
-     * @EnableWebFluxSecurity
-     * open class SecurityConfig {
-     *
-     *  @Bean
-     *  open fun springWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
-     *      return http {
-     *          sessionManagement {
-     *              sessionConcurrency { }
-     *          }
-     *       }
-     *   }
-     * }
-     * ```
-     *
-     * @param sessionManagementConfig custom configuration to configure the Session Management
-     * @since 6.3
-     * @see [ServerSessionManagementDsl]
-     */
-    fun sessionManagement(sessionManagementConfig: ServerSessionManagementDsl.() -> Unit) {
-        val sessionManagementCustomizer = ServerSessionManagementDsl().apply(sessionManagementConfig).get()
-        this.http.sessionManagement(sessionManagementCustomizer)
-    }
-
     /**
      * Apply all configurations to the provided [ServerHttpSecurity]
      */

+ 0 - 48
config/src/main/kotlin/org/springframework/security/config/web/server/ServerSessionConcurrencyDsl.kt

@@ -1,48 +0,0 @@
-/*
- * Copyright 2002-2023 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.config.web.server
-
-import org.springframework.security.core.session.ReactiveSessionRegistry
-import org.springframework.security.web.server.authentication.ServerMaximumSessionsExceededHandler
-import org.springframework.security.web.server.authentication.SessionLimit
-
-/**
- * A Kotlin DSL to configure [ServerHttpSecurity] Session Concurrency support using idiomatic Kotlin code.
- *
- * @author Marcus da Coregio
- * @since 6.3
- */
-@ServerSecurityMarker
-class ServerSessionConcurrencyDsl {
-    var maximumSessions: SessionLimit? = null
-    var maximumSessionsExceededHandler: ServerMaximumSessionsExceededHandler? = null
-    var sessionRegistry: ReactiveSessionRegistry? = null
-
-    internal fun get(): (ServerHttpSecurity.SessionManagementSpec.ConcurrentSessionsSpec) -> Unit {
-        return { sessionConcurrency ->
-            maximumSessions?.also {
-                sessionConcurrency.maximumSessions(maximumSessions!!)
-            }
-            maximumSessionsExceededHandler?.also {
-                sessionConcurrency.maximumSessionsExceededHandler(maximumSessionsExceededHandler!!)
-            }
-            sessionRegistry?.also {
-                sessionConcurrency.sessionRegistry(sessionRegistry!!)
-            }
-        }
-    }
-}

+ 0 - 64
config/src/main/kotlin/org/springframework/security/config/web/server/ServerSessionManagementDsl.kt

@@ -1,64 +0,0 @@
-/*
- * Copyright 2002-2023 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.config.web.server
-
-/**
- * A Kotlin DSL to configure [ServerHttpSecurity] Session Management using idiomatic Kotlin code.
- *
- * @author Marcus da Coregio
- * @since 6.3
- */
-@ServerSecurityMarker
-class ServerSessionManagementDsl {
-    private var sessionConcurrency: ((ServerHttpSecurity.SessionManagementSpec.ConcurrentSessionsSpec) -> Unit)? = null
-
-    /**
-     * Enables Session Management support.
-     *
-     * Example:
-     *
-     * ```
-     * @Configuration
-     * @EnableWebFluxSecurity
-     * open class SecurityConfig {
-     *
-     *  @Bean
-     *  open fun springWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
-     *      return http {
-     *          sessionManagement {
-     *              sessionConcurrency {
-     *                  maximumSessions = { authentication -> Mono.just(1) }
-     *              }
-     *          }
-     *       }
-     *   }
-     * }
-     * ```
-     *
-     * @param backChannelConfig custom configurations to configure OIDC 1.0 Back-Channel Logout support
-     * @see [ServerOidcBackChannelLogoutDsl]
-     */
-    fun sessionConcurrency(sessionConcurrencyConfig: ServerSessionConcurrencyDsl.() -> Unit) {
-        this.sessionConcurrency = ServerSessionConcurrencyDsl().apply(sessionConcurrencyConfig).get()
-    }
-
-    internal fun get(): (ServerHttpSecurity.SessionManagementSpec) -> Unit {
-        return { sessionManagement ->
-            sessionConcurrency?.also { sessionManagement.concurrentSessions(sessionConcurrency) }
-        }
-    }
-}

+ 2 - 4
config/src/main/resources/META-INF/spring.schemas

@@ -1,5 +1,4 @@
-http\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-6.3.xsd
-http\://www.springframework.org/schema/security/spring-security-6.3.xsd=org/springframework/security/config/spring-security-6.3.xsd
+http\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-6.2.xsd
 http\://www.springframework.org/schema/security/spring-security-6.2.xsd=org/springframework/security/config/spring-security-6.2.xsd
 http\://www.springframework.org/schema/security/spring-security-6.1.xsd=org/springframework/security/config/spring-security-6.1.xsd
 http\://www.springframework.org/schema/security/spring-security-6.0.xsd=org/springframework/security/config/spring-security-6.0.xsd
@@ -23,8 +22,7 @@ http\://www.springframework.org/schema/security/spring-security-2.0.xsd=org/spri
 http\://www.springframework.org/schema/security/spring-security-2.0.1.xsd=org/springframework/security/config/spring-security-2.0.1.xsd
 http\://www.springframework.org/schema/security/spring-security-2.0.2.xsd=org/springframework/security/config/spring-security-2.0.2.xsd
 http\://www.springframework.org/schema/security/spring-security-2.0.4.xsd=org/springframework/security/config/spring-security-2.0.4.xsd
-https\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-6.3.xsd
-https\://www.springframework.org/schema/security/spring-security-6.3.xsd=org/springframework/security/config/spring-security-6.3.xsd
+https\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-6.2.xsd
 https\://www.springframework.org/schema/security/spring-security-6.2.xsd=org/springframework/security/config/spring-security-6.2.xsd
 https\://www.springframework.org/schema/security/spring-security-6.1.xsd=org/springframework/security/config/spring-security-6.1.xsd
 https\://www.springframework.org/schema/security/spring-security-6.0.xsd=org/springframework/security/config/spring-security-6.0.xsd

+ 0 - 1349
config/src/main/resources/org/springframework/security/config/spring-security-6.3.rnc

@@ -1,1349 +0,0 @@
-namespace a = "https://relaxng.org/ns/compatibility/annotations/1.0"
-datatypes xsd = "http://www.w3.org/2001/XMLSchema-datatypes"
-
-default namespace = "http://www.springframework.org/schema/security"
-
-start = http | ldap-server | authentication-provider | ldap-authentication-provider | any-user-service | ldap-server | ldap-authentication-provider
-
-hash =
-	## Defines the hashing algorithm used on user passwords. Bcrypt is recommended.
-	attribute hash {"bcrypt"}
-base64 =
-	## Whether a string should be base64 encoded
-	attribute base64 {xsd:boolean}
-request-matcher =
-	## Defines the strategy use for matching incoming requests. Currently the options are 'mvc' (for Spring MVC matcher), 'ant' (for ant path patterns), 'regex' for regular expressions and 'ciRegex' for case-insensitive regular expressions.
-	attribute request-matcher {"mvc" | "ant" | "regex" | "ciRegex"}
-port =
-	## Specifies an IP port number. Used to configure an embedded LDAP server, for example.
-	attribute port { xsd:nonNegativeInteger }
-url =
-	## Specifies a URL.
-	attribute url { xsd:token }
-id =
-	## A bean identifier, used for referring to the bean elsewhere in the context.
-	attribute id {xsd:token}
-name =
-	## A bean identifier, used for referring to the bean elsewhere in the context.
-	attribute name {xsd:token}
-ref =
-	## Defines a reference to a Spring bean Id.
-	attribute ref {xsd:token}
-
-cache-ref =
-	## Defines a reference to a cache for use with a UserDetailsService.
-	attribute cache-ref {xsd:token}
-
-user-service-ref =
-	## A reference to a user-service (or UserDetailsService bean) Id
-	attribute user-service-ref {xsd:token}
-
-authentication-manager-ref =
-	## A reference to an AuthenticationManager bean
-	attribute authentication-manager-ref {xsd:token}
-
-data-source-ref =
-	## A reference to a DataSource bean
-	attribute data-source-ref {xsd:token}
-
-
-
-debug =
-	## Enables Spring Security debugging infrastructure. This will provide human-readable (multi-line) debugging information to monitor requests coming into the security filters. This may include sensitive information, such as request parameters or headers, and should only be used in a development environment.
-	element debug {empty}
-
-password-encoder =
-	## element which defines a password encoding strategy. Used by an authentication provider to convert submitted passwords to hashed versions, for example.
-	element password-encoder {password-encoder.attlist}
-password-encoder.attlist &=
-	ref | (hash)
-
-role-prefix =
-	## A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty.
-	attribute role-prefix {xsd:token}
-
-use-expressions =
-	## Enables the use of expressions in the 'access' attributes in <intercept-url> elements rather than the traditional list of configuration attributes. Defaults to 'true'. If enabled, each attribute should contain a single boolean expression. If the expression evaluates to 'true', access will be granted.
-	attribute use-expressions {xsd:boolean}
-
-ldap-server =
-	## Defines an LDAP server location or starts an embedded server. The url indicates the location of a remote server. If no url is given, an embedded server will be started, listening on the supplied port number. The port is optional and defaults to 33389. A Spring LDAP ContextSource bean will be registered for the server with the id supplied.
-	element ldap-server {ldap-server.attlist}
-ldap-server.attlist &= id?
-ldap-server.attlist &= (url | port)?
-ldap-server.attlist &=
-	## Username (DN) of the "manager" user identity which will be used to authenticate to a (non-embedded) LDAP server. If omitted, anonymous access will be used.
-	attribute manager-dn {xsd:string}?
-ldap-server.attlist &=
-	## The password for the manager DN. This is required if the manager-dn is specified.
-	attribute manager-password {xsd:string}?
-ldap-server.attlist &=
-	## Explicitly specifies an ldif file resource to load into an embedded LDAP server. The default is classpath*:*.ldiff
-	attribute ldif { xsd:string }?
-ldap-server.attlist &=
-	## Optional root suffix for the embedded LDAP server. Default is "dc=springframework,dc=org"
-	attribute root { xsd:string }?
-ldap-server.attlist &=
-	## Explicitly specifies which embedded ldap server should use. Values are 'apacheds' and 'unboundid'. By default, it will depends if the library is available in the classpath.
-	attribute mode { "apacheds" | "unboundid" }?
-
-ldap-server-ref-attribute =
-	## The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used.
-	attribute server-ref {xsd:token}
-
-
-group-search-filter-attribute =
-	## Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user.
-	attribute group-search-filter {xsd:token}
-group-search-base-attribute =
-	## Search base for group membership searches. Defaults to "" (searching from the root).
-	attribute group-search-base {xsd:token}
-user-search-filter-attribute =
-	## The LDAP filter used to search for users (optional). For example "(uid={0})". The substituted parameter is the user's login name.
-	attribute user-search-filter {xsd:token}
-user-search-base-attribute =
-	## Search base for user searches. Defaults to "". Only used with a 'user-search-filter'.
-	attribute user-search-base {xsd:token}
-group-role-attribute-attribute =
-	## The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn".
-	attribute group-role-attribute {xsd:token}
-user-details-class-attribute =
-	## Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object
-	attribute user-details-class {"person" | "inetOrgPerson"}
-user-context-mapper-attribute =
-	## Allows explicit customization of the loaded user object by specifying a UserDetailsContextMapper bean which will be called with the context information from the user's directory entry
-	attribute user-context-mapper-ref {xsd:token}
-
-
-ldap-user-service =
-	## This element configures a LdapUserDetailsService which is a combination of a FilterBasedLdapUserSearch and a DefaultLdapAuthoritiesPopulator.
-	element ldap-user-service {ldap-us.attlist}
-ldap-us.attlist &= id?
-ldap-us.attlist &=
-	ldap-server-ref-attribute?
-ldap-us.attlist &=
-	user-search-filter-attribute?
-ldap-us.attlist &=
-	user-search-base-attribute?
-ldap-us.attlist &=
-	group-search-filter-attribute?
-ldap-us.attlist &=
-	group-search-base-attribute?
-ldap-us.attlist &=
-	group-role-attribute-attribute?
-ldap-us.attlist &=
-	cache-ref?
-ldap-us.attlist &=
-	role-prefix?
-ldap-us.attlist &=
-	(user-details-class-attribute | user-context-mapper-attribute)?
-
-ldap-authentication-provider =
-	## Sets up an ldap authentication provider
-	element ldap-authentication-provider {ldap-ap.attlist, password-compare-element?}
-ldap-ap.attlist &=
-	ldap-server-ref-attribute?
-ldap-ap.attlist &=
-	user-search-base-attribute?
-ldap-ap.attlist &=
-	user-search-filter-attribute?
-ldap-ap.attlist &=
-	group-search-base-attribute?
-ldap-ap.attlist &=
-	group-search-filter-attribute?
-ldap-ap.attlist &=
-	group-role-attribute-attribute?
-ldap-ap.attlist &=
-	## A specific pattern used to build the user's DN, for example "uid={0},ou=people". The key "{0}" must be present and will be substituted with the username.
-	attribute user-dn-pattern {xsd:token}?
-ldap-ap.attlist &=
-	role-prefix?
-ldap-ap.attlist &=
-	(user-details-class-attribute | user-context-mapper-attribute)?
-
-password-compare-element =
-	## Specifies that an LDAP provider should use an LDAP compare operation of the user's password to authenticate the user
-	element password-compare {password-compare.attlist, password-encoder?}
-
-password-compare.attlist &=
-	## The attribute in the directory which contains the user password. Defaults to "userPassword".
-	attribute password-attribute {xsd:token}?
-password-compare.attlist &=
-	hash?
-
-intercept-methods =
-	## Can be used inside a bean definition to add a security interceptor to the bean and set up access configuration attributes for the bean's methods
-	element intercept-methods {intercept-methods.attlist, protect+}
-intercept-methods.attlist &=
-	## Optional AccessDecisionManager bean ID to be used by the created method security interceptor.
-	attribute access-decision-manager-ref {xsd:token}?
-intercept-methods.attlist &=
-	## Use the AuthorizationManager API instead of AccessDecisionManager (defaults to true)
-	attribute use-authorization-manager {xsd:boolean}?
-intercept-methods.attlist &=
-	## Use this AuthorizationManager instead of the default (supercedes use-authorization-manager)
-	attribute authorization-manager-ref {xsd:token}?
-
-protect =
-	## Defines a protected method and the access control configuration attributes that apply to it. We strongly advise you NOT to mix "protect" declarations with any services provided "global-method-security".
-	element protect {protect.attlist, empty}
-protect.attlist &=
-	## A method name
-	attribute method {xsd:token}
-protect.attlist &=
-	## Access configuration attributes list that applies to the method, e.g. "ROLE_A,ROLE_B".
-	attribute access {xsd:token}
-
-method-security-metadata-source =
-	## Creates a MethodSecurityMetadataSource instance
-	element method-security-metadata-source {msmds.attlist, protect+}
-msmds.attlist &= id?
-
-msmds.attlist &= use-expressions?
-
-method-security =
-	## Provides method security for all beans registered in the Spring application context. Specifically, beans will be scanned for matches with Spring Security annotations. Where there is a match, the beans will automatically be proxied and security authorization applied to the methods accordingly. Interceptors are invoked in the order specified in AuthorizationInterceptorsOrder. Use can create your own interceptors using Spring AOP. Also, annotation-based interception can be overridden by expressions listed in <protect-pointcut> elements.
-	element method-security {method-security.attlist, expression-handler?, protect-pointcut*}
-method-security.attlist &=
-	## Specifies whether the use of Spring Security's pre and post invocation annotations (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) should be enabled for this application context. Defaults to "true".
-	attribute pre-post-enabled {xsd:boolean}?
-method-security.attlist &=
-	## Specifies whether the use of Spring Security's @Secured annotations should be enabled for this application context. Defaults to "false".
-	attribute secured-enabled {xsd:boolean}?
-method-security.attlist &=
-	## Specifies whether JSR-250 style attributes are to be used (for example "RolesAllowed"). This will require the javax.annotation.security classes on the classpath. Defaults to "false".
-	attribute jsr250-enabled {xsd:boolean}?
-method-security.attlist &=
-	## If true, class-based proxying will be used instead of interface-based proxying.
-	attribute proxy-target-class {xsd:boolean}?
-method-security.attlist &=
-	## If set to aspectj, then use AspectJ to intercept method invocation
-	attribute mode {"aspectj"}?
-method-security.attlist &=
-	## Specifies the security context holder strategy to use, by default uses a ThreadLocal-based strategy
-	attribute security-context-holder-strategy-ref {xsd:string}?
-method-security.attlist &=
-	## Use this ObservationRegistry to collect metrics on various parts of the filter chain
-	attribute observation-registry-ref {xsd:token}?
-
-global-method-security =
-	## Provides method security for all beans registered in the Spring application context. Specifically, beans will be scanned for matches with the ordered list of "protect-pointcut" sub-elements, Spring Security annotations and/or. Where there is a match, the beans will automatically be proxied and security authorization applied to the methods accordingly. If you use and enable all four sources of method security metadata (ie "protect-pointcut" declarations, expression annotations, @Secured and also JSR250 security annotations), the metadata sources will be queried in that order. In practical terms, this enables you to use XML to override method security metadata expressed in annotations. If using annotations, the order of precedence is EL-based (@PreAuthorize etc.), @Secured and finally JSR-250.
-	element global-method-security {global-method-security.attlist, (pre-post-annotation-handling | expression-handler)?, protect-pointcut*, after-invocation-provider*}
-global-method-security.attlist &=
-	## Specifies whether the use of Spring Security's pre and post invocation annotations (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) should be enabled for this application context. Defaults to "disabled".
-	attribute pre-post-annotations {"disabled" | "enabled" }?
-global-method-security.attlist &=
-	## Specifies whether the use of Spring Security's @Secured annotations should be enabled for this application context. Defaults to "disabled".
-	attribute secured-annotations {"disabled" | "enabled" }?
-global-method-security.attlist &=
-	## Specifies whether JSR-250 style attributes are to be used (for example "RolesAllowed"). This will require the javax.annotation.security classes on the classpath. Defaults to "disabled".
-	attribute jsr250-annotations {"disabled" | "enabled" }?
-global-method-security.attlist &=
-	## Optional AccessDecisionManager bean ID to override the default used for method security.
-	attribute access-decision-manager-ref {xsd:token}?
-global-method-security.attlist &=
-	## Optional RunAsmanager implementation which will be used by the configured MethodSecurityInterceptor
-	attribute run-as-manager-ref {xsd:token}?
-global-method-security.attlist &=
-	## Allows the advice "order" to be set for the method security interceptor.
-	attribute order {xsd:token}?
-global-method-security.attlist &=
-	## If true, class based proxying will be used instead of interface based proxying.
-	attribute proxy-target-class {xsd:boolean}?
-global-method-security.attlist &=
-	## Can be used to specify that AspectJ should be used instead of the default Spring AOP. If set, secured classes must be woven with the AnnotationSecurityAspect from the spring-security-aspects module.
-	attribute mode {"aspectj"}?
-global-method-security.attlist &=
-	## An external MethodSecurityMetadataSource instance can be supplied which will take priority over other sources (such as the default annotations).
-	attribute metadata-source-ref {xsd:token}?
-global-method-security.attlist &=
-	authentication-manager-ref?
-
-
-after-invocation-provider =
-	## Allows addition of extra AfterInvocationProvider beans which should be called by the MethodSecurityInterceptor created by global-method-security.
-	element after-invocation-provider {ref}
-
-pre-post-annotation-handling =
-	## Allows the default expression-based mechanism for handling Spring Security's pre and post invocation annotations (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) to be replace entirely. Only applies if these annotations are enabled.
-	element pre-post-annotation-handling {invocation-attribute-factory, pre-invocation-advice, post-invocation-advice}
-
-invocation-attribute-factory =
-	## Defines the PrePostInvocationAttributeFactory instance which is used to generate pre and post invocation metadata from the annotated methods.
-	element invocation-attribute-factory {ref}
-
-pre-invocation-advice =
-	## Customizes the PreInvocationAuthorizationAdviceVoter with the ref as the PreInvocationAuthorizationAdviceVoter for the <pre-post-annotation-handling> element.
-	element pre-invocation-advice {ref}
-
-post-invocation-advice =
-	## Customizes the PostInvocationAdviceProvider with the ref as the PostInvocationAuthorizationAdvice for the <pre-post-annotation-handling> element.
-	element post-invocation-advice {ref}
-
-
-expression-handler =
-	## Defines the SecurityExpressionHandler instance which will be used if expression-based access-control is enabled. A default implementation (with no ACL support) will be used if not supplied.
-	element expression-handler {ref}
-
-protect-pointcut =
-	## Defines a protected pointcut and the access control configuration attributes that apply to it. Every bean registered in the Spring application context that provides a method that matches the pointcut will receive security authorization.
-	element protect-pointcut {protect-pointcut.attlist, empty}
-protect-pointcut.attlist &=
-	## An AspectJ expression, including the 'execution' keyword. For example, 'execution(int com.foo.TargetObject.countLength(String))' (without the quotes).
-	attribute expression {xsd:string}
-protect-pointcut.attlist &=
-	## Access configuration attributes list that applies to all methods matching the pointcut, e.g. "ROLE_A,ROLE_B"
-	attribute access {xsd:token}
-
-websocket-message-broker =
-	## Allows securing a Message Broker. There are two modes. If no id is specified: ensures that any SimpAnnotationMethodMessageHandler has the AuthenticationPrincipalArgumentResolver registered as a custom argument resolver; ensures that the SecurityContextChannelInterceptor is automatically registered for the clientInboundChannel; and that a ChannelSecurityInterceptor is registered with the clientInboundChannel. If the id is specified, creates a ChannelSecurityInterceptor that can be manually registered with the clientInboundChannel.
-	element websocket-message-broker { websocket-message-broker.attrlist, (intercept-message* & expression-handler?) }
-
-websocket-message-broker.attrlist &=
-	## A bean identifier, used for referring to the bean elsewhere in the context. If specified, explicit configuration within clientInboundChannel is required. If not specified, ensures that any SimpAnnotationMethodMessageHandler has the AuthenticationPrincipalArgumentResolver registered as a custom argument resolver; ensures that the SecurityContextChannelInterceptor is automatically registered for the clientInboundChannel; and that a ChannelSecurityInterceptor is registered with the clientInboundChannel.
-	attribute id {xsd:token}?
-websocket-message-broker.attrlist &=
-	## Disables the requirement for CSRF token to be present in the Stomp headers (default false). Changing the default is useful if it is necessary to allow other origins to make SockJS connections.
-	attribute same-origin-disabled {xsd:boolean}?
-websocket-message-broker.attrlist &=
-	## Use this AuthorizationManager instead of deriving one from <intercept-message> elements
-	attribute authorization-manager-ref {xsd:string}?
-websocket-message-broker.attrlist &=
-	## Use AuthorizationManager API instead of SecurityMetadatasource (defaults to true)
-	attribute use-authorization-manager {xsd:boolean}?
-websocket-message-broker.attrlist &=
-	## Use this SecurityContextHolderStrategy (note only supported in conjunction with the AuthorizationManager API)
-	attribute security-context-holder-strategy-ref {xsd:string}?
-
-intercept-message =
-	## Creates an authorization rule for a websocket message.
-	element intercept-message {intercept-message.attrlist}
-
-intercept-message.attrlist &=
-	## The destination ant pattern which will be mapped to the access attribute. For example, /** matches any message with a destination, /admin/** matches any message that has a destination that starts with admin.
-	attribute pattern {xsd:token}?
-intercept-message.attrlist &=
-	## The access configuration attributes that apply for the configured message. For example, permitAll grants access to anyone, hasRole('ROLE_ADMIN') requires the user have the role 'ROLE_ADMIN'.
-	attribute access {xsd:token}?
-intercept-message.attrlist &=
-	## The type of message to match on. Valid values are defined in SimpMessageType (i.e. CONNECT, CONNECT_ACK, HEARTBEAT, MESSAGE, SUBSCRIBE, UNSUBSCRIBE, DISCONNECT, DISCONNECT_ACK, OTHER).
-	attribute type {"CONNECT" | "CONNECT_ACK" | "HEARTBEAT" | "MESSAGE" | "SUBSCRIBE"| "UNSUBSCRIBE" | "DISCONNECT" | "DISCONNECT_ACK" | "OTHER"}?
-
-http-firewall =
-	## Allows a custom instance of HttpFirewall to be injected into the FilterChainProxy created by the namespace.
-	element http-firewall {ref}
-
-http =
-	## Container element for HTTP security configuration. Multiple elements can now be defined, each with a specific pattern to which the enclosed security configuration applies. A pattern can also be configured to bypass Spring Security's filters completely by setting the "security" attribute to "none".
-	element http {http.attlist, (intercept-url* & access-denied-handler? & form-login? & oauth2-login? & oauth2-client? & oauth2-resource-server? & saml2-login? & saml2-logout? & x509? & jee? & http-basic? & logout? & password-management? & session-management & remember-me? & anonymous? & port-mappings & custom-filter* & request-cache? & expression-handler? & headers? & csrf? & cors?) }
-http.attlist &=
-	## The request URL pattern which will be mapped to the filter chain created by this <http> element. If omitted, the filter chain will match all requests.
-	attribute pattern {xsd:token}?
-http.attlist &=
-	## When set to 'none', requests matching the pattern attribute will be ignored by Spring Security. No security filters will be applied and no SecurityContext will be available. If set, the <http> element must be empty, with no children.
-	attribute security {"none"}?
-http.attlist &=
-	## Allows a RequestMatcher instance to be used, as an alternative to pattern-matching.
-	attribute request-matcher-ref { xsd:token }?
-http.attlist &=
-	## A legacy attribute which automatically registers a login form, BASIC authentication and a logout URL and logout services. If unspecified, defaults to "false". We'd recommend you avoid using this and instead explicitly configure the services you require.
-	attribute auto-config {xsd:boolean}?
-http.attlist &=
-	use-expressions?
-http.attlist &=
-	## A reference to a SecurityContextHolderStrategy bean. This can be used to customize how the SecurityContextHolder is stored during a request
-	attribute security-context-holder-strategy-ref {xsd:token}?
-http.attlist &=
-	## Controls the eagerness with which an HTTP session is created by Spring Security classes. If not set, defaults to "ifRequired". If "stateless" is used, this implies that the application guarantees that it will not create a session. This differs from the use of "never" which means that Spring Security will not create a session, but will make use of one if the application does.
-	attribute create-session {"ifRequired" | "always" | "never" | "stateless"}?
-http.attlist &=
-	## A reference to a SecurityContextRepository bean. This can be used to customize how the SecurityContext is stored between requests.
-	attribute security-context-repository-ref {xsd:token}?
-http.attlist &=
-	## Optional attribute that specifies that the SecurityContext should require explicit saving rather than being synchronized from the SecurityContextHolder. Defaults to "true".
-	attribute security-context-explicit-save {xsd:boolean}?
-http.attlist &=
-	request-matcher?
-http.attlist &=
-	## Provides versions of HttpServletRequest security methods such as isUserInRole() and getPrincipal() which are implemented by accessing the Spring SecurityContext. Defaults to "true".
-	attribute servlet-api-provision {xsd:boolean}?
-http.attlist &=
-	## If available, runs the request as the Subject acquired from the JaasAuthenticationToken. Defaults to "false".
-	attribute jaas-api-provision {xsd:boolean}?
-http.attlist &=
-	## Use AuthorizationManager API instead of SecurityMetadataSource (defaults to true)
-	attribute use-authorization-manager {xsd:boolean}?
-http.attlist &=
-	## Use this AuthorizationManager instead of deriving one from <intercept-url> elements
-	attribute authorization-manager-ref {xsd:token}?
-http.attlist &=
-	## Optional attribute specifying the ID of the AccessDecisionManager implementation which should be used for authorizing HTTP requests.
-	attribute access-decision-manager-ref {xsd:token}?
-http.attlist &=
-	## Optional attribute specifying the realm name that will be used for all authentication features that require a realm name (eg BASIC and Digest authentication). If unspecified, defaults to "Spring Security Application".
-	attribute realm {xsd:token}?
-http.attlist &=
-	## Allows a customized AuthenticationEntryPoint to be set on the ExceptionTranslationFilter.
-	attribute entry-point-ref {xsd:token}?
-http.attlist &=
-	## Corresponds to the observeOncePerRequest property of FilterSecurityInterceptor. Defaults to "false"
-	attribute once-per-request {xsd:boolean}?
-http.attlist &=
-	## Corresponds to the shouldFilterAllDispatcherTypes property of AuthorizationFilter. Do not work when use-authorization-manager=false. Defaults to "true".
-	attribute filter-all-dispatcher-types {xsd:boolean}?
-http.attlist &=
-	## Prevents the jsessionid parameter from being added to rendered URLs. Defaults to "true" (rewriting is disabled).
-	attribute disable-url-rewriting {xsd:boolean}?
-http.attlist &=
-	## Exposes the list of filters defined by this configuration under this bean name in the application context.
-	name?
-http.attlist &=
-	authentication-manager-ref?
-http.attlist &=
-	## Use this ObservationRegistry to collect metrics on various parts of the filter chain
-	attribute observation-registry-ref {xsd:token}?
-
-access-denied-handler =
-	## Defines the access-denied strategy that should be used. An access denied page can be defined or a reference to an AccessDeniedHandler instance.
-	element access-denied-handler {access-denied-handler.attlist, empty}
-access-denied-handler.attlist &= (ref | access-denied-handler-page)
-
-access-denied-handler-page =
-	## The access denied page that an authenticated user will be redirected to if they request a page which they don't have the authority to access.
-	attribute error-page {xsd:token}
-
-intercept-url =
-	## Specifies the access attributes and/or filter list for a particular set of URLs.
-	element intercept-url {intercept-url.attlist, empty}
-intercept-url.attlist &=
-	(pattern | request-matcher-ref)
-intercept-url.attlist &=
-	## The access configuration attributes that apply for the configured path.
-	attribute access {xsd:token}?
-intercept-url.attlist &=
-	## The HTTP Method for which the access configuration attributes should apply. If not specified, the attributes will apply to any method.
-	attribute method {"GET" | "DELETE" | "HEAD" | "OPTIONS" | "POST" | "PUT" | "PATCH" | "TRACE"}?
-
-intercept-url.attlist &=
-	## Used to specify that a URL must be accessed over http or https, or that there is no preference. The value should be "http", "https" or "any", respectively.
-	attribute requires-channel {xsd:token}?
-intercept-url.attlist &=
-	## The path to the servlet. This attribute is only applicable when 'request-matcher' is 'mvc'. In addition, the value is only required in the following 2 use cases: 1) There are 2 or more HttpServlet's registered in the ServletContext that have mappings starting with '/' and are different; 2) The pattern starts with the same value of a registered HttpServlet path, excluding the default (root) HttpServlet '/'.
-	attribute servlet-path {xsd:token}?
-
-logout =
-	## Incorporates a logout processing filter. Most web applications require a logout filter, although you may not require one if you write a controller to provider similar logic.
-	element logout {logout.attlist, empty}
-logout.attlist &=
-	## Specifies the URL that will cause a logout. Spring Security will initialize a filter that responds to this particular URL. Defaults to /logout if unspecified.
-	attribute logout-url {xsd:token}?
-logout.attlist &=
-	## Specifies the URL to display once the user has logged out. If not specified, defaults to <form-login-login-page>/?logout (i.e. /login?logout).
-	attribute logout-success-url {xsd:token}?
-logout.attlist &=
-	## Specifies whether a logout also causes HttpSession invalidation, which is generally desirable. If unspecified, defaults to true.
-	attribute invalidate-session {xsd:boolean}?
-logout.attlist &=
-	## A reference to a LogoutSuccessHandler implementation which will be used to determine the destination to which the user is taken after logging out.
-	attribute success-handler-ref {xsd:token}?
-logout.attlist &=
-	## A comma-separated list of the names of cookies which should be deleted when the user logs out
-	attribute delete-cookies {xsd:token}?
-
-request-cache =
-	## Allow the RequestCache used for saving requests during the login process to be set
-	element request-cache {ref}
-
-form-login =
-	## Sets up a form login configuration for authentication with a username and password
-	element form-login {form-login.attlist, empty}
-form-login.attlist &=
-	## The URL that the login form is posted to. If unspecified, it defaults to /login.
-	attribute login-processing-url {xsd:token}?
-form-login.attlist &=
-	## The name of the request parameter which contains the username. Defaults to 'username'.
-	attribute username-parameter {xsd:token}?
-form-login.attlist &=
-	## The name of the request parameter which contains the password. Defaults to 'password'.
-	attribute password-parameter {xsd:token}?
-form-login.attlist &=
-	## The URL that will be redirected to after successful authentication, if the user's previous action could not be resumed. This generally happens if the user visits a login page without having first requested a secured operation that triggers authentication. If unspecified, defaults to the root of the application.
-	attribute default-target-url {xsd:token}?
-form-login.attlist &=
-	## Whether the user should always be redirected to the default-target-url after login.
-	attribute always-use-default-target {xsd:boolean}?
-form-login.attlist &=
-	## The URL for the login page. If no login URL is specified, Spring Security will automatically create a login URL at GET /login and a corresponding filter to render that login URL when requested.
-	attribute login-page {xsd:token}?
-form-login.attlist &=
-	## The URL for the login failure page. If no login failure URL is specified, Spring Security will automatically create a failure login URL at /login?error and a corresponding filter to render that login failure URL when requested.
-	attribute authentication-failure-url {xsd:token}?
-form-login.attlist &=
-	## Reference to an AuthenticationSuccessHandler bean which should be used to handle a successful authentication request. Should not be used in combination with default-target-url (or always-use-default-target-url) as the implementation should always deal with navigation to the subsequent destination
-	attribute authentication-success-handler-ref {xsd:token}?
-form-login.attlist &=
-	## Reference to an AuthenticationFailureHandler bean which should be used to handle a failed authentication request. Should not be used in combination with authentication-failure-url as the implementation should always deal with navigation to the subsequent destination
-	attribute authentication-failure-handler-ref {xsd:token}?
-form-login.attlist &=
-	## Reference to an AuthenticationDetailsSource which will be used by the authentication filter
-	attribute authentication-details-source-ref {xsd:token}?
-form-login.attlist &=
-	## The URL for the ForwardAuthenticationFailureHandler
-	attribute authentication-failure-forward-url {xsd:token}?
-form-login.attlist &=
-	## The URL for the ForwardAuthenticationSuccessHandler
-	attribute authentication-success-forward-url {xsd:token}?
-
-oauth2-login =
-	## Configures authentication support using an OAuth 2.0 and/or OpenID Connect 1.0 Provider.
-	element oauth2-login {oauth2-login.attlist}
-oauth2-login.attlist &=
-	## Reference to the ClientRegistrationRepository
-	attribute client-registration-repository-ref {xsd:token}?
-oauth2-login.attlist &=
-	## Reference to the OAuth2AuthorizedClientRepository
-	attribute authorized-client-repository-ref {xsd:token}?
-oauth2-login.attlist &=
-	## Reference to the OAuth2AuthorizedClientService
-	attribute authorized-client-service-ref {xsd:token}?
-oauth2-login.attlist &=
-	## Reference to the AuthorizationRequestRepository
-	attribute authorization-request-repository-ref {xsd:token}?
-oauth2-login.attlist &=
-	## Reference to the OAuth2AuthorizationRequestResolver
-	attribute authorization-request-resolver-ref {xsd:token}?
-oauth2-login.attlist &=
-	## Reference to the authorization RedirectStrategy
-	attribute authorization-redirect-strategy-ref {xsd:token}?
-oauth2-login.attlist &=
-	## Reference to the OAuth2AccessTokenResponseClient
-	attribute access-token-response-client-ref {xsd:token}?
-oauth2-login.attlist &=
-	## Reference to the GrantedAuthoritiesMapper
-	attribute user-authorities-mapper-ref {xsd:token}?
-oauth2-login.attlist &=
-	## Reference to the OAuth2UserService
-	attribute user-service-ref {xsd:token}?
-oauth2-login.attlist &=
-	## Reference to the OpenID Connect OAuth2UserService
-	attribute oidc-user-service-ref {xsd:token}?
-oauth2-login.attlist &=
-	## The URI where the filter processes authentication requests
-	attribute login-processing-url {xsd:token}?
-oauth2-login.attlist &=
-	## The URI to send users to login
-	attribute login-page {xsd:token}?
-oauth2-login.attlist &=
-	## Reference to the AuthenticationSuccessHandler
-	attribute authentication-success-handler-ref {xsd:token}?
-oauth2-login.attlist &=
-	## Reference to the AuthenticationFailureHandler
-	attribute authentication-failure-handler-ref {xsd:token}?
-oauth2-login.attlist &=
-	## Reference to the JwtDecoderFactory used by OidcAuthorizationCodeAuthenticationProvider
-	attribute jwt-decoder-factory-ref {xsd:token}?
-
-oauth2-client =
-	## Configures OAuth 2.0 Client support.
-	element oauth2-client {oauth2-client.attlist, (authorization-code-grant?) }
-oauth2-client.attlist &=
-	## Reference to the ClientRegistrationRepository
-	attribute client-registration-repository-ref {xsd:token}?
-oauth2-client.attlist &=
-	## Reference to the OAuth2AuthorizedClientRepository
-	attribute authorized-client-repository-ref {xsd:token}?
-oauth2-client.attlist &=
-	## Reference to the OAuth2AuthorizedClientService
-	attribute authorized-client-service-ref {xsd:token}?
-
-authorization-code-grant =
-	## Configures OAuth 2.0 Authorization Code Grant.
-	element authorization-code-grant {authorization-code-grant.attlist, empty}
-authorization-code-grant.attlist &=
-	## Reference to the AuthorizationRequestRepository
-	attribute authorization-request-repository-ref {xsd:token}?
-authorization-code-grant.attlist &=
-    ## Reference to the authorization RedirectStrategy
-	attribute authorization-redirect-strategy-ref {xsd:token}?
-authorization-code-grant.attlist &=
-	## Reference to the OAuth2AuthorizationRequestResolver
-	attribute authorization-request-resolver-ref {xsd:token}?
-authorization-code-grant.attlist &=
-	## Reference to the OAuth2AccessTokenResponseClient
-	attribute access-token-response-client-ref {xsd:token}?
-
-client-registrations =
-	## Container element for client(s) registered with an OAuth 2.0 or OpenID Connect 1.0 Provider.
-	element client-registrations {client-registration+, provider*}
-
-client-registration =
-	## Represents a client registered with an OAuth 2.0 or OpenID Connect 1.0 Provider.
-	element client-registration {client-registration.attlist}
-client-registration.attlist &=
-	## The ID that uniquely identifies the client registration.
-	attribute registration-id {xsd:token}
-client-registration.attlist &=
-	## The client identifier.
-	attribute client-id {xsd:token}
-client-registration.attlist &=
-	## The client secret.
-	attribute client-secret {xsd:token}?
-client-registration.attlist &=
-	## The method used to authenticate the client with the provider. The supported values are client_secret_basic, client_secret_post and none (public clients).
-	attribute client-authentication-method {"client_secret_basic" | "basic" | "client_secret_post" | "post" | "none"}?
-client-registration.attlist &=
-	## The OAuth 2.0 Authorization Framework defines four Authorization Grant types. The supported values are authorization_code, client_credentials and password.
-	attribute authorization-grant-type {"authorization_code" | "client_credentials" | "password"}?
-client-registration.attlist &=
-	## The client’s registered redirect URI that the Authorization Server redirects the end-user’s user-agent to after the end-user has authenticated and authorized access to the client.
-	attribute redirect-uri {xsd:token}?
-client-registration.attlist &=
-	## A comma-separated list of scope(s) requested by the client during the Authorization Request flow, such as openid, email, or profile.
-	attribute scope {xsd:token}?
-client-registration.attlist &=
-	## A descriptive name used for the client. The name may be used in certain scenarios, such as when displaying the name of the client in the auto-generated login page.
-	attribute client-name {xsd:token}?
-client-registration.attlist &=
-	## A reference to the associated provider. May reference a 'provider' element or use one of the common providers (google, github, facebook, okta).
-	attribute provider-id {xsd:token}
-
-provider =
-	## The configuration information for an OAuth 2.0 or OpenID Connect 1.0 Provider.
-	element provider {provider.attlist}
-provider.attlist &=
-	## The ID that uniquely identifies the provider.
-	attribute provider-id {xsd:token}
-provider.attlist &=
-	## The Authorization Endpoint URI for the Authorization Server.
-	attribute authorization-uri {xsd:token}?
-provider.attlist &=
-	## The Token Endpoint URI for the Authorization Server.
-	attribute token-uri {xsd:token}?
-provider.attlist &=
-	## The UserInfo Endpoint URI used to access the claims/attributes of the authenticated end-user.
-	attribute user-info-uri {xsd:token}?
-provider.attlist &=
-	## The authentication method used when sending the access token to the UserInfo Endpoint. The supported values are header, form and query.
-	attribute user-info-authentication-method {"header" | "form" | "query"}?
-provider.attlist &=
-	## The name of the attribute returned in the UserInfo Response that references the Name or Identifier of the end-user.
-	attribute user-info-user-name-attribute {xsd:token}?
-provider.attlist &=
-	## The URI used to retrieve the JSON Web Key (JWK) Set from the Authorization Server, which contains the cryptographic key(s) used to verify the JSON Web Signature (JWS) of the ID Token and optionally the UserInfo Response.
-	attribute jwk-set-uri {xsd:token}?
-provider.attlist &=
-	## The URI used to discover the configuration information for an OAuth 2.0 or OpenID Connect 1.0 Provider.
-	attribute issuer-uri {xsd:token}?
-
-oauth2-resource-server =
-	## Configures authentication support as an OAuth 2.0 Resource Server.
-	element oauth2-resource-server {oauth2-resource-server.attlist, (jwt? & opaque-token?)}
-oauth2-resource-server.attlist &=
-	## Reference to an AuthenticationManagerResolver
-	attribute authentication-manager-resolver-ref {xsd:token}?
-oauth2-resource-server.attlist &=
-	## Reference to a BearerTokenResolver
-	attribute bearer-token-resolver-ref {xsd:token}?
-oauth2-resource-server.attlist &=
-	## Reference to a AuthenticationEntryPoint
-	attribute entry-point-ref {xsd:token}?
-
-jwt =
-    ## Configures JWT authentication
-    element jwt {jwt.attlist}
-jwt.attlist &=
-    ## The URI to use to collect the JWK Set for verifying JWTs
-    attribute jwk-set-uri {xsd:token}?
-jwt.attlist &=
-    ## Reference to a JwtDecoder
-    attribute decoder-ref {xsd:token}?
-jwt.attlist &=
-    ## Reference to a Converter<Jwt, AbstractAuthenticationToken>
-    attribute jwt-authentication-converter-ref {xsd:token}?
-
-opaque-token =
-    ## Configuration Opaque Token authentication
-    element opaque-token {opaque-token.attlist}
-opaque-token.attlist &=
-    ## The URI to use to introspect opaque token attributes
-    attribute introspection-uri {xsd:token}?
-opaque-token.attlist &=
-    ## The Client ID to use to authenticate the introspection request
-    attribute client-id {xsd:token}?
-opaque-token.attlist &=
-    ## The Client secret to use to authenticate the introspection request
-    attribute client-secret {xsd:token}?
-opaque-token.attlist &=
-    ## Reference to an OpaqueTokenIntrospector
-    attribute introspector-ref {xsd:token}?
-opaque-token.attlist &=
-    ## Reference to an OpaqueTokenAuthenticationConverter responsible for converting successful introspection result into an Authentication.
-    attribute authentication-converter-ref {xsd:token}?
-
-saml2-login =
-	## Configures authentication support for SAML 2.0 Login
-	element saml2-login {saml2-login.attlist}
-saml2-login.attlist &=
-	## Reference to the RelyingPartyRegistrationRepository
-	attribute relying-party-registration-repository-ref {xsd:token}?
-saml2-login.attlist &=
-	## Reference to the Saml2AuthenticationRequestRepository
-	attribute authentication-request-repository-ref {xsd:token}?
-saml2-login.attlist &=
-	## Reference to the Saml2AuthenticationRequestResolver
-	attribute authentication-request-resolver-ref {xsd:token}?
-saml2-login.attlist &=
-	## Reference to the AuthenticationConverter
-	attribute authentication-converter-ref {xsd:token}?
-saml2-login.attlist &=
-	## The URI where the filter processes authentication requests
-	attribute login-processing-url {xsd:token}?
-saml2-login.attlist &=
-	## The URI to send users to login
-	attribute login-page {xsd:token}?
-saml2-login.attlist &=
-	## Reference to the AuthenticationSuccessHandler
-	attribute authentication-success-handler-ref {xsd:token}?
-saml2-login.attlist &=
-	## Reference to the AuthenticationFailureHandler
-	attribute authentication-failure-handler-ref {xsd:token}?
-saml2-login.attlist &=
-	## Reference to the AuthenticationManager
-	attribute authentication-manager-ref {xsd:token}?
-
-saml2-logout =
-	## Configures SAML 2.0 Single Logout support
-	element saml2-logout {saml2-logout.attlist}
-saml2-logout.attlist &=
-	## The URL by which the relying or asserting party can trigger logout
-	attribute logout-url {xsd:token}?
-saml2-logout.attlist &=
-	## The URL by which the asserting party can send a SAML 2.0 Logout Request
-	attribute logout-request-url {xsd:token}?
-saml2-logout.attlist &=
-	## The URL by which the asserting party can send a SAML 2.0 Logout Response
-	attribute logout-response-url {xsd:token}?
-saml2-logout.attlist &=
-	## Reference to the RelyingPartyRegistrationRepository
-	attribute relying-party-registration-repository-ref {xsd:token}?
-saml2-logout.attlist &=
-	## Reference to the Saml2LogoutRequestValidator
-	attribute logout-request-validator-ref {xsd:token}?
-saml2-logout.attlist &=
-	## Reference to the Saml2LogoutRequestResolver
-	attribute logout-request-resolver-ref {xsd:token}?
-saml2-logout.attlist &=
-	## Reference to the Saml2LogoutRequestRepository
-	attribute logout-request-repository-ref {xsd:token}?
-saml2-logout.attlist &=
-	## Reference to the Saml2LogoutResponseValidator
-	attribute logout-response-validator-ref {xsd:token}?
-saml2-logout.attlist &=
-	## Reference to the Saml2LogoutResponseResolver
-	attribute logout-response-resolver-ref {xsd:token}?
-
-relying-party-registrations =
-	## Container element for relying party(ies) registered with a SAML 2.0 identity provider
-	element relying-party-registrations {relying-party-registrations.attlist, relying-party-registration+, asserting-party*}
-relying-party-registrations.attlist &=
-    ## The identifier by which to refer to the repository in other beans
-    attribute id {xsd:token}?
-
-relying-party-registration =
-	## Represents a relying party registered with a SAML 2.0 identity provider
-	element relying-party-registration {relying-party-registration.attlist, signing-credential*, decryption-credential*}
-relying-party-registration.attlist &=
-	## The ID that uniquely identifies the relying party registration.
-	attribute registration-id {xsd:token}
-relying-party-registration.attlist &=
-	## The location of the Identity Provider's metadata.
-	attribute metadata-location {xsd:token}?
-relying-party-registration.attlist &=
-	## The relying party's EntityID
-	attribute entity-id {xsd:token}?
-relying-party-registration.attlist &=
-	## The Assertion Consumer Service Location
-	attribute assertion-consumer-service-location {xsd:token}?
-relying-party-registration.attlist &=
-	## The Assertion Consumer Service Binding
-	attribute assertion-consumer-service-binding {xsd:token}?
-relying-party-registration.attlist &=
-	## A reference to the associated asserting party.
-	attribute asserting-party-id {xsd:token}?
-relying-party-registration.attlist &=
-	## The relying party <a href="https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7">SingleLogoutService Location</a>
-	attribute single-logout-service-location {xsd:token}?
-relying-party-registration.attlist &=
-	## The relying party <a href="https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7">SingleLogoutService Response Location</a>
-	attribute single-logout-service-response-location {xsd:token}?
-relying-party-registration.attlist &=
-	## The relying party <a href="https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7">SingleLogoutService Binding</a>
-	attribute single-logout-service-binding {xsd:token}?
-
-signing-credential =
-	## The relying party's signing credential
-	element signing-credential {signing-credential.attlist}
-signing-credential.attlist &=
-	## The private key location
-	attribute private-key-location {xsd:token}
-signing-credential.attlist &=
-	## The certificate location
-	attribute certificate-location {xsd:token}
-
-decryption-credential =
-	## The relying party's decryption credential
-	element decryption-credential {decryption-credential.attlist}
-decryption-credential.attlist &=
-	## The private key location
-	attribute private-key-location {xsd:token}
-decryption-credential.attlist &=
-	## The certificate location
-	attribute certificate-location {xsd:token}
-
-asserting-party =
-	## The configuration metadata of the Asserting party
-	element asserting-party {asserting-party.attlist, verification-credential*, encryption-credential*}
-asserting-party.attlist &=
-	## A unique identifier of the asserting party.
-	attribute asserting-party-id {xsd:token}
-asserting-party.attlist &=
-	## The asserting party's EntityID.
-	attribute entity-id {xsd:token}
-asserting-party.attlist &=
-	## Indicates the asserting party's preference that relying parties should sign the AuthnRequest before sending
-	attribute want-authn-requests-signed {xsd:token}?
-asserting-party.attlist &=
-	## The <a href="https://www.oasis-open.org/committees/download.php/51890/SAML%20MD%20simplified%20overview.pdf#2.5%20Endpoint">SingleSignOnService</a> Location.
-	attribute single-sign-on-service-location {xsd:token}
-asserting-party.attlist &=
-	## The <a href="https://www.oasis-open.org/committees/download.php/51890/SAML%20MD%20simplified%20overview.pdf#2.5%20Endpoint">SingleSignOnService</a> Binding.
-	attribute single-sign-on-service-binding {xsd:token}?
-asserting-party.attlist &=
-	## A comma separated list of org.opensaml.saml.ext.saml2alg.SigningMethod Algorithms for this asserting party, in preference order.
-	attribute signing-algorithms {xsd:token}?
-asserting-party.attlist &=
-	## The asserting party <a href="https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7">SingleLogoutService Location</a>
-	attribute single-logout-service-location {xsd:token}?
-asserting-party.attlist &=
-	## The asserting party <a href="https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7">SingleLogoutService Response Location</a>
-	attribute single-logout-service-response-location {xsd:token}?
-asserting-party.attlist &=
-	## The asserting party <a href="https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7">SingleLogoutService Binding</a>
-	attribute single-logout-service-binding {xsd:token}?
-
-verification-credential =
-	## The relying party's verification credential
-	element verification-credential {verification-credential.attlist}
-verification-credential.attlist &=
-	## The private key location
-	attribute private-key-location {xsd:token}
-verification-credential.attlist &=
-	## The certificate location
-	attribute certificate-location {xsd:token}
-
-encryption-credential =
-	## The asserting party's encryption credential
-	element encryption-credential {encryption-credential.attlist}
-encryption-credential.attlist &=
-	## The private key location
-	attribute private-key-location {xsd:token}
-encryption-credential.attlist &=
-	## The certificate location
-	attribute certificate-location {xsd:token}
-
-
-filter-chain-map =
-	## Used to explicitly configure a FilterChainProxy instance with a FilterChainMap
-	element filter-chain-map {filter-chain-map.attlist, filter-chain+}
-filter-chain-map.attlist &=
-	request-matcher?
-
-filter-chain =
-	## Used within to define a specific URL pattern and the list of filters which apply to the URLs matching that pattern. When multiple filter-chain elements are assembled in a list in order to configure a FilterChainProxy, the most specific patterns must be placed at the top of the list, with  most general ones at the bottom.
-	element filter-chain {filter-chain.attlist, empty}
-filter-chain.attlist &=
-	(pattern | request-matcher-ref)
-filter-chain.attlist &=
-	## A comma separated list of bean names that implement Filter that should be processed for this FilterChain. If the value is none, then no Filters will be used for this FilterChain.
-	attribute filters {xsd:token}
-
-pattern =
-	## The request URL pattern which will be mapped to the FilterChain.
-	attribute pattern {xsd:token}
-request-matcher-ref =
-	## Allows a RequestMatcher instance to be used, as an alternative to pattern-matching.
-	attribute request-matcher-ref {xsd:token}
-
-filter-security-metadata-source =
-	## Used to explicitly configure a FilterSecurityMetadataSource bean for use with a FilterSecurityInterceptor. Usually only needed if you are configuring a FilterChainProxy explicitly, rather than using the <http> element. The intercept-url elements used should only contain pattern, method and access attributes. Any others will result in a configuration error.
-	element filter-security-metadata-source {fsmds.attlist, intercept-url+}
-fsmds.attlist &=
-	use-expressions?
-fsmds.attlist &=
-	id?
-fsmds.attlist &=
-	request-matcher?
-
-http-basic =
-	## Adds support for basic authentication
-	element http-basic {http-basic.attlist, empty}
-
-http-basic.attlist &=
-	## Sets the AuthenticationEntryPoint which is used by the BasicAuthenticationFilter.
-	attribute entry-point-ref {xsd:token}?
-http-basic.attlist &=
-	## Reference to an AuthenticationDetailsSource which will be used by the authentication filter
-	attribute authentication-details-source-ref {xsd:token}?
-
-password-management =
-    ## Adds support for the password management.
-    element password-management {password-management.attlist, empty}
-
-password-management.attlist &=
-    ## The change password page. Defaults to "/change-password".
-    attribute change-password-page {xsd:string}?
-
-session-management =
-	## Session-management related functionality is implemented by the addition of a SessionManagementFilter to the filter stack.
-	element session-management {session-management.attlist, concurrency-control?}
-
-session-management.attlist &=
-	## Specifies that SessionAuthenticationStrategy must be explicitly invoked. Default false (i.e. SessionManagementFilter will implicitly invoke SessionAuthenticationStrategy).
-	attribute authentication-strategy-explicit-invocation {xsd:boolean}?
-session-management.attlist &=
-	## Indicates how session fixation protection will be applied when a user authenticates. If set to "none", no protection will be applied. "newSession" will create a new empty session, with only Spring Security-related attributes migrated. "migrateSession" will create a new session and copy all session attributes to the new session. In Servlet 3.1 (Java EE 7) and newer containers, specifying "changeSessionId" will keep the existing session and use the container-supplied session fixation protection (HttpServletRequest#changeSessionId()). Defaults to "changeSessionId" in Servlet 3.1 and newer containers, "migrateSession" in older containers. Throws an exception if "changeSessionId" is used in older containers.
-	attribute session-fixation-protection {"none" | "newSession" | "migrateSession" | "changeSessionId" }?
-session-management.attlist &=
-	## The URL to which a user will be redirected if they submit an invalid session indentifier. Typically used to detect session timeouts.
-	attribute invalid-session-url {xsd:token}?
-session-management.attlist &=
-	## Allows injection of the InvalidSessionStrategy instance used by the SessionManagementFilter
-	attribute invalid-session-strategy-ref {xsd:token}?
-session-management.attlist &=
-	## Allows injection of the SessionAuthenticationStrategy instance used by the SessionManagementFilter
-	attribute session-authentication-strategy-ref {xsd:token}?
-session-management.attlist &=
-	## Defines the URL of the error page which should be shown when the SessionAuthenticationStrategy raises an exception. If not set, an unauthorized (401) error code will be returned to the client. Note that this attribute doesn't apply if the error occurs during a form-based login, where the URL for authentication failure will take precedence.
-	attribute session-authentication-error-url {xsd:token}?
-
-
-concurrency-control =
-	## Enables concurrent session control, limiting the number of authenticated sessions a user may have at the same time.
-	element concurrency-control {concurrency-control.attlist, empty}
-
-concurrency-control.attlist &=
-	## The maximum number of sessions a single authenticated user can have open at the same time. Defaults to "1". A negative value denotes unlimited sessions.
-	attribute max-sessions {xsd:token}?
-concurrency-control.attlist &=
-	## The URL a user will be redirected to if they attempt to use a session which has been "expired" because they have logged in again.
-	attribute expired-url {xsd:token}?
-concurrency-control.attlist &=
-	## Allows injection of the SessionInformationExpiredStrategy instance used by the ConcurrentSessionFilter
-	attribute expired-session-strategy-ref {xsd:token}?
-concurrency-control.attlist &=
-	## Specifies that an unauthorized error should be reported when a user attempts to login when they already have the maximum configured sessions open. The default behaviour is to expire the original session. If the session-authentication-error-url attribute is set on the session-management URL, the user will be redirected to this URL.
-	attribute error-if-maximum-exceeded {xsd:boolean}?
-concurrency-control.attlist &=
-	## Allows you to define an alias for the SessionRegistry bean in order to access it in your own configuration.
-	attribute session-registry-alias {xsd:token}?
-concurrency-control.attlist &=
-	## Allows you to define an external SessionRegistry bean to be used by the concurrency control setup.
-	attribute session-registry-ref {xsd:token}?
-
-
-remember-me =
-	## Sets up remember-me authentication. If used with the "key" attribute (or no attributes) the cookie-only implementation will be used. Specifying "token-repository-ref" or "remember-me-data-source-ref" will use the more secure, persisten token approach.
-	element remember-me {remember-me.attlist}
-remember-me.attlist &=
-	## The "key" used to identify cookies from a specific token-based remember-me application. You should set this to a unique value for your application. If unset, it will default to a random value generated by SecureRandom.
-	attribute key {xsd:token}?
-
-remember-me.attlist &=
-	(token-repository-ref | remember-me-data-source-ref | remember-me-services-ref)
-
-remember-me.attlist &=
-	user-service-ref?
-
-remember-me.attlist &=
-	## Exports the internally defined RememberMeServices as a bean alias, allowing it to be used by other beans in the application context.
-	attribute services-alias {xsd:token}?
-
-remember-me.attlist &=
-	## Determines whether the "secure" flag will be set on the remember-me cookie. If set to true, the cookie will only be submitted over HTTPS (recommended). By default, secure cookies will be used if the request is made on a secure connection.
-	attribute use-secure-cookie {xsd:boolean}?
-
-remember-me.attlist &=
-	## The period (in seconds) for which the remember-me cookie should be valid.
-	attribute token-validity-seconds {xsd:string}?
-
-remember-me.attlist &=
-	## Reference to an AuthenticationSuccessHandler bean which should be used to handle a successful remember-me authentication.
-	attribute authentication-success-handler-ref {xsd:token}?
-remember-me.attlist &=
-	## The name of the request parameter which toggles remember-me authentication. Defaults to 'remember-me'.
-	attribute remember-me-parameter {xsd:token}?
-remember-me.attlist &=
-	## The name of cookie which store the token for remember-me authentication. Defaults to 'remember-me'.
-	attribute remember-me-cookie {xsd:token}?
-
-token-repository-ref =
-	## Reference to a PersistentTokenRepository bean for use with the persistent token remember-me implementation.
-	attribute token-repository-ref {xsd:token}
-remember-me-services-ref =
-	## Allows a custom implementation of RememberMeServices to be used. Note that this implementation should return RememberMeAuthenticationToken instances with the same "key" value as specified in the remember-me element. Alternatively it should register its own AuthenticationProvider. It should also implement the LogoutHandler interface, which will be invoked when a user logs out. Typically the remember-me cookie would be removed on logout.
-	attribute services-ref {xsd:token}?
-remember-me-data-source-ref =
-	## DataSource bean for the database that contains the token repository schema.
-	data-source-ref
-
-anonymous =
-	## Adds support for automatically granting all anonymous web requests a particular principal identity and a corresponding granted authority.
-	element anonymous {anonymous.attlist}
-anonymous.attlist &=
-	## The key shared between the provider and filter. This generally does not need to be set. If unset, it will default to a random value generated by SecureRandom.
-	attribute key {xsd:token}?
-anonymous.attlist &=
-	## The username that should be assigned to the anonymous request. This allows the principal to be identified, which may be important for logging and auditing. if unset, defaults to "anonymousUser".
-	attribute username {xsd:token}?
-anonymous.attlist &=
-	## The granted authority that should be assigned to the anonymous request. Commonly this is used to assign the anonymous request particular roles, which can subsequently be used in authorization decisions. If unset, defaults to "ROLE_ANONYMOUS".
-	attribute granted-authority {xsd:token}?
-anonymous.attlist &=
-	## With the default namespace setup, the anonymous "authentication" facility is automatically enabled. You can disable it using this property.
-	attribute enabled {xsd:boolean}?
-
-
-port-mappings =
-	## Defines the list of mappings between http and https ports for use in redirects
-	element port-mappings {port-mappings.attlist, port-mapping+}
-
-port-mappings.attlist &= empty
-
-port-mapping =
-	## Provides a method to map http ports to https ports when forcing a redirect.
-	element port-mapping {http-port, https-port}
-
-http-port =
-	## The http port to use.
-	attribute http {xsd:token}
-
-https-port =
-	## The https port to use.
-	attribute https {xsd:token}
-
-
-x509 =
-	## Adds support for X.509 client authentication.
-	element x509 {x509.attlist}
-x509.attlist &=
-	## The regular expression used to obtain the username from the certificate's subject. Defaults to matching on the common name using the pattern "CN=(.*?),".
-	attribute subject-principal-regex {xsd:token}?
-x509.attlist &=
-	## Explicitly specifies which user-service should be used to load user data for X.509 authenticated clients. If ommitted, the default user-service will be used.
-	user-service-ref?
-x509.attlist &=
-	## Reference to an AuthenticationDetailsSource which will be used by the authentication filter
-	attribute authentication-details-source-ref {xsd:token}?
-
-jee =
-	## Adds a J2eePreAuthenticatedProcessingFilter to the filter chain to provide integration with container authentication.
-	element jee {jee.attlist}
-jee.attlist &=
-	## A comma-separate list of roles to look for in the incoming HttpServletRequest.
-	attribute mappable-roles {xsd:token}
-jee.attlist &=
-	## Explicitly specifies which user-service should be used to load user data for container authenticated clients. If ommitted, the set of mappable-roles will be used to construct the authorities for the user.
-	user-service-ref?
-
-authentication-manager =
-	## Registers the AuthenticationManager instance and allows its list of AuthenticationProviders to be defined. Also allows you to define an alias to allow you to reference the AuthenticationManager in your own beans.
-	element authentication-manager {authman.attlist & authentication-provider* & ldap-authentication-provider*}
-authman.attlist &=
-	id?
-authman.attlist &=
-	## An alias you wish to use for the AuthenticationManager bean (not required it you are using a specific id)
-	attribute alias {xsd:token}?
-authman.attlist &=
-	## If set to true, the AuthenticationManger will attempt to clear any credentials data in the returned Authentication object, once the user has been authenticated.
-	attribute erase-credentials {xsd:boolean}?
-authman.attlist &=
-	## Use this ObservationRegistry to collect metrics on various parts of the filter chain
-	attribute observation-registry-ref {xsd:token}?
-
-authentication-provider =
-	## Indicates that the contained user-service should be used as an authentication source.
-	element authentication-provider {ap.attlist & any-user-service & password-encoder?}
-ap.attlist &=
-	## Specifies a reference to a separately configured AuthenticationProvider instance which should be registered within the AuthenticationManager.
-	ref?
-ap.attlist &=
-	## Specifies a reference to a separately configured UserDetailsService from which to obtain authentication data.
-	user-service-ref?
-
-user-service =
-	## Creates an in-memory UserDetailsService from a properties file or a list of "user" child elements. Usernames are converted to lower-case internally to allow for case-insensitive lookups, so this should not be used if case-sensitivity is required.
-	element user-service {id? & (properties-file | (user*))}
-properties-file =
-	## The location of a Properties file where each line is in the format of username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]
-	attribute properties {xsd:token}?
-
-user =
-	## Represents a user in the application.
-	element user {user.attlist, empty}
-user.attlist &=
-	## The username assigned to the user.
-	attribute name {xsd:token}
-user.attlist &=
-	## The password assigned to the user. This may be hashed if the corresponding authentication provider supports hashing (remember to set the "hash" attribute of the "user-service" element). This attribute be omitted in the case where the data will not be used for authentication, but only for accessing authorities. If omitted, the namespace will generate a random value, preventing its accidental use for authentication. Cannot be empty.
-	attribute password {xsd:string}?
-user.attlist &=
-	## One of more authorities granted to the user. Separate authorities with a comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR"
-	attribute authorities {xsd:token}
-user.attlist &=
-	## Can be set to "true" to mark an account as locked and unusable.
-	attribute locked {xsd:boolean}?
-user.attlist &=
-	## Can be set to "true" to mark an account as disabled and unusable.
-	attribute disabled {xsd:boolean}?
-
-jdbc-user-service =
-	## Causes creation of a JDBC-based UserDetailsService.
-	element jdbc-user-service {id? & jdbc-user-service.attlist}
-jdbc-user-service.attlist &=
-	## The bean ID of the DataSource which provides the required tables.
-	attribute data-source-ref {xsd:token}
-jdbc-user-service.attlist &=
-	cache-ref?
-jdbc-user-service.attlist &=
-	## An SQL statement to query a username, password, and enabled status given a username. Default is "select username,password,enabled from users where username = ?"
-	attribute users-by-username-query {xsd:token}?
-jdbc-user-service.attlist &=
-	## An SQL statement to query for a user's granted authorities given a username. The default is "select username, authority from authorities where username = ?"
-	attribute authorities-by-username-query {xsd:token}?
-jdbc-user-service.attlist &=
-	## An SQL statement to query user's group authorities given a username. The default is "select g.id, g.group_name, ga.authority from groups g, group_members gm, group_authorities ga where gm.username = ? and g.id = ga.group_id and g.id = gm.group_id"
-	attribute group-authorities-by-username-query {xsd:token}?
-jdbc-user-service.attlist &=
-	role-prefix?
-
-csrf =
-## Element for configuration of the CsrfFilter for protection against CSRF. It also updates the default RequestCache to only replay "GET" requests.
-	element csrf {csrf-options.attlist}
-csrf-options.attlist &=
-	## Specifies if csrf protection should be disabled. Default false (i.e. CSRF protection is enabled).
-	attribute disabled {xsd:boolean}?
-csrf-options.attlist &=
-	## The RequestMatcher instance to be used to determine if CSRF should be applied. Default is any HTTP method except "GET", "TRACE", "HEAD", "OPTIONS"
-	attribute request-matcher-ref { xsd:token }?
-csrf-options.attlist &=
-	## The CsrfTokenRepository to use. The default is HttpSessionCsrfTokenRepository wrapped by LazyCsrfTokenRepository.
-	attribute token-repository-ref { xsd:token }?
-csrf-options.attlist &=
-	## The CsrfTokenRequestHandler to use. The default is CsrfTokenRequestAttributeHandler.
-	attribute request-handler-ref { xsd:token }?
-
-headers =
-## Element for configuration of the HeaderWritersFilter. Enables easy setting for the X-Frame-Options, X-XSS-Protection and X-Content-Type-Options headers.
-element headers { headers-options.attlist, (cache-control? & xss-protection? & hsts? & frame-options? & content-type-options? & hpkp? & content-security-policy? & referrer-policy? & feature-policy? & permissions-policy? & cross-origin-opener-policy? & cross-origin-embedder-policy? & cross-origin-resource-policy? & header*)}
-headers-options.attlist &=
-	## Specifies if the default headers should be disabled. Default false.
-	attribute defaults-disabled {xsd:token}?
-headers-options.attlist &=
-	## Specifies if headers should be disabled. Default false.
-	attribute disabled {xsd:token}?
-hsts =
-	## Adds support for HTTP Strict Transport Security (HSTS)
-	element hsts {hsts-options.attlist}
-hsts-options.attlist &=
-	## Specifies if HTTP Strict Transport Security (HSTS) should be disabled. Default false.
-	attribute disabled {xsd:boolean}?
-hsts-options.attlist &=
-	## Specifies if subdomains should be included. Default true.
-	attribute include-subdomains {xsd:boolean}?
-hsts-options.attlist &=
-	## Specifies the maximum amount of time the host should be considered a Known HSTS Host. Default one year.
-	attribute max-age-seconds {xsd:integer}?
-hsts-options.attlist &=
-	## The RequestMatcher instance to be used to determine if the header should be set. Default is if HttpServletRequest.isSecure() is true.
-	attribute request-matcher-ref { xsd:token }?
-hsts-options.attlist &=
-	## Specifies if preload should be included. Default false.
-	attribute preload {xsd:boolean}?
-
-cors =
-## Element for configuration of CorsFilter. If no CorsFilter or CorsConfigurationSource is specified a HandlerMappingIntrospector is used as the CorsConfigurationSource
-element cors { cors-options.attlist }
-cors-options.attlist &=
-	ref?
-cors-options.attlist &=
-	## Specifies a bean id that is a CorsConfigurationSource used to construct the CorsFilter to use
-	attribute configuration-source-ref {xsd:token}?
-
-hpkp =
-	## Adds support for HTTP Public Key Pinning (HPKP).
-	element hpkp {hpkp.pins,hpkp.attlist}
-hpkp.pins =
-	## The list with pins
-	element pins {hpkp.pin+}
-hpkp.pin =
-	## A pin is specified using the base64-encoded SPKI fingerprint as value and the cryptographic hash algorithm as attribute
-	element pin {
-		## The cryptographic hash algorithm
-		attribute algorithm { xsd:string }?,
-		text
-	}
-hpkp.attlist &=
-	## Specifies if HTTP Public Key Pinning (HPKP) should be disabled. Default false.
-	attribute disabled {xsd:boolean}?
-hpkp.attlist &=
-	## Specifies if subdomains should be included. Default false.
-	attribute include-subdomains {xsd:boolean}?
-hpkp.attlist &=
-	## Sets the value for the max-age directive of the Public-Key-Pins header. Default 60 days.
-	attribute max-age-seconds {xsd:integer}?
-hpkp.attlist &=
-	## Specifies if the browser should only report pin validation failures. Default true.
-	attribute report-only {xsd:boolean}?
-hpkp.attlist &=
-	## Specifies the URI to which the browser should report pin validation failures.
-	attribute report-uri {xsd:string}?
-
-content-security-policy =
-	## Adds support for Content Security Policy (CSP)
-	element content-security-policy {csp-options.attlist}
-csp-options.attlist &=
-	## The security policy directive(s) for the Content-Security-Policy header or if report-only is set to true, then the Content-Security-Policy-Report-Only header is used.
-	attribute policy-directives {xsd:token}?
-csp-options.attlist &=
-	## Set to true, to enable the Content-Security-Policy-Report-Only header for reporting policy violations only. Defaults to false.
-	attribute report-only {xsd:boolean}?
-
-referrer-policy =
-	## Adds support for Referrer Policy
-	element referrer-policy {referrer-options.attlist}
-referrer-options.attlist &=
-	## The policies for the Referrer-Policy header.
-	attribute policy {"no-referrer","no-referrer-when-downgrade","same-origin","origin","strict-origin","origin-when-cross-origin","strict-origin-when-cross-origin","unsafe-url"}?
-
-feature-policy =
-	## Adds support for Feature Policy
-	element feature-policy {feature-options.attlist}
-feature-options.attlist &=
-	## The security policy directive(s) for the Feature-Policy header.
-	attribute policy-directives {xsd:token}?
-
-permissions-policy =
-	## Adds support for Permissions Policy
-	element permissions-policy {permissions-options.attlist}
-permissions-options.attlist &=
-	## The policies for the Permissions-Policy header.
-	attribute policy {xsd:token}?
-
-cache-control =
-	## Adds Cache-Control no-cache, no-store, must-revalidate, Pragma no-cache, and Expires 0 for every request
-	element cache-control {cache-control.attlist}
-cache-control.attlist &=
-	## Specifies if Cache Control should be disabled. Default false.
-	attribute disabled {xsd:boolean}?
-
-frame-options =
-	## Enable basic clickjacking support for newer browsers (IE8+), will set the X-Frame-Options header.
-	element frame-options {frame-options.attlist,empty}
-frame-options.attlist &=
-	## If disabled, the X-Frame-Options header will not be included. Default false.
-	attribute disabled {xsd:boolean}?
-frame-options.attlist &=
-	## Specify the policy to use for the X-Frame-Options-Header.
-	attribute policy {"DENY","SAMEORIGIN","ALLOW-FROM"}?
-frame-options.attlist &=
-	## Specify the strategy to use when ALLOW-FROM is chosen.
-	attribute strategy {"static","whitelist","regexp"}?
-frame-options.attlist &=
-	## Specify a reference to the custom AllowFromStrategy to use when ALLOW-FROM is chosen.
-	ref?
-frame-options.attlist &=
-	## Specify a value to use for the chosen strategy.
-	attribute value {xsd:string}?
-frame-options.attlist &=
-	## Specify the request parameter to use for the origin when using a 'whitelist' or 'regexp' based strategy. Default is 'from'.
-	## Deprecated ALLOW-FROM is an obsolete directive that no longer works in modern browsers. Instead use
-	## Content-Security-Policy with the
-	## <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors">frame-ancestors</a>
-	## directive.
-	attribute from-parameter {xsd:string}?
-
-
-xss-protection =
-	## Enable basic XSS browser protection, supported by newer browsers (IE8+), will set the X-XSS-Protection header.
-	element xss-protection {xss-protection.attlist,empty}
-xss-protection.attlist &=
-	## disable the X-XSS-Protection header. Default is 'false' meaning it is enabled.
-	attribute disabled {xsd:boolean}?
-xss-protection.attlist &=
-	## Specify the value for the X-Xss-Protection header. Defaults to "0".
-	attribute header-value {"0"|"1"|"1; mode=block"}?
-
-content-type-options =
-	## Add a X-Content-Type-Options header to the resopnse. Value is always 'nosniff'.
-	element content-type-options {content-type-options.attlist, empty}
-content-type-options.attlist &=
-	## If disabled, the X-Content-Type-Options header will not be included. Default false.
-	attribute disabled {xsd:boolean}?
-
-cross-origin-opener-policy =
-	## Adds support for Cross-Origin-Opener-Policy header
-	element cross-origin-opener-policy {cross-origin-opener-policy-options.attlist,empty}
-cross-origin-opener-policy-options.attlist &=
-	## The policies for the Cross-Origin-Opener-Policy header.
-	attribute policy {"unsafe-none","same-origin","same-origin-allow-popups"}?
-
-cross-origin-embedder-policy =
-	## Adds support for Cross-Origin-Embedder-Policy header
-	element cross-origin-embedder-policy {cross-origin-embedder-policy-options.attlist,empty}
-cross-origin-embedder-policy-options.attlist &=
-	## The policies for the Cross-Origin-Embedder-Policy header.
-	attribute policy {"unsafe-none","require-corp"}?
-
-cross-origin-resource-policy =
-	## Adds support for Cross-Origin-Resource-Policy header
-	element cross-origin-resource-policy {cross-origin-resource-policy-options.attlist,empty}
-cross-origin-resource-policy-options.attlist &=
-	## The policies for the Cross-Origin-Resource-Policy header.
-	attribute policy {"cross-origin","same-origin","same-site"}?
-
-header=
-	## Add additional headers to the response.
-	element header {header.attlist}
-header.attlist &=
-	## The name of the header to add.
-	attribute name {xsd:token}?
-header.attlist &=
-	## The value for the header.
-	attribute value {xsd:token}?
-header.attlist &=
-	## Reference to a custom HeaderWriter implementation.
-	ref?
-
-any-user-service = user-service | jdbc-user-service | ldap-user-service
-
-custom-filter =
-	## Used to indicate that a filter bean declaration should be incorporated into the security filter chain.
-	element custom-filter {custom-filter.attlist}
-
-custom-filter.attlist &=
-	ref
-
-custom-filter.attlist &=
-	(after | before | position)
-
-after =
-	## The filter immediately after which the custom-filter should be placed in the chain. This feature will only be needed by advanced users who wish to mix their own filters into the security filter chain and have some knowledge of the standard Spring Security filters. The filter names map to specific Spring Security implementation filters.
-	attribute after {named-security-filter}
-before =
-	## The filter immediately before which the custom-filter should be placed in the chain
-	attribute before {named-security-filter}
-position =
-	## The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter.
-	attribute position {named-security-filter}
-
-named-security-filter = "FIRST" | "DISABLE_ENCODE_URL_FILTER" | "FORCE_EAGER_SESSION_FILTER" | "CHANNEL_FILTER" | "SECURITY_CONTEXT_FILTER" | "CONCURRENT_SESSION_FILTER" | "WEB_ASYNC_MANAGER_FILTER" | "HEADERS_FILTER" | "CORS_FILTER" | "SAML2_LOGOUT_REQUEST_FILTER" | "SAML2_LOGOUT_RESPONSE_FILTER" | "CSRF_FILTER" | "SAML2_LOGOUT_FILTER" | "LOGOUT_FILTER" | "OAUTH2_AUTHORIZATION_REQUEST_FILTER" | "SAML2_AUTHENTICATION_REQUEST_FILTER" | "X509_FILTER" | "PRE_AUTH_FILTER" | "CAS_FILTER" | "OAUTH2_LOGIN_FILTER" | "SAML2_AUTHENTICATION_FILTER" | "FORM_LOGIN_FILTER" | "LOGIN_PAGE_FILTER" |"LOGOUT_PAGE_FILTER" | "DIGEST_AUTH_FILTER" | "BEARER_TOKEN_AUTH_FILTER" | "BASIC_AUTH_FILTER" | "REQUEST_CACHE_FILTER" | "SERVLET_API_SUPPORT_FILTER" | "JAAS_API_SUPPORT_FILTER" | "REMEMBER_ME_FILTER" | "ANONYMOUS_FILTER" | "OAUTH2_AUTHORIZATION_CODE_GRANT_FILTER" | "WELL_KNOWN_CHANGE_PASSWORD_REDIRECT_FILTER" | "SESSION_MANAGEMENT_FILTER" | "EXCEPTION_TRANSLATION_FILTER" | "FILTER_SECURITY_INTERCEPTOR" | "SWITCH_USER_FILTER" | "LAST"

+ 0 - 3821
config/src/main/resources/org/springframework/security/config/spring-security-6.3.xsd

@@ -1,3821 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
-           xmlns:security="http://www.springframework.org/schema/security"
-           elementFormDefault="qualified"
-           targetNamespace="http://www.springframework.org/schema/security">
-  <xs:attributeGroup name="hash">
-      <xs:attribute name="hash" use="required">
-         <xs:annotation>
-            <xs:documentation>Defines the hashing algorithm used on user passwords. Bcrypt is recommended.
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="bcrypt"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="base64">
-      <xs:attribute name="base64" use="required" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Whether a string should be base64 encoded
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="request-matcher">
-      <xs:attribute name="request-matcher" use="required">
-         <xs:annotation>
-            <xs:documentation>Defines the strategy use for matching incoming requests. Currently the options are 'mvc'
-                (for Spring MVC matcher), 'ant' (for ant path patterns), 'regex' for regular expressions
-                and 'ciRegex' for case-insensitive regular expressions.
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="mvc"/>
-               <xs:enumeration value="ant"/>
-               <xs:enumeration value="regex"/>
-               <xs:enumeration value="ciRegex"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="port">
-      <xs:attribute name="port" use="required" type="xs:nonNegativeInteger">
-         <xs:annotation>
-            <xs:documentation>Specifies an IP port number. Used to configure an embedded LDAP server, for example.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="url">
-      <xs:attribute name="url" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Specifies a URL.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="id">
-      <xs:attribute name="id" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="name">
-      <xs:attribute name="name" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="ref">
-      <xs:attribute name="ref" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Defines a reference to a Spring bean Id.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="cache-ref">
-      <xs:attribute name="cache-ref" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Defines a reference to a cache for use with a UserDetailsService.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="user-service-ref">
-      <xs:attribute name="user-service-ref" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="authentication-manager-ref">
-      <xs:attribute name="authentication-manager-ref" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A reference to an AuthenticationManager bean
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="data-source-ref">
-      <xs:attribute name="data-source-ref" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A reference to a DataSource bean
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="debug">
-      <xs:annotation>
-         <xs:documentation>Enables Spring Security debugging infrastructure. This will provide human-readable
-                (multi-line) debugging information to monitor requests coming into the security filters.
-                This may include sensitive information, such as request parameters or headers, and should
-                only be used in a development environment.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType/>
-   </xs:element>
-  
-  <xs:attributeGroup name="password-encoder.attlist">
-      <xs:attribute name="ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Defines a reference to a Spring bean Id.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="hash">
-         <xs:annotation>
-            <xs:documentation>Defines the hashing algorithm used on user passwords. Bcrypt is recommended.
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="bcrypt"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="role-prefix">
-      <xs:attribute name="role-prefix" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A non-empty string prefix that will be added to role strings loaded from persistent
-                storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is
-                non-empty.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="use-expressions">
-      <xs:attribute name="use-expressions" use="required" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Enables the use of expressions in the 'access' attributes in &lt;intercept-url&gt; elements
-                rather than the traditional list of configuration attributes. Defaults to 'true'. If
-                enabled, each attribute should contain a single boolean expression. If the expression
-                evaluates to 'true', access will be granted.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="ldap-server">
-      <xs:annotation>
-         <xs:documentation>Defines an LDAP server location or starts an embedded server. The url indicates the
-                location of a remote server. If no url is given, an embedded server will be started,
-                listening on the supplied port number. The port is optional and defaults to 33389. A
-                Spring LDAP ContextSource bean will be registered for the server with the id supplied.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:ldap-server.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="ldap-server.attlist">
-      <xs:attribute name="id" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="url" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Specifies a URL.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="port" type="xs:nonNegativeInteger">
-         <xs:annotation>
-            <xs:documentation>Specifies an IP port number. Used to configure an embedded LDAP server, for example.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="manager-dn" type="xs:string">
-         <xs:annotation>
-            <xs:documentation>Username (DN) of the "manager" user identity which will be used to authenticate to a
-                (non-embedded) LDAP server. If omitted, anonymous access will be used.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="manager-password" type="xs:string">
-         <xs:annotation>
-            <xs:documentation>The password for the manager DN. This is required if the manager-dn is specified.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="ldif" type="xs:string">
-         <xs:annotation>
-            <xs:documentation>Explicitly specifies an ldif file resource to load into an embedded LDAP server. The
-                default is classpath*:*.ldiff
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="root" type="xs:string">
-         <xs:annotation>
-            <xs:documentation>Optional root suffix for the embedded LDAP server. Default is "dc=springframework,dc=org"
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="mode">
-         <xs:annotation>
-            <xs:documentation>Explicitly specifies which embedded ldap server should use. Values are 'apacheds' and
-                'unboundid'. By default, it will depends if the library is available in the classpath.
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="apacheds"/>
-               <xs:enumeration value="unboundid"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="ldap-server-ref-attribute">
-      <xs:attribute name="server-ref" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The optional server to use. If omitted, and a default LDAP server is registered (using
-                &lt;ldap-server&gt; with no Id), that server will be used.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="group-search-filter-attribute">
-      <xs:attribute name="group-search-filter" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN
-                of the user.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="group-search-base-attribute">
-      <xs:attribute name="group-search-base" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Search base for group membership searches. Defaults to "" (searching from the root).
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="user-search-filter-attribute">
-      <xs:attribute name="user-search-filter" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The LDAP filter used to search for users (optional). For example "(uid={0})". The
-                substituted parameter is the user's login name.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="user-search-base-attribute">
-      <xs:attribute name="user-search-base" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Search base for user searches. Defaults to "". Only used with a 'user-search-filter'.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="group-role-attribute-attribute">
-      <xs:attribute name="group-role-attribute" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The LDAP attribute name which contains the role name which will be used within Spring
-                Security. Defaults to "cn".
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="user-details-class-attribute">
-      <xs:attribute name="user-details-class" use="required">
-         <xs:annotation>
-            <xs:documentation>Allows the objectClass of the user entry to be specified. If set, the framework will
-                attempt to load standard attributes for the defined class into the returned UserDetails
-                object
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="person"/>
-               <xs:enumeration value="inetOrgPerson"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="user-context-mapper-attribute">
-      <xs:attribute name="user-context-mapper-ref" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Allows explicit customization of the loaded user object by specifying a
-                UserDetailsContextMapper bean which will be called with the context information from the
-                user's directory entry
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="ldap-user-service" substitutionGroup="security:any-user-service">
-      <xs:annotation>
-         <xs:documentation>This element configures a LdapUserDetailsService which is a combination of a
-                FilterBasedLdapUserSearch and a DefaultLdapAuthoritiesPopulator.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:ldap-us.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="ldap-us.attlist">
-      <xs:attribute name="id" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="server-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The optional server to use. If omitted, and a default LDAP server is registered (using
-                &lt;ldap-server&gt; with no Id), that server will be used.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="user-search-filter" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The LDAP filter used to search for users (optional). For example "(uid={0})". The
-                substituted parameter is the user's login name.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="user-search-base" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Search base for user searches. Defaults to "". Only used with a 'user-search-filter'.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="group-search-filter" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN
-                of the user.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="group-search-base" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Search base for group membership searches. Defaults to "" (searching from the root).
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="group-role-attribute" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The LDAP attribute name which contains the role name which will be used within Spring
-                Security. Defaults to "cn".
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="cache-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Defines a reference to a cache for use with a UserDetailsService.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="role-prefix" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A non-empty string prefix that will be added to role strings loaded from persistent
-                storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is
-                non-empty.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="user-details-class">
-         <xs:annotation>
-            <xs:documentation>Allows the objectClass of the user entry to be specified. If set, the framework will
-                attempt to load standard attributes for the defined class into the returned UserDetails
-                object
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="person"/>
-               <xs:enumeration value="inetOrgPerson"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-      <xs:attribute name="user-context-mapper-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Allows explicit customization of the loaded user object by specifying a
-                UserDetailsContextMapper bean which will be called with the context information from the
-                user's directory entry
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  
-  <xs:attributeGroup name="ldap-ap.attlist">
-      <xs:attribute name="server-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The optional server to use. If omitted, and a default LDAP server is registered (using
-                &lt;ldap-server&gt; with no Id), that server will be used.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="user-search-base" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Search base for user searches. Defaults to "". Only used with a 'user-search-filter'.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="user-search-filter" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The LDAP filter used to search for users (optional). For example "(uid={0})". The
-                substituted parameter is the user's login name.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="group-search-base" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Search base for group membership searches. Defaults to "" (searching from the root).
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="group-search-filter" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN
-                of the user.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="group-role-attribute" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The LDAP attribute name which contains the role name which will be used within Spring
-                Security. Defaults to "cn".
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="user-dn-pattern" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A specific pattern used to build the user's DN, for example "uid={0},ou=people". The key
-                "{0}" must be present and will be substituted with the username.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="role-prefix" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A non-empty string prefix that will be added to role strings loaded from persistent
-                storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is
-                non-empty.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="user-details-class">
-         <xs:annotation>
-            <xs:documentation>Allows the objectClass of the user entry to be specified. If set, the framework will
-                attempt to load standard attributes for the defined class into the returned UserDetails
-                object
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="person"/>
-               <xs:enumeration value="inetOrgPerson"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-      <xs:attribute name="user-context-mapper-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Allows explicit customization of the loaded user object by specifying a
-                UserDetailsContextMapper bean which will be called with the context information from the
-                user's directory entry
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  
-  <xs:attributeGroup name="password-compare.attlist">
-      <xs:attribute name="password-attribute" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The attribute in the directory which contains the user password. Defaults to
-                "userPassword".
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="hash">
-         <xs:annotation>
-            <xs:documentation>Defines the hashing algorithm used on user passwords. Bcrypt is recommended.
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="bcrypt"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="intercept-methods">
-      <xs:annotation>
-         <xs:documentation>Can be used inside a bean definition to add a security interceptor to the bean and set up
-                access configuration attributes for the bean's methods
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:sequence>
-            <xs:element maxOccurs="unbounded" name="protect">
-               <xs:annotation>
-                  <xs:documentation>Defines a protected method and the access control configuration attributes that apply to
-                it. We strongly advise you NOT to mix "protect" declarations with any services provided
-                "global-method-security".
-                </xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
-                  <xs:attributeGroup ref="security:protect.attlist"/>
-               </xs:complexType>
-            </xs:element>
-         </xs:sequence>
-         <xs:attributeGroup ref="security:intercept-methods.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="intercept-methods.attlist">
-      <xs:attribute name="access-decision-manager-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Optional AccessDecisionManager bean ID to be used by the created method security
-                interceptor.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="use-authorization-manager" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Use the AuthorizationManager API instead of AccessDecisionManager (defaults to true)
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authorization-manager-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Use this AuthorizationManager instead of the default (supercedes
-                use-authorization-manager)
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  
-  <xs:attributeGroup name="protect.attlist">
-      <xs:attribute name="method" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A method name
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="access" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Access configuration attributes list that applies to the method, e.g. "ROLE_A,ROLE_B".
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="method-security-metadata-source">
-      <xs:annotation>
-         <xs:documentation>Creates a MethodSecurityMetadataSource instance
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:sequence>
-            <xs:element maxOccurs="unbounded" name="protect">
-               <xs:annotation>
-                  <xs:documentation>Defines a protected method and the access control configuration attributes that apply to
-                it. We strongly advise you NOT to mix "protect" declarations with any services provided
-                "global-method-security".
-                </xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
-                  <xs:attributeGroup ref="security:protect.attlist"/>
-               </xs:complexType>
-            </xs:element>
-         </xs:sequence>
-         <xs:attributeGroup ref="security:msmds.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="msmds.attlist">
-      <xs:attribute name="id" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="use-expressions" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Enables the use of expressions in the 'access' attributes in &lt;intercept-url&gt; elements
-                rather than the traditional list of configuration attributes. Defaults to 'true'. If
-                enabled, each attribute should contain a single boolean expression. If the expression
-                evaluates to 'true', access will be granted.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="method-security">
-      <xs:annotation>
-         <xs:documentation>Provides method security for all beans registered in the Spring application context.
-                Specifically, beans will be scanned for matches with Spring Security annotations. Where
-                there is a match, the beans will automatically be proxied and security authorization
-                applied to the methods accordingly. Interceptors are invoked in the order specified in
-                AuthorizationInterceptorsOrder. Use can create your own interceptors using Spring AOP.
-                Also, annotation-based interception can be overridden by expressions listed in
-                &lt;protect-pointcut&gt; elements.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:sequence>
-            <xs:element minOccurs="0" name="expression-handler">
-               <xs:annotation>
-                  <xs:documentation>Defines the SecurityExpressionHandler instance which will be used if expression-based
-                access-control is enabled. A default implementation (with no ACL support) will be used if
-                not supplied.
-                </xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
-                  <xs:attributeGroup ref="security:ref"/>
-               </xs:complexType>
-            </xs:element>
-            <xs:element minOccurs="0" maxOccurs="unbounded" name="protect-pointcut">
-               <xs:annotation>
-                  <xs:documentation>Defines a protected pointcut and the access control configuration attributes that apply to
-                it. Every bean registered in the Spring application context that provides a method that
-                matches the pointcut will receive security authorization.
-                </xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
-                  <xs:attributeGroup ref="security:protect-pointcut.attlist"/>
-               </xs:complexType>
-            </xs:element>
-         </xs:sequence>
-         <xs:attributeGroup ref="security:method-security.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="method-security.attlist">
-      <xs:attribute name="pre-post-enabled" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Specifies whether the use of Spring Security's pre and post invocation annotations
-                (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) should be enabled for this
-                application context. Defaults to "true".
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="secured-enabled" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Specifies whether the use of Spring Security's @Secured annotations should be enabled for
-                this application context. Defaults to "false".
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="jsr250-enabled" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Specifies whether JSR-250 style attributes are to be used (for example "RolesAllowed").
-                This will require the javax.annotation.security classes on the classpath. Defaults to
-                "false".
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="proxy-target-class" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>If true, class-based proxying will be used instead of interface-based proxying.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="mode">
-         <xs:annotation>
-            <xs:documentation>If set to aspectj, then use AspectJ to intercept method invocation
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="aspectj"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-      <xs:attribute name="security-context-holder-strategy-ref" type="xs:string">
-         <xs:annotation>
-            <xs:documentation>Specifies the security context holder strategy to use, by default uses a ThreadLocal-based
-                strategy
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="observation-registry-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Use this ObservationRegistry to collect metrics on various parts of the filter chain
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="global-method-security">
-      <xs:annotation>
-         <xs:documentation>Provides method security for all beans registered in the Spring application context.
-                Specifically, beans will be scanned for matches with the ordered list of
-                "protect-pointcut" sub-elements, Spring Security annotations and/or. Where there is a
-                match, the beans will automatically be proxied and security authorization applied to the
-                methods accordingly. If you use and enable all four sources of method security metadata
-                (ie "protect-pointcut" declarations, expression annotations, @Secured and also JSR250
-                security annotations), the metadata sources will be queried in that order. In practical
-                terms, this enables you to use XML to override method security metadata expressed in
-                annotations. If using annotations, the order of precedence is EL-based (@PreAuthorize
-                etc.), @Secured and finally JSR-250.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:sequence>
-            <xs:choice minOccurs="0">
-               <xs:element name="pre-post-annotation-handling">
-                  <xs:annotation>
-                     <xs:documentation>Allows the default expression-based mechanism for handling Spring Security's pre and post
-                invocation annotations (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) to be
-                replace entirely. Only applies if these annotations are enabled.
-                </xs:documentation>
-                  </xs:annotation>
-                  <xs:complexType>
-                     <xs:sequence>
-                        <xs:element name="invocation-attribute-factory">
-                           <xs:annotation>
-                              <xs:documentation>Defines the PrePostInvocationAttributeFactory instance which is used to generate pre and
-                post invocation metadata from the annotated methods.
-                </xs:documentation>
-                           </xs:annotation>
-                           <xs:complexType>
-                              <xs:attributeGroup ref="security:ref"/>
-                           </xs:complexType>
-                        </xs:element>
-                        <xs:element name="pre-invocation-advice">
-                           <xs:annotation>
-                              <xs:documentation>Customizes the PreInvocationAuthorizationAdviceVoter with the ref as the
-                PreInvocationAuthorizationAdviceVoter for the &lt;pre-post-annotation-handling&gt; element.
-                </xs:documentation>
-                           </xs:annotation>
-                           <xs:complexType>
-                              <xs:attributeGroup ref="security:ref"/>
-                           </xs:complexType>
-                        </xs:element>
-                        <xs:element name="post-invocation-advice">
-                           <xs:annotation>
-                              <xs:documentation>Customizes the PostInvocationAdviceProvider with the ref as the
-                PostInvocationAuthorizationAdvice for the &lt;pre-post-annotation-handling&gt; element.
-                </xs:documentation>
-                           </xs:annotation>
-                           <xs:complexType>
-                              <xs:attributeGroup ref="security:ref"/>
-                           </xs:complexType>
-                        </xs:element>
-                     </xs:sequence>
-                  </xs:complexType>
-               </xs:element>
-               <xs:element name="expression-handler">
-                  <xs:annotation>
-                     <xs:documentation>Defines the SecurityExpressionHandler instance which will be used if expression-based
-                access-control is enabled. A default implementation (with no ACL support) will be used if
-                not supplied.
-                </xs:documentation>
-                  </xs:annotation>
-                  <xs:complexType>
-                     <xs:attributeGroup ref="security:ref"/>
-                  </xs:complexType>
-               </xs:element>
-            </xs:choice>
-            <xs:element minOccurs="0" maxOccurs="unbounded" name="protect-pointcut">
-               <xs:annotation>
-                  <xs:documentation>Defines a protected pointcut and the access control configuration attributes that apply to
-                it. Every bean registered in the Spring application context that provides a method that
-                matches the pointcut will receive security authorization.
-                </xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
-                  <xs:attributeGroup ref="security:protect-pointcut.attlist"/>
-               </xs:complexType>
-            </xs:element>
-            <xs:element minOccurs="0" maxOccurs="unbounded" name="after-invocation-provider">
-               <xs:annotation>
-                  <xs:documentation>Allows addition of extra AfterInvocationProvider beans which should be called by the
-                MethodSecurityInterceptor created by global-method-security.
-                </xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
-                  <xs:attributeGroup ref="security:ref"/>
-               </xs:complexType>
-            </xs:element>
-         </xs:sequence>
-         <xs:attributeGroup ref="security:global-method-security.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="global-method-security.attlist">
-      <xs:attribute name="pre-post-annotations">
-         <xs:annotation>
-            <xs:documentation>Specifies whether the use of Spring Security's pre and post invocation annotations
-                (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) should be enabled for this
-                application context. Defaults to "disabled".
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="disabled"/>
-               <xs:enumeration value="enabled"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-      <xs:attribute name="secured-annotations">
-         <xs:annotation>
-            <xs:documentation>Specifies whether the use of Spring Security's @Secured annotations should be enabled for
-                this application context. Defaults to "disabled".
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="disabled"/>
-               <xs:enumeration value="enabled"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-      <xs:attribute name="jsr250-annotations">
-         <xs:annotation>
-            <xs:documentation>Specifies whether JSR-250 style attributes are to be used (for example "RolesAllowed").
-                This will require the javax.annotation.security classes on the classpath. Defaults to
-                "disabled".
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="disabled"/>
-               <xs:enumeration value="enabled"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-      <xs:attribute name="access-decision-manager-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Optional AccessDecisionManager bean ID to override the default used for method security.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="run-as-manager-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Optional RunAsmanager implementation which will be used by the configured
-                MethodSecurityInterceptor
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="order" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Allows the advice "order" to be set for the method security interceptor.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="proxy-target-class" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>If true, class based proxying will be used instead of interface based proxying.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="mode">
-         <xs:annotation>
-            <xs:documentation>Can be used to specify that AspectJ should be used instead of the default Spring AOP. If
-                set, secured classes must be woven with the AnnotationSecurityAspect from the
-                spring-security-aspects module.
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="aspectj"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-      <xs:attribute name="metadata-source-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>An external MethodSecurityMetadataSource instance can be supplied which will take priority
-                over other sources (such as the default annotations).
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authentication-manager-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A reference to an AuthenticationManager bean
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  
-  
-  
-  
-  
-  
-  
-  <xs:attributeGroup name="protect-pointcut.attlist">
-      <xs:attribute name="expression" use="required" type="xs:string">
-         <xs:annotation>
-            <xs:documentation>An AspectJ expression, including the 'execution' keyword. For example, 'execution(int
-                com.foo.TargetObject.countLength(String))' (without the quotes).
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="access" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Access configuration attributes list that applies to all methods matching the pointcut,
-                e.g. "ROLE_A,ROLE_B"
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="websocket-message-broker">
-      <xs:annotation>
-         <xs:documentation>Allows securing a Message Broker. There are two modes. If no id is specified: ensures that
-                any SimpAnnotationMethodMessageHandler has the AuthenticationPrincipalArgumentResolver
-                registered as a custom argument resolver; ensures that the
-                SecurityContextChannelInterceptor is automatically registered for the
-                clientInboundChannel; and that a ChannelSecurityInterceptor is registered with the
-                clientInboundChannel. If the id is specified, creates a ChannelSecurityInterceptor that
-                can be manually registered with the clientInboundChannel.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:choice minOccurs="0" maxOccurs="unbounded">
-            <xs:element ref="security:intercept-message"/>
-            <xs:element name="expression-handler">
-               <xs:annotation>
-                  <xs:documentation>Defines the SecurityExpressionHandler instance which will be used if expression-based
-                access-control is enabled. A default implementation (with no ACL support) will be used if
-                not supplied.
-                </xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
-                  <xs:attributeGroup ref="security:ref"/>
-               </xs:complexType>
-            </xs:element>
-         </xs:choice>
-         <xs:attributeGroup ref="security:websocket-message-broker.attrlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="websocket-message-broker.attrlist">
-      <xs:attribute name="id" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context. If specified,
-                explicit configuration within clientInboundChannel is required. If not specified, ensures
-                that any SimpAnnotationMethodMessageHandler has the
-                AuthenticationPrincipalArgumentResolver registered as a custom argument resolver; ensures
-                that the SecurityContextChannelInterceptor is automatically registered for the
-                clientInboundChannel; and that a ChannelSecurityInterceptor is registered with the
-                clientInboundChannel.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="same-origin-disabled" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Disables the requirement for CSRF token to be present in the Stomp headers (default
-                false). Changing the default is useful if it is necessary to allow other origins to make
-                SockJS connections.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authorization-manager-ref" type="xs:string">
-         <xs:annotation>
-            <xs:documentation>Use this AuthorizationManager instead of deriving one from &lt;intercept-message&gt; elements
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="use-authorization-manager" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Use AuthorizationManager API instead of SecurityMetadatasource (defaults to true)
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="security-context-holder-strategy-ref" type="xs:string">
-         <xs:annotation>
-            <xs:documentation>Use this SecurityContextHolderStrategy (note only supported in conjunction with the
-                AuthorizationManager API)
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="intercept-message">
-      <xs:annotation>
-         <xs:documentation>Creates an authorization rule for a websocket message.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:intercept-message.attrlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="intercept-message.attrlist">
-      <xs:attribute name="pattern" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The destination ant pattern which will be mapped to the access attribute. For example, /**
-                matches any message with a destination, /admin/** matches any message that has a
-                destination that starts with admin.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="access" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The access configuration attributes that apply for the configured message. For example,
-                permitAll grants access to anyone, hasRole('ROLE_ADMIN') requires the user have the role
-                'ROLE_ADMIN'.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="type">
-         <xs:annotation>
-            <xs:documentation>The type of message to match on. Valid values are defined in SimpMessageType (i.e.
-                CONNECT, CONNECT_ACK, HEARTBEAT, MESSAGE, SUBSCRIBE, UNSUBSCRIBE, DISCONNECT,
-                DISCONNECT_ACK, OTHER).
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="CONNECT"/>
-               <xs:enumeration value="CONNECT_ACK"/>
-               <xs:enumeration value="HEARTBEAT"/>
-               <xs:enumeration value="MESSAGE"/>
-               <xs:enumeration value="SUBSCRIBE"/>
-               <xs:enumeration value="UNSUBSCRIBE"/>
-               <xs:enumeration value="DISCONNECT"/>
-               <xs:enumeration value="DISCONNECT_ACK"/>
-               <xs:enumeration value="OTHER"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="http-firewall">
-      <xs:annotation>
-         <xs:documentation>Allows a custom instance of HttpFirewall to be injected into the FilterChainProxy created
-                by the namespace.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:ref"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:element name="http">
-      <xs:annotation>
-         <xs:documentation>Container element for HTTP security configuration. Multiple elements can now be defined,
-                each with a specific pattern to which the enclosed security configuration applies. A
-                pattern can also be configured to bypass Spring Security's filters completely by setting
-                the "security" attribute to "none".
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:choice minOccurs="0" maxOccurs="unbounded">
-            <xs:element name="intercept-url">
-               <xs:annotation>
-                  <xs:documentation>Specifies the access attributes and/or filter list for a particular set of URLs.
-                </xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
-                  <xs:attributeGroup ref="security:intercept-url.attlist"/>
-               </xs:complexType>
-            </xs:element>
-            <xs:element name="access-denied-handler">
-               <xs:annotation>
-                  <xs:documentation>Defines the access-denied strategy that should be used. An access denied page can be
-                defined or a reference to an AccessDeniedHandler instance.
-                </xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
-                  <xs:attributeGroup ref="security:access-denied-handler.attlist"/>
-               </xs:complexType>
-            </xs:element>
-            <xs:element name="form-login">
-               <xs:annotation>
-                  <xs:documentation>Sets up a form login configuration for authentication with a username and password
-                </xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
-                  <xs:attributeGroup ref="security:form-login.attlist"/>
-               </xs:complexType>
-            </xs:element>
-            <xs:element ref="security:oauth2-login"/>
-            <xs:element ref="security:oauth2-client"/>
-            <xs:element ref="security:oauth2-resource-server"/>
-            <xs:element name="saml2-login">
-               <xs:annotation>
-                  <xs:documentation>Configures authentication support for SAML 2.0 Login
-                </xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
-                  <xs:attributeGroup ref="security:saml2-login.attlist"/>
-               </xs:complexType>
-            </xs:element>
-            <xs:element name="saml2-logout">
-               <xs:annotation>
-                  <xs:documentation>Configures SAML 2.0 Single Logout support
-                </xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
-                  <xs:attributeGroup ref="security:saml2-logout.attlist"/>
-               </xs:complexType>
-            </xs:element>
-            <xs:element name="x509">
-               <xs:annotation>
-                  <xs:documentation>Adds support for X.509 client authentication.
-                </xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
-                  <xs:attributeGroup ref="security:x509.attlist"/>
-               </xs:complexType>
-            </xs:element>
-            <xs:element ref="security:jee"/>
-            <xs:element name="http-basic">
-               <xs:annotation>
-                  <xs:documentation>Adds support for basic authentication
-                </xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
-                  <xs:attributeGroup ref="security:http-basic.attlist"/>
-               </xs:complexType>
-            </xs:element>
-            <xs:element name="logout">
-               <xs:annotation>
-                  <xs:documentation>Incorporates a logout processing filter. Most web applications require a logout filter,
-                although you may not require one if you write a controller to provider similar logic.
-                </xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
-                  <xs:attributeGroup ref="security:logout.attlist"/>
-               </xs:complexType>
-            </xs:element>
-            <xs:element ref="security:password-management"/>
-            <xs:element name="session-management">
-               <xs:annotation>
-                  <xs:documentation>Session-management related functionality is implemented by the addition of a
-                SessionManagementFilter to the filter stack.
-                </xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
-                  <xs:sequence>
-                     <xs:element minOccurs="0" name="concurrency-control">
-                        <xs:annotation>
-                           <xs:documentation>Enables concurrent session control, limiting the number of authenticated sessions a user
-                may have at the same time.
-                </xs:documentation>
-                        </xs:annotation>
-                        <xs:complexType>
-                           <xs:attributeGroup ref="security:concurrency-control.attlist"/>
-                        </xs:complexType>
-                     </xs:element>
-                  </xs:sequence>
-                  <xs:attributeGroup ref="security:session-management.attlist"/>
-               </xs:complexType>
-            </xs:element>
-            <xs:element name="remember-me">
-               <xs:annotation>
-                  <xs:documentation>Sets up remember-me authentication. If used with the "key" attribute (or no attributes)
-                the cookie-only implementation will be used. Specifying "token-repository-ref" or
-                "remember-me-data-source-ref" will use the more secure, persisten token approach.
-                </xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
-                  <xs:attributeGroup ref="security:remember-me.attlist"/>
-               </xs:complexType>
-            </xs:element>
-            <xs:element name="anonymous">
-               <xs:annotation>
-                  <xs:documentation>Adds support for automatically granting all anonymous web requests a particular principal
-                identity and a corresponding granted authority.
-                </xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
-                  <xs:attributeGroup ref="security:anonymous.attlist"/>
-               </xs:complexType>
-            </xs:element>
-            <xs:element name="port-mappings">
-               <xs:annotation>
-                  <xs:documentation>Defines the list of mappings between http and https ports for use in redirects
-                </xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
-                  <xs:sequence>
-                     <xs:element maxOccurs="unbounded" name="port-mapping">
-                        <xs:annotation>
-                           <xs:documentation>Provides a method to map http ports to https ports when forcing a redirect.
-                </xs:documentation>
-                        </xs:annotation>
-                        <xs:complexType>
-                           <xs:attributeGroup ref="security:http-port"/>
-                           <xs:attributeGroup ref="security:https-port"/>
-                        </xs:complexType>
-                     </xs:element>
-                  </xs:sequence>
-               </xs:complexType>
-            </xs:element>
-            <xs:element ref="security:custom-filter"/>
-            <xs:element ref="security:request-cache"/>
-            <xs:element name="expression-handler">
-               <xs:annotation>
-                  <xs:documentation>Defines the SecurityExpressionHandler instance which will be used if expression-based
-                access-control is enabled. A default implementation (with no ACL support) will be used if
-                not supplied.
-                </xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
-                  <xs:attributeGroup ref="security:ref"/>
-               </xs:complexType>
-            </xs:element>
-            <xs:element ref="security:headers"/>
-            <xs:element ref="security:csrf"/>
-            <xs:element ref="security:cors"/>
-         </xs:choice>
-         <xs:attributeGroup ref="security:http.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="http.attlist">
-      <xs:attribute name="pattern" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The request URL pattern which will be mapped to the filter chain created by this &lt;http&gt;
-                element. If omitted, the filter chain will match all requests.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="security">
-         <xs:annotation>
-            <xs:documentation>When set to 'none', requests matching the pattern attribute will be ignored by Spring
-                Security. No security filters will be applied and no SecurityContext will be available. If
-                set, the &lt;http&gt; element must be empty, with no children.
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="none"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-      <xs:attribute name="request-matcher-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Allows a RequestMatcher instance to be used, as an alternative to pattern-matching.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="auto-config" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>A legacy attribute which automatically registers a login form, BASIC authentication and a
-                logout URL and logout services. If unspecified, defaults to "false". We'd recommend you
-                avoid using this and instead explicitly configure the services you require.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="use-expressions" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Enables the use of expressions in the 'access' attributes in &lt;intercept-url&gt; elements
-                rather than the traditional list of configuration attributes. Defaults to 'true'. If
-                enabled, each attribute should contain a single boolean expression. If the expression
-                evaluates to 'true', access will be granted.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="security-context-holder-strategy-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A reference to a SecurityContextHolderStrategy bean. This can be used to customize how the
-                SecurityContextHolder is stored during a request
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="create-session">
-         <xs:annotation>
-            <xs:documentation>Controls the eagerness with which an HTTP session is created by Spring Security classes.
-                If not set, defaults to "ifRequired". If "stateless" is used, this implies that the
-                application guarantees that it will not create a session. This differs from the use of
-                "never" which means that Spring Security will not create a session, but will make use of
-                one if the application does.
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="ifRequired"/>
-               <xs:enumeration value="always"/>
-               <xs:enumeration value="never"/>
-               <xs:enumeration value="stateless"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-      <xs:attribute name="security-context-repository-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A reference to a SecurityContextRepository bean. This can be used to customize how the
-                SecurityContext is stored between requests.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="security-context-explicit-save" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Optional attribute that specifies that the SecurityContext should require explicit saving
-                rather than being synchronized from the SecurityContextHolder. Defaults to "true".
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="request-matcher">
-         <xs:annotation>
-            <xs:documentation>Defines the strategy use for matching incoming requests. Currently the options are 'mvc'
-                (for Spring MVC matcher), 'ant' (for ant path patterns), 'regex' for regular expressions
-                and 'ciRegex' for case-insensitive regular expressions.
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="mvc"/>
-               <xs:enumeration value="ant"/>
-               <xs:enumeration value="regex"/>
-               <xs:enumeration value="ciRegex"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-      <xs:attribute name="servlet-api-provision" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Provides versions of HttpServletRequest security methods such as isUserInRole() and
-                getPrincipal() which are implemented by accessing the Spring SecurityContext. Defaults to
-                "true".
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="jaas-api-provision" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>If available, runs the request as the Subject acquired from the JaasAuthenticationToken.
-                Defaults to "false".
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="use-authorization-manager" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Use AuthorizationManager API instead of SecurityMetadataSource (defaults to true)
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authorization-manager-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Use this AuthorizationManager instead of deriving one from &lt;intercept-url&gt; elements
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="access-decision-manager-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Optional attribute specifying the ID of the AccessDecisionManager implementation which
-                should be used for authorizing HTTP requests.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="realm" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Optional attribute specifying the realm name that will be used for all authentication
-                features that require a realm name (eg BASIC and Digest authentication). If unspecified,
-                defaults to "Spring Security Application".
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="entry-point-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Allows a customized AuthenticationEntryPoint to be set on the ExceptionTranslationFilter.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="once-per-request" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Corresponds to the observeOncePerRequest property of FilterSecurityInterceptor. Defaults
-                to "false"
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="filter-all-dispatcher-types" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Corresponds to the shouldFilterAllDispatcherTypes property of AuthorizationFilter. Do not
-                work when use-authorization-manager=false. Defaults to "true".
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="disable-url-rewriting" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Prevents the jsessionid parameter from being added to rendered URLs. Defaults to "true"
-                (rewriting is disabled).
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="name" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authentication-manager-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A reference to an AuthenticationManager bean
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="observation-registry-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Use this ObservationRegistry to collect metrics on various parts of the filter chain
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  
-  <xs:attributeGroup name="access-denied-handler.attlist">
-      <xs:attribute name="ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Defines a reference to a Spring bean Id.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="error-page" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The access denied page that an authenticated user will be redirected to if they request a
-                page which they don't have the authority to access.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="access-denied-handler-page">
-      <xs:attribute name="error-page" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The access denied page that an authenticated user will be redirected to if they request a
-                page which they don't have the authority to access.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  
-  <xs:attributeGroup name="intercept-url.attlist">
-      <xs:attribute name="pattern" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The request URL pattern which will be mapped to the FilterChain.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="request-matcher-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Allows a RequestMatcher instance to be used, as an alternative to pattern-matching.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="access" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The access configuration attributes that apply for the configured path.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="method">
-         <xs:annotation>
-            <xs:documentation>The HTTP Method for which the access configuration attributes should apply. If not
-                specified, the attributes will apply to any method.
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="GET"/>
-               <xs:enumeration value="DELETE"/>
-               <xs:enumeration value="HEAD"/>
-               <xs:enumeration value="OPTIONS"/>
-               <xs:enumeration value="POST"/>
-               <xs:enumeration value="PUT"/>
-               <xs:enumeration value="PATCH"/>
-               <xs:enumeration value="TRACE"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-      <xs:attribute name="requires-channel" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Used to specify that a URL must be accessed over http or https, or that there is no
-                preference. The value should be "http", "https" or "any", respectively.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="servlet-path" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The path to the servlet. This attribute is only applicable when 'request-matcher' is
-                'mvc'. In addition, the value is only required in the following 2 use cases: 1) There are
-                2 or more HttpServlet's registered in the ServletContext that have mappings starting with
-                '/' and are different; 2) The pattern starts with the same value of a registered
-                HttpServlet path, excluding the default (root) HttpServlet '/'.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  
-  <xs:attributeGroup name="logout.attlist">
-      <xs:attribute name="logout-url" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Specifies the URL that will cause a logout. Spring Security will initialize a filter that
-                responds to this particular URL. Defaults to /logout if unspecified.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="logout-success-url" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Specifies the URL to display once the user has logged out. If not specified, defaults to
-                &lt;form-login-login-page&gt;/?logout (i.e. /login?logout).
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="invalidate-session" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Specifies whether a logout also causes HttpSession invalidation, which is generally
-                desirable. If unspecified, defaults to true.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="success-handler-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A reference to a LogoutSuccessHandler implementation which will be used to determine the
-                destination to which the user is taken after logging out.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="delete-cookies" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A comma-separated list of the names of cookies which should be deleted when the user logs
-                out
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="request-cache">
-      <xs:annotation>
-         <xs:documentation>Allow the RequestCache used for saving requests during the login process to be set
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:ref"/>
-      </xs:complexType>
-   </xs:element>
-  
-  <xs:attributeGroup name="form-login.attlist">
-      <xs:attribute name="login-processing-url" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The URL that the login form is posted to. If unspecified, it defaults to /login.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="username-parameter" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The name of the request parameter which contains the username. Defaults to 'username'.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="password-parameter" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The name of the request parameter which contains the password. Defaults to 'password'.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="default-target-url" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The URL that will be redirected to after successful authentication, if the user's previous
-                action could not be resumed. This generally happens if the user visits a login page
-                without having first requested a secured operation that triggers authentication. If
-                unspecified, defaults to the root of the application.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="always-use-default-target" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Whether the user should always be redirected to the default-target-url after login.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="login-page" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The URL for the login page. If no login URL is specified, Spring Security will
-                automatically create a login URL at GET /login and a corresponding filter to render that
-                login URL when requested.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authentication-failure-url" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The URL for the login failure page. If no login failure URL is specified, Spring Security
-                will automatically create a failure login URL at /login?error and a corresponding filter
-                to render that login failure URL when requested.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authentication-success-handler-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to an AuthenticationSuccessHandler bean which should be used to handle a
-                successful authentication request. Should not be used in combination with
-                default-target-url (or always-use-default-target-url) as the implementation should always
-                deal with navigation to the subsequent destination
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authentication-failure-handler-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to an AuthenticationFailureHandler bean which should be used to handle a failed
-                authentication request. Should not be used in combination with authentication-failure-url
-                as the implementation should always deal with navigation to the subsequent destination
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authentication-details-source-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to an AuthenticationDetailsSource which will be used by the authentication
-                filter
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authentication-failure-forward-url" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The URL for the ForwardAuthenticationFailureHandler
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authentication-success-forward-url" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The URL for the ForwardAuthenticationSuccessHandler
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="oauth2-login">
-      <xs:annotation>
-         <xs:documentation>Configures authentication support using an OAuth 2.0 and/or OpenID Connect 1.0 Provider.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:oauth2-login.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="oauth2-login.attlist">
-      <xs:attribute name="client-registration-repository-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the ClientRegistrationRepository
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authorized-client-repository-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the OAuth2AuthorizedClientRepository
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authorized-client-service-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the OAuth2AuthorizedClientService
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authorization-request-repository-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the AuthorizationRequestRepository
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authorization-request-resolver-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the OAuth2AuthorizationRequestResolver
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authorization-redirect-strategy-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the authorization RedirectStrategy
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="access-token-response-client-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the OAuth2AccessTokenResponseClient
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="user-authorities-mapper-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the GrantedAuthoritiesMapper
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="user-service-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the OAuth2UserService
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="oidc-user-service-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the OpenID Connect OAuth2UserService
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="login-processing-url" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The URI where the filter processes authentication requests
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="login-page" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The URI to send users to login
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authentication-success-handler-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the AuthenticationSuccessHandler
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authentication-failure-handler-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the AuthenticationFailureHandler
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="jwt-decoder-factory-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the JwtDecoderFactory used by OidcAuthorizationCodeAuthenticationProvider
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="oauth2-client">
-      <xs:annotation>
-         <xs:documentation>Configures OAuth 2.0 Client support.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:sequence>
-            <xs:element minOccurs="0" ref="security:authorization-code-grant"/>
-         </xs:sequence>
-         <xs:attributeGroup ref="security:oauth2-client.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="oauth2-client.attlist">
-      <xs:attribute name="client-registration-repository-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the ClientRegistrationRepository
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authorized-client-repository-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the OAuth2AuthorizedClientRepository
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authorized-client-service-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the OAuth2AuthorizedClientService
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="authorization-code-grant">
-      <xs:annotation>
-         <xs:documentation>Configures OAuth 2.0 Authorization Code Grant.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:authorization-code-grant.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="authorization-code-grant.attlist">
-      <xs:attribute name="authorization-request-repository-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the AuthorizationRequestRepository
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authorization-redirect-strategy-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the authorization RedirectStrategy
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authorization-request-resolver-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the OAuth2AuthorizationRequestResolver
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="access-token-response-client-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the OAuth2AccessTokenResponseClient
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="client-registrations">
-      <xs:annotation>
-         <xs:documentation>Container element for client(s) registered with an OAuth 2.0 or OpenID Connect 1.0
-                Provider.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:sequence>
-            <xs:element maxOccurs="unbounded" ref="security:client-registration"/>
-            <xs:element minOccurs="0" maxOccurs="unbounded" ref="security:provider"/>
-         </xs:sequence>
-      </xs:complexType>
-   </xs:element>
-  <xs:element name="client-registration">
-      <xs:annotation>
-         <xs:documentation>Represents a client registered with an OAuth 2.0 or OpenID Connect 1.0 Provider.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:client-registration.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="client-registration.attlist">
-      <xs:attribute name="registration-id" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The ID that uniquely identifies the client registration.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="client-id" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The client identifier.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="client-secret" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The client secret.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="client-authentication-method">
-         <xs:annotation>
-            <xs:documentation>The method used to authenticate the client with the provider. The supported values are
-                client_secret_basic, client_secret_post and none (public clients).
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="client_secret_basic"/>
-               <xs:enumeration value="basic"/>
-               <xs:enumeration value="client_secret_post"/>
-               <xs:enumeration value="post"/>
-               <xs:enumeration value="none"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-      <xs:attribute name="authorization-grant-type">
-         <xs:annotation>
-            <xs:documentation>The OAuth 2.0 Authorization Framework defines four Authorization Grant types. The
-                supported values are authorization_code, client_credentials and password.
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="authorization_code"/>
-               <xs:enumeration value="client_credentials"/>
-               <xs:enumeration value="password"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-      <xs:attribute name="redirect-uri" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The client’s registered redirect URI that the Authorization Server redirects the
-                end-user’s user-agent to after the end-user has authenticated and authorized access to the
-                client.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="scope" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A comma-separated list of scope(s) requested by the client during the Authorization
-                Request flow, such as openid, email, or profile.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="client-name" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A descriptive name used for the client. The name may be used in certain scenarios, such as
-                when displaying the name of the client in the auto-generated login page.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="provider-id" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A reference to the associated provider. May reference a 'provider' element or use one of
-                the common providers (google, github, facebook, okta).
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="provider">
-      <xs:annotation>
-         <xs:documentation>The configuration information for an OAuth 2.0 or OpenID Connect 1.0 Provider.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:provider.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="provider.attlist">
-      <xs:attribute name="provider-id" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The ID that uniquely identifies the provider.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authorization-uri" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The Authorization Endpoint URI for the Authorization Server.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="token-uri" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The Token Endpoint URI for the Authorization Server.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="user-info-uri" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The UserInfo Endpoint URI used to access the claims/attributes of the authenticated
-                end-user.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="user-info-authentication-method">
-         <xs:annotation>
-            <xs:documentation>The authentication method used when sending the access token to the UserInfo Endpoint. The
-                supported values are header, form and query.
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="header"/>
-               <xs:enumeration value="form"/>
-               <xs:enumeration value="query"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-      <xs:attribute name="user-info-user-name-attribute" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The name of the attribute returned in the UserInfo Response that references the Name or
-                Identifier of the end-user.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="jwk-set-uri" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The URI used to retrieve the JSON Web Key (JWK) Set from the Authorization Server, which
-                contains the cryptographic key(s) used to verify the JSON Web Signature (JWS) of the ID
-                Token and optionally the UserInfo Response.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="issuer-uri" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The URI used to discover the configuration information for an OAuth 2.0 or OpenID Connect
-                1.0 Provider.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="oauth2-resource-server">
-      <xs:annotation>
-         <xs:documentation>Configures authentication support as an OAuth 2.0 Resource Server.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:choice minOccurs="0" maxOccurs="unbounded">
-            <xs:element ref="security:jwt"/>
-            <xs:element ref="security:opaque-token"/>
-         </xs:choice>
-         <xs:attributeGroup ref="security:oauth2-resource-server.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="oauth2-resource-server.attlist">
-      <xs:attribute name="authentication-manager-resolver-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to an AuthenticationManagerResolver
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="bearer-token-resolver-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to a BearerTokenResolver
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="entry-point-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to a AuthenticationEntryPoint
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="jwt">
-      <xs:annotation>
-         <xs:documentation>Configures JWT authentication
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:jwt.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="jwt.attlist">
-      <xs:attribute name="jwk-set-uri" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The URI to use to collect the JWK Set for verifying JWTs
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="decoder-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to a JwtDecoder
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="jwt-authentication-converter-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to a Converter&lt;Jwt, AbstractAuthenticationToken&gt;
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="opaque-token">
-      <xs:annotation>
-         <xs:documentation>Configuration Opaque Token authentication
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:opaque-token.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="opaque-token.attlist">
-      <xs:attribute name="introspection-uri" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The URI to use to introspect opaque token attributes
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="client-id" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The Client ID to use to authenticate the introspection request
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="client-secret" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The Client secret to use to authenticate the introspection request
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="introspector-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to an OpaqueTokenIntrospector
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authentication-converter-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to an OpaqueTokenAuthenticationConverter responsible for converting successful
-                introspection result into an Authentication.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  
-  <xs:attributeGroup name="saml2-login.attlist">
-      <xs:attribute name="relying-party-registration-repository-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the RelyingPartyRegistrationRepository
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authentication-request-repository-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the Saml2AuthenticationRequestRepository
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authentication-request-resolver-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the Saml2AuthenticationRequestResolver
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authentication-converter-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the AuthenticationConverter
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="login-processing-url" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The URI where the filter processes authentication requests
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="login-page" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The URI to send users to login
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authentication-success-handler-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the AuthenticationSuccessHandler
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authentication-failure-handler-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the AuthenticationFailureHandler
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authentication-manager-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the AuthenticationManager
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  
-  <xs:attributeGroup name="saml2-logout.attlist">
-      <xs:attribute name="logout-url" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The URL by which the relying or asserting party can trigger logout
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="logout-request-url" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The URL by which the asserting party can send a SAML 2.0 Logout Request
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="logout-response-url" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The URL by which the asserting party can send a SAML 2.0 Logout Response
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="relying-party-registration-repository-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the RelyingPartyRegistrationRepository
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="logout-request-validator-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the Saml2LogoutRequestValidator
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="logout-request-resolver-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the Saml2LogoutRequestResolver
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="logout-request-repository-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the Saml2LogoutRequestRepository
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="logout-response-validator-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the Saml2LogoutResponseValidator
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="logout-response-resolver-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to the Saml2LogoutResponseResolver
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="relying-party-registrations">
-      <xs:annotation>
-         <xs:documentation>Container element for relying party(ies) registered with a SAML 2.0 identity provider
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:sequence>
-            <xs:element maxOccurs="unbounded" ref="security:relying-party-registration"/>
-            <xs:element minOccurs="0" maxOccurs="unbounded" ref="security:asserting-party"/>
-         </xs:sequence>
-         <xs:attributeGroup ref="security:relying-party-registrations.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="relying-party-registrations.attlist">
-      <xs:attribute name="id" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The identifier by which to refer to the repository in other beans
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="relying-party-registration">
-      <xs:annotation>
-         <xs:documentation>Represents a relying party registered with a SAML 2.0 identity provider
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:sequence>
-            <xs:element minOccurs="0" maxOccurs="unbounded" ref="security:signing-credential"/>
-            <xs:element minOccurs="0" maxOccurs="unbounded" ref="security:decryption-credential"/>
-         </xs:sequence>
-         <xs:attributeGroup ref="security:relying-party-registration.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="relying-party-registration.attlist">
-      <xs:attribute name="registration-id" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The ID that uniquely identifies the relying party registration.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="metadata-location" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The location of the Identity Provider's metadata.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="entity-id" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The relying party's EntityID
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="assertion-consumer-service-location" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The Assertion Consumer Service Location
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="assertion-consumer-service-binding" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The Assertion Consumer Service Binding
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="asserting-party-id" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A reference to the associated asserting party.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="single-logout-service-location" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The relying party &lt;a
-                href="https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7"&gt;SingleLogoutService
-                Location&lt;/a&gt;
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="single-logout-service-response-location" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The relying party &lt;a
-                href="https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7"&gt;SingleLogoutService
-                Response Location&lt;/a&gt;
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="single-logout-service-binding" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The relying party &lt;a
-                href="https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7"&gt;SingleLogoutService
-                Binding&lt;/a&gt;
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="signing-credential">
-      <xs:annotation>
-         <xs:documentation>The relying party's signing credential
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:signing-credential.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="signing-credential.attlist">
-      <xs:attribute name="private-key-location" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The private key location
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="certificate-location" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The certificate location
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="decryption-credential">
-      <xs:annotation>
-         <xs:documentation>The relying party's decryption credential
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:decryption-credential.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="decryption-credential.attlist">
-      <xs:attribute name="private-key-location" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The private key location
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="certificate-location" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The certificate location
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="asserting-party">
-      <xs:annotation>
-         <xs:documentation>The configuration metadata of the Asserting party
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:sequence>
-            <xs:element minOccurs="0" maxOccurs="unbounded" ref="security:verification-credential"/>
-            <xs:element minOccurs="0" maxOccurs="unbounded" ref="security:encryption-credential"/>
-         </xs:sequence>
-         <xs:attributeGroup ref="security:asserting-party.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="asserting-party.attlist">
-      <xs:attribute name="asserting-party-id" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A unique identifier of the asserting party.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="entity-id" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The asserting party's EntityID.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="want-authn-requests-signed" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Indicates the asserting party's preference that relying parties should sign the
-                AuthnRequest before sending
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="single-sign-on-service-location" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The &lt;a
-                href="https://www.oasis-open.org/committees/download.php/51890/SAML%20MD%20simplified%20overview.pdf#2.5%20Endpoint"&gt;SingleSignOnService&lt;/a&gt;
-                Location.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="single-sign-on-service-binding" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The &lt;a
-                href="https://www.oasis-open.org/committees/download.php/51890/SAML%20MD%20simplified%20overview.pdf#2.5%20Endpoint"&gt;SingleSignOnService&lt;/a&gt;
-                Binding.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="signing-algorithms" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A comma separated list of org.opensaml.saml.ext.saml2alg.SigningMethod Algorithms for this
-                asserting party, in preference order.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="single-logout-service-location" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The asserting party &lt;a
-                href="https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7"&gt;SingleLogoutService
-                Location&lt;/a&gt;
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="single-logout-service-response-location" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The asserting party &lt;a
-                href="https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7"&gt;SingleLogoutService
-                Response Location&lt;/a&gt;
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="single-logout-service-binding" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The asserting party &lt;a
-                href="https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7"&gt;SingleLogoutService
-                Binding&lt;/a&gt;
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="verification-credential">
-      <xs:annotation>
-         <xs:documentation>The relying party's verification credential
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:verification-credential.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="verification-credential.attlist">
-      <xs:attribute name="private-key-location" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The private key location
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="certificate-location" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The certificate location
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="encryption-credential">
-      <xs:annotation>
-         <xs:documentation>The asserting party's encryption credential
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:encryption-credential.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="encryption-credential.attlist">
-      <xs:attribute name="private-key-location" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The private key location
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="certificate-location" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The certificate location
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="filter-chain-map">
-      <xs:annotation>
-         <xs:documentation>Used to explicitly configure a FilterChainProxy instance with a FilterChainMap
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:sequence>
-            <xs:element maxOccurs="unbounded" ref="security:filter-chain"/>
-         </xs:sequence>
-         <xs:attributeGroup ref="security:filter-chain-map.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="filter-chain-map.attlist">
-      <xs:attribute name="request-matcher">
-         <xs:annotation>
-            <xs:documentation>Defines the strategy use for matching incoming requests. Currently the options are 'mvc'
-                (for Spring MVC matcher), 'ant' (for ant path patterns), 'regex' for regular expressions
-                and 'ciRegex' for case-insensitive regular expressions.
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="mvc"/>
-               <xs:enumeration value="ant"/>
-               <xs:enumeration value="regex"/>
-               <xs:enumeration value="ciRegex"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="filter-chain">
-      <xs:annotation>
-         <xs:documentation>Used within to define a specific URL pattern and the list of filters which apply to the
-                URLs matching that pattern. When multiple filter-chain elements are assembled in a list in
-                order to configure a FilterChainProxy, the most specific patterns must be placed at the
-                top of the list, with most general ones at the bottom.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:filter-chain.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="filter-chain.attlist">
-      <xs:attribute name="pattern" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The request URL pattern which will be mapped to the FilterChain.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="request-matcher-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Allows a RequestMatcher instance to be used, as an alternative to pattern-matching.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="filters" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A comma separated list of bean names that implement Filter that should be processed for
-                this FilterChain. If the value is none, then no Filters will be used for this FilterChain.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="pattern">
-      <xs:attribute name="pattern" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The request URL pattern which will be mapped to the FilterChain.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="request-matcher-ref">
-      <xs:attribute name="request-matcher-ref" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Allows a RequestMatcher instance to be used, as an alternative to pattern-matching.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="filter-security-metadata-source">
-      <xs:annotation>
-         <xs:documentation>Used to explicitly configure a FilterSecurityMetadataSource bean for use with a
-                FilterSecurityInterceptor. Usually only needed if you are configuring a FilterChainProxy
-                explicitly, rather than using the &lt;http&gt; element. The intercept-url elements used should
-                only contain pattern, method and access attributes. Any others will result in a
-                configuration error.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:sequence>
-            <xs:element maxOccurs="unbounded" name="intercept-url">
-               <xs:annotation>
-                  <xs:documentation>Specifies the access attributes and/or filter list for a particular set of URLs.
-                </xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
-                  <xs:attributeGroup ref="security:intercept-url.attlist"/>
-               </xs:complexType>
-            </xs:element>
-         </xs:sequence>
-         <xs:attributeGroup ref="security:fsmds.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="fsmds.attlist">
-      <xs:attribute name="use-expressions" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Enables the use of expressions in the 'access' attributes in &lt;intercept-url&gt; elements
-                rather than the traditional list of configuration attributes. Defaults to 'true'. If
-                enabled, each attribute should contain a single boolean expression. If the expression
-                evaluates to 'true', access will be granted.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="id" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="request-matcher">
-         <xs:annotation>
-            <xs:documentation>Defines the strategy use for matching incoming requests. Currently the options are 'mvc'
-                (for Spring MVC matcher), 'ant' (for ant path patterns), 'regex' for regular expressions
-                and 'ciRegex' for case-insensitive regular expressions.
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="mvc"/>
-               <xs:enumeration value="ant"/>
-               <xs:enumeration value="regex"/>
-               <xs:enumeration value="ciRegex"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-  </xs:attributeGroup>
-  
-  <xs:attributeGroup name="http-basic.attlist">
-      <xs:attribute name="entry-point-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Sets the AuthenticationEntryPoint which is used by the BasicAuthenticationFilter.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authentication-details-source-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to an AuthenticationDetailsSource which will be used by the authentication
-                filter
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="password-management">
-      <xs:annotation>
-         <xs:documentation>Adds support for the password management.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:password-management.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="password-management.attlist">
-      <xs:attribute name="change-password-page" type="xs:string">
-         <xs:annotation>
-            <xs:documentation>The change password page. Defaults to "/change-password".
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  
-  <xs:attributeGroup name="session-management.attlist">
-      <xs:attribute name="authentication-strategy-explicit-invocation" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Specifies that SessionAuthenticationStrategy must be explicitly invoked. Default false
-                (i.e. SessionManagementFilter will implicitly invoke SessionAuthenticationStrategy).
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="session-fixation-protection">
-         <xs:annotation>
-            <xs:documentation>Indicates how session fixation protection will be applied when a user authenticates. If
-                set to "none", no protection will be applied. "newSession" will create a new empty
-                session, with only Spring Security-related attributes migrated. "migrateSession" will
-                create a new session and copy all session attributes to the new session. In Servlet 3.1
-                (Java EE 7) and newer containers, specifying "changeSessionId" will keep the existing
-                session and use the container-supplied session fixation protection
-                (HttpServletRequest#changeSessionId()). Defaults to "changeSessionId" in Servlet 3.1 and
-                newer containers, "migrateSession" in older containers. Throws an exception if
-                "changeSessionId" is used in older containers.
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="none"/>
-               <xs:enumeration value="newSession"/>
-               <xs:enumeration value="migrateSession"/>
-               <xs:enumeration value="changeSessionId"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-      <xs:attribute name="invalid-session-url" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The URL to which a user will be redirected if they submit an invalid session indentifier.
-                Typically used to detect session timeouts.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="invalid-session-strategy-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Allows injection of the InvalidSessionStrategy instance used by the
-                SessionManagementFilter
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="session-authentication-strategy-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Allows injection of the SessionAuthenticationStrategy instance used by the
-                SessionManagementFilter
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="session-authentication-error-url" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Defines the URL of the error page which should be shown when the
-                SessionAuthenticationStrategy raises an exception. If not set, an unauthorized (401) error
-                code will be returned to the client. Note that this attribute doesn't apply if the error
-                occurs during a form-based login, where the URL for authentication failure will take
-                precedence.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  
-  <xs:attributeGroup name="concurrency-control.attlist">
-      <xs:attribute name="max-sessions" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The maximum number of sessions a single authenticated user can have open at the same time.
-                Defaults to "1". A negative value denotes unlimited sessions.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="expired-url" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The URL a user will be redirected to if they attempt to use a session which has been
-                "expired" because they have logged in again.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="expired-session-strategy-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Allows injection of the SessionInformationExpiredStrategy instance used by the
-                ConcurrentSessionFilter
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="error-if-maximum-exceeded" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Specifies that an unauthorized error should be reported when a user attempts to login when
-                they already have the maximum configured sessions open. The default behaviour is to expire
-                the original session. If the session-authentication-error-url attribute is set on the
-                session-management URL, the user will be redirected to this URL.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="session-registry-alias" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Allows you to define an alias for the SessionRegistry bean in order to access it in your
-                own configuration.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="session-registry-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Allows you to define an external SessionRegistry bean to be used by the concurrency
-                control setup.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  
-  <xs:attributeGroup name="remember-me.attlist">
-      <xs:attribute name="key" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The "key" used to identify cookies from a specific token-based remember-me application.
-                You should set this to a unique value for your application. If unset, it will default to a
-                random value generated by SecureRandom.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="token-repository-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to a PersistentTokenRepository bean for use with the persistent token
-                remember-me implementation.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="data-source-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A reference to a DataSource bean
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attributeGroup ref="security:remember-me-services-ref"/>
-      <xs:attribute name="user-service-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="services-alias" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Exports the internally defined RememberMeServices as a bean alias, allowing it to be used
-                by other beans in the application context.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="use-secure-cookie" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Determines whether the "secure" flag will be set on the remember-me cookie. If set to
-                true, the cookie will only be submitted over HTTPS (recommended). By default, secure
-                cookies will be used if the request is made on a secure connection.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="token-validity-seconds" type="xs:string">
-         <xs:annotation>
-            <xs:documentation>The period (in seconds) for which the remember-me cookie should be valid.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authentication-success-handler-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to an AuthenticationSuccessHandler bean which should be used to handle a
-                successful remember-me authentication.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="remember-me-parameter" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The name of the request parameter which toggles remember-me authentication. Defaults to
-                'remember-me'.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="remember-me-cookie" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The name of cookie which store the token for remember-me authentication. Defaults to
-                'remember-me'.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="token-repository-ref">
-      <xs:attribute name="token-repository-ref" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to a PersistentTokenRepository bean for use with the persistent token
-                remember-me implementation.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="remember-me-services-ref">
-      <xs:attribute name="services-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Allows a custom implementation of RememberMeServices to be used. Note that this
-                implementation should return RememberMeAuthenticationToken instances with the same "key"
-                value as specified in the remember-me element. Alternatively it should register its own
-                AuthenticationProvider. It should also implement the LogoutHandler interface, which will
-                be invoked when a user logs out. Typically the remember-me cookie would be removed on
-                logout.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="remember-me-data-source-ref">
-      <xs:attributeGroup ref="security:data-source-ref"/>
-  </xs:attributeGroup>
-  
-  <xs:attributeGroup name="anonymous.attlist">
-      <xs:attribute name="key" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The key shared between the provider and filter. This generally does not need to be set. If
-                unset, it will default to a random value generated by SecureRandom.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="username" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The username that should be assigned to the anonymous request. This allows the principal
-                to be identified, which may be important for logging and auditing. if unset, defaults to
-                "anonymousUser".
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="granted-authority" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The granted authority that should be assigned to the anonymous request. Commonly this is
-                used to assign the anonymous request particular roles, which can subsequently be used in
-                authorization decisions. If unset, defaults to "ROLE_ANONYMOUS".
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="enabled" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>With the default namespace setup, the anonymous "authentication" facility is automatically
-                enabled. You can disable it using this property.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  
-  
-  <xs:attributeGroup name="http-port">
-      <xs:attribute name="http" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The http port to use.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="https-port">
-      <xs:attribute name="https" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The https port to use.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  
-  <xs:attributeGroup name="x509.attlist">
-      <xs:attribute name="subject-principal-regex" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The regular expression used to obtain the username from the certificate's subject.
-                Defaults to matching on the common name using the pattern "CN=(.*?),".
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="user-service-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authentication-details-source-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Reference to an AuthenticationDetailsSource which will be used by the authentication
-                filter
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="jee">
-      <xs:annotation>
-         <xs:documentation>Adds a J2eePreAuthenticatedProcessingFilter to the filter chain to provide integration
-                with container authentication.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:jee.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="jee.attlist">
-      <xs:attribute name="mappable-roles" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A comma-separate list of roles to look for in the incoming HttpServletRequest.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="user-service-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="authentication-manager">
-      <xs:annotation>
-         <xs:documentation>Registers the AuthenticationManager instance and allows its list of
-                AuthenticationProviders to be defined. Also allows you to define an alias to allow you to
-                reference the AuthenticationManager in your own beans.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:choice minOccurs="0" maxOccurs="unbounded">
-            <xs:element name="authentication-provider">
-               <xs:annotation>
-                  <xs:documentation>Indicates that the contained user-service should be used as an authentication source.
-                </xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
-                  <xs:choice minOccurs="0" maxOccurs="unbounded">
-                     <xs:element ref="security:any-user-service"/>
-                     <xs:element name="password-encoder">
-                        <xs:annotation>
-                           <xs:documentation>element which defines a password encoding strategy. Used by an authentication provider to
-                convert submitted passwords to hashed versions, for example.
-                </xs:documentation>
-                        </xs:annotation>
-                        <xs:complexType>
-                           <xs:attributeGroup ref="security:password-encoder.attlist"/>
-                        </xs:complexType>
-                     </xs:element>
-                  </xs:choice>
-                  <xs:attributeGroup ref="security:ap.attlist"/>
-               </xs:complexType>
-            </xs:element>
-            <xs:element name="ldap-authentication-provider">
-               <xs:annotation>
-                  <xs:documentation>Sets up an ldap authentication provider
-                </xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
-                  <xs:sequence>
-                     <xs:element minOccurs="0" name="password-compare">
-                        <xs:annotation>
-                           <xs:documentation>Specifies that an LDAP provider should use an LDAP compare operation of the user's
-                password to authenticate the user
-                </xs:documentation>
-                        </xs:annotation>
-                        <xs:complexType>
-                           <xs:sequence>
-                              <xs:element minOccurs="0" name="password-encoder">
-                                 <xs:annotation>
-                                    <xs:documentation>element which defines a password encoding strategy. Used by an authentication provider to
-                convert submitted passwords to hashed versions, for example.
-                </xs:documentation>
-                                 </xs:annotation>
-                                 <xs:complexType>
-                                    <xs:attributeGroup ref="security:password-encoder.attlist"/>
-                                 </xs:complexType>
-                              </xs:element>
-                           </xs:sequence>
-                           <xs:attributeGroup ref="security:password-compare.attlist"/>
-                        </xs:complexType>
-                     </xs:element>
-                  </xs:sequence>
-                  <xs:attributeGroup ref="security:ldap-ap.attlist"/>
-               </xs:complexType>
-            </xs:element>
-         </xs:choice>
-         <xs:attributeGroup ref="security:authman.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="authman.attlist">
-      <xs:attribute name="id" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="alias" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>An alias you wish to use for the AuthenticationManager bean (not required it you are using
-                a specific id)
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="erase-credentials" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>If set to true, the AuthenticationManger will attempt to clear any credentials data in the
-                returned Authentication object, once the user has been authenticated.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="observation-registry-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Use this ObservationRegistry to collect metrics on various parts of the filter chain
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  
-  <xs:attributeGroup name="ap.attlist">
-      <xs:attribute name="ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Defines a reference to a Spring bean Id.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="user-service-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="user-service" substitutionGroup="security:any-user-service">
-      <xs:annotation>
-         <xs:documentation>Creates an in-memory UserDetailsService from a properties file or a list of "user" child
-                elements. Usernames are converted to lower-case internally to allow for case-insensitive
-                lookups, so this should not be used if case-sensitivity is required.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:sequence>
-            <xs:element minOccurs="0" maxOccurs="unbounded" name="user">
-               <xs:annotation>
-                  <xs:documentation>Represents a user in the application.
-                </xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
-                  <xs:attributeGroup ref="security:user.attlist"/>
-               </xs:complexType>
-            </xs:element>
-         </xs:sequence>
-         <xs:attribute name="id" type="xs:token">
-            <xs:annotation>
-               <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.
-                </xs:documentation>
-            </xs:annotation>
-         </xs:attribute>
-         <xs:attributeGroup ref="security:properties-file"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="properties-file">
-      <xs:attribute name="properties" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The location of a Properties file where each line is in the format of
-                username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  
-  <xs:attributeGroup name="user.attlist">
-      <xs:attribute name="name" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The username assigned to the user.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="password" type="xs:string">
-         <xs:annotation>
-            <xs:documentation>The password assigned to the user. This may be hashed if the corresponding authentication
-                provider supports hashing (remember to set the "hash" attribute of the "user-service"
-                element). This attribute be omitted in the case where the data will not be used for
-                authentication, but only for accessing authorities. If omitted, the namespace will
-                generate a random value, preventing its accidental use for authentication. Cannot be
-                empty.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authorities" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>One of more authorities granted to the user. Separate authorities with a comma (but no
-                space). For example, "ROLE_USER,ROLE_ADMINISTRATOR"
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="locked" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Can be set to "true" to mark an account as locked and unusable.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="disabled" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Can be set to "true" to mark an account as disabled and unusable.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="jdbc-user-service" substitutionGroup="security:any-user-service">
-      <xs:annotation>
-         <xs:documentation>Causes creation of a JDBC-based UserDetailsService.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attribute name="id" type="xs:token">
-            <xs:annotation>
-               <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.
-                </xs:documentation>
-            </xs:annotation>
-         </xs:attribute>
-         <xs:attributeGroup ref="security:jdbc-user-service.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="jdbc-user-service.attlist">
-      <xs:attribute name="data-source-ref" use="required" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The bean ID of the DataSource which provides the required tables.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="cache-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Defines a reference to a cache for use with a UserDetailsService.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="users-by-username-query" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>An SQL statement to query a username, password, and enabled status given a username.
-                Default is "select username,password,enabled from users where username = ?"
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="authorities-by-username-query" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>An SQL statement to query for a user's granted authorities given a username. The default
-                is "select username, authority from authorities where username = ?"
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="group-authorities-by-username-query" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>An SQL statement to query user's group authorities given a username. The default is
-                "select g.id, g.group_name, ga.authority from groups g, group_members gm,
-                group_authorities ga where gm.username = ? and g.id = ga.group_id and g.id = gm.group_id"
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="role-prefix" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>A non-empty string prefix that will be added to role strings loaded from persistent
-                storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is
-                non-empty.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="csrf">
-      <xs:annotation>
-         <xs:documentation>Element for configuration of the CsrfFilter for protection against CSRF. It also updates
-                the default RequestCache to only replay "GET" requests.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:csrf-options.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="csrf-options.attlist">
-      <xs:attribute name="disabled" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Specifies if csrf protection should be disabled. Default false (i.e. CSRF protection is
-                enabled).
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="request-matcher-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The RequestMatcher instance to be used to determine if CSRF should be applied. Default is
-                any HTTP method except "GET", "TRACE", "HEAD", "OPTIONS"
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="token-repository-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The CsrfTokenRepository to use. The default is HttpSessionCsrfTokenRepository wrapped by
-                LazyCsrfTokenRepository.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="request-handler-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The CsrfTokenRequestHandler to use. The default is CsrfTokenRequestAttributeHandler.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="headers">
-      <xs:annotation>
-         <xs:documentation>Element for configuration of the HeaderWritersFilter. Enables easy setting for the
-                X-Frame-Options, X-XSS-Protection and X-Content-Type-Options headers.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:choice minOccurs="0" maxOccurs="unbounded">
-            <xs:element ref="security:cache-control"/>
-            <xs:element ref="security:xss-protection"/>
-            <xs:element ref="security:hsts"/>
-            <xs:element ref="security:frame-options"/>
-            <xs:element ref="security:content-type-options"/>
-            <xs:element ref="security:hpkp"/>
-            <xs:element ref="security:content-security-policy"/>
-            <xs:element ref="security:referrer-policy"/>
-            <xs:element ref="security:feature-policy"/>
-            <xs:element ref="security:permissions-policy"/>
-            <xs:element ref="security:cross-origin-opener-policy"/>
-            <xs:element ref="security:cross-origin-embedder-policy"/>
-            <xs:element ref="security:cross-origin-resource-policy"/>
-            <xs:element ref="security:header"/>
-         </xs:choice>
-         <xs:attributeGroup ref="security:headers-options.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="headers-options.attlist">
-      <xs:attribute name="defaults-disabled" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Specifies if the default headers should be disabled. Default false.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="disabled" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Specifies if headers should be disabled. Default false.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="hsts">
-      <xs:annotation>
-         <xs:documentation>Adds support for HTTP Strict Transport Security (HSTS)
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:hsts-options.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="hsts-options.attlist">
-      <xs:attribute name="disabled" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Specifies if HTTP Strict Transport Security (HSTS) should be disabled. Default false.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="include-subdomains" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Specifies if subdomains should be included. Default true.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="max-age-seconds" type="xs:integer">
-         <xs:annotation>
-            <xs:documentation>Specifies the maximum amount of time the host should be considered a Known HSTS Host.
-                Default one year.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="request-matcher-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The RequestMatcher instance to be used to determine if the header should be set. Default
-                is if HttpServletRequest.isSecure() is true.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="preload" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Specifies if preload should be included. Default false.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="cors">
-      <xs:annotation>
-         <xs:documentation>Element for configuration of CorsFilter. If no CorsFilter or CorsConfigurationSource is
-                specified a HandlerMappingIntrospector is used as the CorsConfigurationSource
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:cors-options.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="cors-options.attlist">
-      <xs:attribute name="ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Defines a reference to a Spring bean Id.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="configuration-source-ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Specifies a bean id that is a CorsConfigurationSource used to construct the CorsFilter to
-                use
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="hpkp">
-      <xs:annotation>
-         <xs:documentation>Adds support for HTTP Public Key Pinning (HPKP).
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:complexContent>
-            <xs:extension base="security:hpkp.pins">
-               <xs:attributeGroup ref="security:hpkp.attlist"/>
-            </xs:extension>
-         </xs:complexContent>
-      </xs:complexType>
-   </xs:element>
-  <xs:complexType name="hpkp.pins">
-      <xs:sequence>
-         <xs:element ref="security:pins"/>
-      </xs:sequence>
-  </xs:complexType>
-  <xs:element name="pins">
-      <xs:annotation>
-         <xs:documentation>The list with pins
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:sequence>
-            <xs:element maxOccurs="unbounded" ref="security:pin"/>
-         </xs:sequence>
-      </xs:complexType>
-   </xs:element>
-  <xs:element name="pin">
-      <xs:annotation>
-         <xs:documentation>A pin is specified using the base64-encoded SPKI fingerprint as value and the
-                cryptographic hash algorithm as attribute
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType mixed="true">
-         <xs:attribute name="algorithm" type="xs:string">
-            <xs:annotation>
-               <xs:documentation>The cryptographic hash algorithm
-                </xs:documentation>
-            </xs:annotation>
-         </xs:attribute>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="hpkp.attlist">
-      <xs:attribute name="disabled" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Specifies if HTTP Public Key Pinning (HPKP) should be disabled. Default false.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="include-subdomains" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Specifies if subdomains should be included. Default false.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="max-age-seconds" type="xs:integer">
-         <xs:annotation>
-            <xs:documentation>Sets the value for the max-age directive of the Public-Key-Pins header. Default 60 days.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="report-only" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Specifies if the browser should only report pin validation failures. Default true.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="report-uri" type="xs:string">
-         <xs:annotation>
-            <xs:documentation>Specifies the URI to which the browser should report pin validation failures.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="content-security-policy">
-      <xs:annotation>
-         <xs:documentation>Adds support for Content Security Policy (CSP)
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:csp-options.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="csp-options.attlist">
-      <xs:attribute name="policy-directives" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The security policy directive(s) for the Content-Security-Policy header or if report-only
-                is set to true, then the Content-Security-Policy-Report-Only header is used.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="report-only" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Set to true, to enable the Content-Security-Policy-Report-Only header for reporting policy
-                violations only. Defaults to false.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="referrer-policy">
-      <xs:annotation>
-         <xs:documentation>Adds support for Referrer Policy
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:referrer-options.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="referrer-options.attlist">
-      <xs:attribute name="policy">
-         <xs:annotation>
-            <xs:documentation>The policies for the Referrer-Policy header.
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="no-referrer"/>
-               <xs:enumeration value="no-referrer-when-downgrade"/>
-               <xs:enumeration value="same-origin"/>
-               <xs:enumeration value="origin"/>
-               <xs:enumeration value="strict-origin"/>
-               <xs:enumeration value="origin-when-cross-origin"/>
-               <xs:enumeration value="strict-origin-when-cross-origin"/>
-               <xs:enumeration value="unsafe-url"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="feature-policy">
-      <xs:annotation>
-         <xs:documentation>Adds support for Feature Policy
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:feature-options.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="feature-options.attlist">
-      <xs:attribute name="policy-directives" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The security policy directive(s) for the Feature-Policy header.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="permissions-policy">
-      <xs:annotation>
-         <xs:documentation>Adds support for Permissions Policy
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:permissions-options.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="permissions-options.attlist">
-      <xs:attribute name="policy" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The policies for the Permissions-Policy header.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="cache-control">
-      <xs:annotation>
-         <xs:documentation>Adds Cache-Control no-cache, no-store, must-revalidate, Pragma no-cache, and Expires 0 for
-                every request
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:cache-control.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="cache-control.attlist">
-      <xs:attribute name="disabled" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>Specifies if Cache Control should be disabled. Default false.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="frame-options">
-      <xs:annotation>
-         <xs:documentation>Enable basic clickjacking support for newer browsers (IE8+), will set the X-Frame-Options
-                header.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:frame-options.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="frame-options.attlist">
-      <xs:attribute name="disabled" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>If disabled, the X-Frame-Options header will not be included. Default false.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="policy">
-         <xs:annotation>
-            <xs:documentation>Specify the policy to use for the X-Frame-Options-Header.
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="DENY"/>
-               <xs:enumeration value="SAMEORIGIN"/>
-               <xs:enumeration value="ALLOW-FROM"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-      <xs:attribute name="strategy">
-         <xs:annotation>
-            <xs:documentation>Specify the strategy to use when ALLOW-FROM is chosen.
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="static"/>
-               <xs:enumeration value="whitelist"/>
-               <xs:enumeration value="regexp"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-      <xs:attribute name="ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Defines a reference to a Spring bean Id.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="value" type="xs:string">
-         <xs:annotation>
-            <xs:documentation>Specify a value to use for the chosen strategy.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="from-parameter" type="xs:string">
-         <xs:annotation>
-            <xs:documentation>Specify the request parameter to use for the origin when using a 'whitelist' or 'regexp'
-                based strategy. Default is 'from'. Deprecated ALLOW-FROM is an obsolete directive that no
-                longer works in modern browsers. Instead use Content-Security-Policy with the &lt;a
-                href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors"&gt;frame-ancestors&lt;/a&gt;
-                directive.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="xss-protection">
-      <xs:annotation>
-         <xs:documentation>Enable basic XSS browser protection, supported by newer browsers (IE8+), will set the
-                X-XSS-Protection header.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:xss-protection.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="xss-protection.attlist">
-      <xs:attribute name="disabled" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>disable the X-XSS-Protection header. Default is 'false' meaning it is enabled.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="header-value">
-         <xs:annotation>
-            <xs:documentation>Specify the value for the X-Xss-Protection header. Defaults to "0".
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="0"/>
-               <xs:enumeration value="1"/>
-               <xs:enumeration value="1; mode=block"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="content-type-options">
-      <xs:annotation>
-         <xs:documentation>Add a X-Content-Type-Options header to the resopnse. Value is always 'nosniff'.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:content-type-options.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="content-type-options.attlist">
-      <xs:attribute name="disabled" type="xs:boolean">
-         <xs:annotation>
-            <xs:documentation>If disabled, the X-Content-Type-Options header will not be included. Default false.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="cross-origin-opener-policy">
-      <xs:annotation>
-         <xs:documentation>Adds support for Cross-Origin-Opener-Policy header
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:cross-origin-opener-policy-options.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="cross-origin-opener-policy-options.attlist">
-      <xs:attribute name="policy">
-         <xs:annotation>
-            <xs:documentation>The policies for the Cross-Origin-Opener-Policy header.
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="unsafe-none"/>
-               <xs:enumeration value="same-origin"/>
-               <xs:enumeration value="same-origin-allow-popups"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="cross-origin-embedder-policy">
-      <xs:annotation>
-         <xs:documentation>Adds support for Cross-Origin-Embedder-Policy header
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:cross-origin-embedder-policy-options.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="cross-origin-embedder-policy-options.attlist">
-      <xs:attribute name="policy">
-         <xs:annotation>
-            <xs:documentation>The policies for the Cross-Origin-Embedder-Policy header.
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="unsafe-none"/>
-               <xs:enumeration value="require-corp"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="cross-origin-resource-policy">
-      <xs:annotation>
-         <xs:documentation>Adds support for Cross-Origin-Resource-Policy header
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:cross-origin-resource-policy-options.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="cross-origin-resource-policy-options.attlist">
-      <xs:attribute name="policy">
-         <xs:annotation>
-            <xs:documentation>The policies for the Cross-Origin-Resource-Policy header.
-                </xs:documentation>
-         </xs:annotation>
-         <xs:simpleType>
-            <xs:restriction base="xs:token">
-               <xs:enumeration value="cross-origin"/>
-               <xs:enumeration value="same-origin"/>
-               <xs:enumeration value="same-site"/>
-            </xs:restriction>
-         </xs:simpleType>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="header">
-      <xs:annotation>
-         <xs:documentation>Add additional headers to the response.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:header.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="header.attlist">
-      <xs:attribute name="name" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The name of the header to add.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="value" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>The value for the header.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="ref" type="xs:token">
-         <xs:annotation>
-            <xs:documentation>Defines a reference to a Spring bean Id.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:element name="any-user-service" abstract="true"/>
-  <xs:element name="custom-filter">
-      <xs:annotation>
-         <xs:documentation>Used to indicate that a filter bean declaration should be incorporated into the security
-                filter chain.
-                </xs:documentation>
-      </xs:annotation>
-      <xs:complexType>
-         <xs:attributeGroup ref="security:custom-filter.attlist"/>
-      </xs:complexType>
-   </xs:element>
-  <xs:attributeGroup name="custom-filter.attlist">
-      <xs:attributeGroup ref="security:ref"/>
-      <xs:attribute name="after" type="security:named-security-filter">
-         <xs:annotation>
-            <xs:documentation>The filter immediately after which the custom-filter should be placed in the chain. This
-                feature will only be needed by advanced users who wish to mix their own filters into the
-                security filter chain and have some knowledge of the standard Spring Security filters. The
-                filter names map to specific Spring Security implementation filters.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="before" type="security:named-security-filter">
-         <xs:annotation>
-            <xs:documentation>The filter immediately before which the custom-filter should be placed in the chain
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="position" type="security:named-security-filter">
-         <xs:annotation>
-            <xs:documentation>The explicit position at which the custom-filter should be placed in the chain. Use if you
-                are replacing a standard filter.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="after">
-      <xs:attribute name="after" use="required" type="security:named-security-filter">
-         <xs:annotation>
-            <xs:documentation>The filter immediately after which the custom-filter should be placed in the chain. This
-                feature will only be needed by advanced users who wish to mix their own filters into the
-                security filter chain and have some knowledge of the standard Spring Security filters. The
-                filter names map to specific Spring Security implementation filters.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="before">
-      <xs:attribute name="before" use="required" type="security:named-security-filter">
-         <xs:annotation>
-            <xs:documentation>The filter immediately before which the custom-filter should be placed in the chain
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:attributeGroup name="position">
-      <xs:attribute name="position" use="required" type="security:named-security-filter">
-         <xs:annotation>
-            <xs:documentation>The explicit position at which the custom-filter should be placed in the chain. Use if you
-                are replacing a standard filter.
-                </xs:documentation>
-         </xs:annotation>
-      </xs:attribute>
-  </xs:attributeGroup>
-  <xs:simpleType name="named-security-filter">
-      <xs:restriction base="xs:token">
-         <xs:enumeration value="FIRST"/>
-         <xs:enumeration value="DISABLE_ENCODE_URL_FILTER"/>
-         <xs:enumeration value="FORCE_EAGER_SESSION_FILTER"/>
-         <xs:enumeration value="CHANNEL_FILTER"/>
-         <xs:enumeration value="SECURITY_CONTEXT_FILTER"/>
-         <xs:enumeration value="CONCURRENT_SESSION_FILTER"/>
-         <xs:enumeration value="WEB_ASYNC_MANAGER_FILTER"/>
-         <xs:enumeration value="HEADERS_FILTER"/>
-         <xs:enumeration value="CORS_FILTER"/>
-         <xs:enumeration value="SAML2_LOGOUT_REQUEST_FILTER"/>
-         <xs:enumeration value="SAML2_LOGOUT_RESPONSE_FILTER"/>
-         <xs:enumeration value="CSRF_FILTER"/>
-         <xs:enumeration value="SAML2_LOGOUT_FILTER"/>
-         <xs:enumeration value="LOGOUT_FILTER"/>
-         <xs:enumeration value="OAUTH2_AUTHORIZATION_REQUEST_FILTER"/>
-         <xs:enumeration value="SAML2_AUTHENTICATION_REQUEST_FILTER"/>
-         <xs:enumeration value="X509_FILTER"/>
-         <xs:enumeration value="PRE_AUTH_FILTER"/>
-         <xs:enumeration value="CAS_FILTER"/>
-         <xs:enumeration value="OAUTH2_LOGIN_FILTER"/>
-         <xs:enumeration value="SAML2_AUTHENTICATION_FILTER"/>
-         <xs:enumeration value="FORM_LOGIN_FILTER"/>
-         <xs:enumeration value="LOGIN_PAGE_FILTER"/>
-         <xs:enumeration value="LOGOUT_PAGE_FILTER"/>
-         <xs:enumeration value="DIGEST_AUTH_FILTER"/>
-         <xs:enumeration value="BEARER_TOKEN_AUTH_FILTER"/>
-         <xs:enumeration value="BASIC_AUTH_FILTER"/>
-         <xs:enumeration value="REQUEST_CACHE_FILTER"/>
-         <xs:enumeration value="SERVLET_API_SUPPORT_FILTER"/>
-         <xs:enumeration value="JAAS_API_SUPPORT_FILTER"/>
-         <xs:enumeration value="REMEMBER_ME_FILTER"/>
-         <xs:enumeration value="ANONYMOUS_FILTER"/>
-         <xs:enumeration value="OAUTH2_AUTHORIZATION_CODE_GRANT_FILTER"/>
-         <xs:enumeration value="WELL_KNOWN_CHANGE_PASSWORD_REDIRECT_FILTER"/>
-         <xs:enumeration value="SESSION_MANAGEMENT_FILTER"/>
-         <xs:enumeration value="EXCEPTION_TRANSLATION_FILTER"/>
-         <xs:enumeration value="FILTER_SECURITY_INTERCEPTOR"/>
-         <xs:enumeration value="SWITCH_USER_FILTER"/>
-         <xs:enumeration value="LAST"/>
-      </xs:restriction>
-  </xs:simpleType>
-</xs:schema>

+ 1 - 0
config/src/test/java/org/springframework/security/SpringSecurityCoreVersionSerializableTests.java

@@ -248,6 +248,7 @@ class SpringSecurityCoreVersionSerializableTests {
 
 	@ParameterizedTest
 	@MethodSource("getFilesToDeserialize")
+	@Disabled("The feature is only supported for versions >= 6.3")
 	void shouldBeAbleToDeserializeClassFromPreviousVersion(Path filePath) {
 		try (FileInputStream fileInputStream = new FileInputStream(filePath.toFile());
 				ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream)) {

+ 0 - 137
config/src/test/java/org/springframework/security/config/annotation/method/configuration/AuthorizationProxyConfigurationTests.java

@@ -1,137 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.config.annotation.method.configuration;
-
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import reactor.core.publisher.Mono;
-import reactor.test.StepVerifier;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.security.access.AccessDeniedException;
-import org.springframework.security.access.prepost.PostAuthorize;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.security.authentication.TestAuthentication;
-import org.springframework.security.authorization.AuthorizationProxyFactory;
-import org.springframework.security.config.test.SpringTestContext;
-import org.springframework.security.config.test.SpringTestContextExtension;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.ReactiveSecurityContextHolder;
-import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners;
-import org.springframework.security.test.context.support.WithMockUser;
-import org.springframework.test.context.junit.jupiter.SpringExtension;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-
-/**
- * Tests for {@link PrePostMethodSecurityConfiguration}.
- *
- * @author Evgeniy Cheban
- * @author Josh Cummings
- */
-@ExtendWith({ SpringExtension.class, SpringTestContextExtension.class })
-@SecurityTestExecutionListeners
-public class AuthorizationProxyConfigurationTests {
-
-	public final SpringTestContext spring = new SpringTestContext(this);
-
-	@Autowired
-	AuthorizationProxyFactory proxyFactory;
-
-	@WithMockUser
-	@Test
-	public void proxyWhenNotPreAuthorizedThenDenies() {
-		this.spring.register(DefaultsConfig.class).autowire();
-		Toaster toaster = (Toaster) this.proxyFactory.proxy(new Toaster());
-		assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(toaster::makeToast)
-			.withMessage("Access Denied");
-		assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(toaster::extractBread)
-			.withMessage("Access Denied");
-	}
-
-	@WithMockUser(roles = "ADMIN")
-	@Test
-	public void proxyWhenPreAuthorizedThenAllows() {
-		this.spring.register(DefaultsConfig.class).autowire();
-		Toaster toaster = (Toaster) this.proxyFactory.proxy(new Toaster());
-		toaster.makeToast();
-		assertThat(toaster.extractBread()).isEqualTo("yummy");
-	}
-
-	@Test
-	public void proxyReactiveWhenNotPreAuthorizedThenDenies() {
-		this.spring.register(ReactiveDefaultsConfig.class).autowire();
-		Toaster toaster = (Toaster) this.proxyFactory.proxy(new Toaster());
-		Authentication user = TestAuthentication.authenticatedUser();
-		StepVerifier
-			.create(toaster.reactiveMakeToast().contextWrite(ReactiveSecurityContextHolder.withAuthentication(user)))
-			.verifyError(AccessDeniedException.class);
-		StepVerifier
-			.create(toaster.reactiveExtractBread().contextWrite(ReactiveSecurityContextHolder.withAuthentication(user)))
-			.verifyError(AccessDeniedException.class);
-	}
-
-	@Test
-	public void proxyReactiveWhenPreAuthorizedThenAllows() {
-		this.spring.register(ReactiveDefaultsConfig.class).autowire();
-		Toaster toaster = (Toaster) this.proxyFactory.proxy(new Toaster());
-		Authentication admin = TestAuthentication.authenticatedAdmin();
-		StepVerifier
-			.create(toaster.reactiveMakeToast().contextWrite(ReactiveSecurityContextHolder.withAuthentication(admin)))
-			.expectNext()
-			.verifyComplete();
-	}
-
-	@EnableMethodSecurity
-	@Configuration
-	static class DefaultsConfig {
-
-	}
-
-	@EnableReactiveMethodSecurity
-	@Configuration
-	static class ReactiveDefaultsConfig {
-
-	}
-
-	static class Toaster {
-
-		@PreAuthorize("hasRole('ADMIN')")
-		void makeToast() {
-
-		}
-
-		@PostAuthorize("hasRole('ADMIN')")
-		String extractBread() {
-			return "yummy";
-		}
-
-		@PreAuthorize("hasRole('ADMIN')")
-		Mono<Void> reactiveMakeToast() {
-			return Mono.empty();
-		}
-
-		@PostAuthorize("hasRole('ADMIN')")
-		Mono<String> reactiveExtractBread() {
-			return Mono.just("yummy");
-		}
-
-	}
-
-}

+ 0 - 18
config/src/test/java/org/springframework/security/config/annotation/method/configuration/Authz.java

@@ -18,8 +18,6 @@ package org.springframework.security.config.annotation.method.configuration;
 
 import reactor.core.publisher.Mono;
 
-import org.springframework.security.authorization.AuthorizationDecision;
-import org.springframework.security.authorization.AuthorizationResult;
 import org.springframework.security.core.Authentication;
 import org.springframework.stereotype.Component;
 
@@ -47,20 +45,4 @@ public class Authz {
 		return message != null && message.contains(authentication.getName());
 	}
 
-	public AuthorizationResult checkResult(boolean result) {
-		return new AuthzResult(result);
-	}
-
-	public Mono<AuthorizationResult> checkReactiveResult(boolean result) {
-		return Mono.just(checkResult(result));
-	}
-
-	public static class AuthzResult extends AuthorizationDecision {
-
-		public AuthzResult(boolean granted) {
-			super(granted);
-		}
-
-	}
-
 }

+ 1 - 266
config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityService.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2022 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,42 +16,23 @@
 
 package org.springframework.security.config.annotation.method.configuration;
 
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
 import java.util.List;
 
 import jakarta.annotation.security.DenyAll;
 import jakarta.annotation.security.PermitAll;
 import jakarta.annotation.security.RolesAllowed;
-import org.aopalliance.intercept.MethodInvocation;
 
-import org.springframework.context.ApplicationContext;
-import org.springframework.core.annotation.AnnotationUtils;
-import org.springframework.expression.EvaluationContext;
-import org.springframework.expression.Expression;
 import org.springframework.security.access.annotation.Secured;
-import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
 import org.springframework.security.access.prepost.PostAuthorize;
 import org.springframework.security.access.prepost.PostFilter;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.access.prepost.PreFilter;
-import org.springframework.security.authorization.AuthorizationResult;
-import org.springframework.security.authorization.method.AuthorizeReturnObject;
-import org.springframework.security.authorization.method.HandleAuthorizationDenied;
-import org.springframework.security.authorization.method.MethodAuthorizationDeniedHandler;
-import org.springframework.security.authorization.method.MethodInvocationResult;
 import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.core.parameters.P;
-import org.springframework.util.StringUtils;
 
 /**
  * @author Rob Winch
  */
-@MethodSecurityService.Mask("classmask")
 public interface MethodSecurityService {
 
 	@PreAuthorize("denyAll")
@@ -72,9 +53,6 @@ public interface MethodSecurityService {
 	@RolesAllowed("ADMIN")
 	String jsr250RolesAllowed();
 
-	@RolesAllowed("USER")
-	String jsr250RolesAllowedUser();
-
 	@Secured({ "ROLE_USER", "RUN_AS_SUPER" })
 	Authentication runAs();
 
@@ -90,9 +68,6 @@ public interface MethodSecurityService {
 	@PreAuthorize("hasRole('ADMIN')")
 	void preAuthorizeAdmin();
 
-	@PreAuthorize("hasRole('USER')")
-	void preAuthorizeUser();
-
 	@PreAuthorize("hasPermission(#object,'read')")
 	String hasPermission(String object);
 
@@ -115,248 +90,8 @@ public interface MethodSecurityService {
 	@PostAuthorize("returnObject.size == 2")
 	List<String> manyAnnotations(List<String> array);
 
-	@PreFilter("filterObject != 'DropOnPreFilter'")
-	@PreAuthorize("#list.remove('DropOnPreAuthorize')")
-	@Secured("ROLE_SECURED")
-	@RolesAllowed("JSR250")
-	@PostAuthorize("#list.remove('DropOnPostAuthorize')")
-	@PostFilter("filterObject != 'DropOnPostFilter'")
-	List<String> allAnnotations(List<String> list);
-
 	@RequireUserRole
 	@RequireAdminRole
 	void repeatedAnnotations();
 
-	@PreAuthorize("hasRole('ADMIN')")
-	@HandleAuthorizationDenied(handlerClass = StarMaskingHandler.class)
-	String preAuthorizeGetCardNumberIfAdmin(String cardNumber);
-
-	@PreAuthorize("hasRole('ADMIN')")
-	@HandleAuthorizationDenied(handlerClass = StartMaskingHandlerChild.class)
-	String preAuthorizeWithHandlerChildGetCardNumberIfAdmin(String cardNumber);
-
-	@PreAuthorize("hasRole('ADMIN')")
-	@HandleAuthorizationDenied(handlerClass = StarMaskingHandler.class)
-	String preAuthorizeThrowAccessDeniedManually();
-
-	@PostAuthorize("hasRole('ADMIN')")
-	@HandleAuthorizationDenied(handlerClass = CardNumberMaskingPostProcessor.class)
-	String postAuthorizeGetCardNumberIfAdmin(String cardNumber);
-
-	@PostAuthorize("hasRole('ADMIN')")
-	@HandleAuthorizationDenied(handlerClass = PostMaskingPostProcessor.class)
-	String postAuthorizeThrowAccessDeniedManually();
-
-	@PreAuthorize("denyAll()")
-	@Mask("methodmask")
-	@HandleAuthorizationDenied(handlerClass = MaskAnnotationHandler.class)
-	String preAuthorizeDeniedMethodWithMaskAnnotation();
-
-	@PreAuthorize("denyAll()")
-	@HandleAuthorizationDenied(handlerClass = MaskAnnotationHandler.class)
-	String preAuthorizeDeniedMethodWithNoMaskAnnotation();
-
-	@NullDenied(role = "ADMIN")
-	String postAuthorizeDeniedWithNullDenied();
-
-	@PostAuthorize("denyAll()")
-	@Mask("methodmask")
-	@HandleAuthorizationDenied(handlerClass = MaskAnnotationPostProcessor.class)
-	String postAuthorizeDeniedMethodWithMaskAnnotation();
-
-	@PostAuthorize("denyAll()")
-	@HandleAuthorizationDenied(handlerClass = MaskAnnotationPostProcessor.class)
-	String postAuthorizeDeniedMethodWithNoMaskAnnotation();
-
-	@PreAuthorize("hasRole('ADMIN')")
-	@Mask(expression = "@myMasker.getMask()")
-	@HandleAuthorizationDenied(handlerClass = MaskAnnotationHandler.class)
-	String preAuthorizeWithMaskAnnotationUsingBean();
-
-	@PostAuthorize("hasRole('ADMIN')")
-	@Mask(expression = "@myMasker.getMask(returnObject)")
-	@HandleAuthorizationDenied(handlerClass = MaskAnnotationPostProcessor.class)
-	String postAuthorizeWithMaskAnnotationUsingBean();
-
-	@AuthorizeReturnObject
-	UserRecordWithEmailProtected getUserRecordWithEmailProtected();
-
-	@PreAuthorize("hasRole('ADMIN')")
-	@HandleAuthorizationDenied(handlerClass = UserFallbackDeniedHandler.class)
-	UserRecordWithEmailProtected getUserWithFallbackWhenUnauthorized();
-
-	@PreAuthorize("@authz.checkResult(#result)")
-	@PostAuthorize("@authz.checkResult(!#result)")
-	@HandleAuthorizationDenied(handlerClass = MethodAuthorizationDeniedHandler.class)
-	String checkCustomResult(boolean result);
-
-	class StarMaskingHandler implements MethodAuthorizationDeniedHandler {
-
-		@Override
-		public Object handleDeniedInvocation(MethodInvocation methodInvocation, AuthorizationResult result) {
-			return "***";
-		}
-
-	}
-
-	class StartMaskingHandlerChild extends StarMaskingHandler {
-
-		@Override
-		public Object handleDeniedInvocation(MethodInvocation methodInvocation, AuthorizationResult result) {
-			return super.handleDeniedInvocation(methodInvocation, result) + "-child";
-		}
-
-	}
-
-	class MaskAnnotationHandler implements MethodAuthorizationDeniedHandler {
-
-		MaskValueResolver maskValueResolver;
-
-		MaskAnnotationHandler(ApplicationContext context) {
-			this.maskValueResolver = new MaskValueResolver(context);
-		}
-
-		public Object handle(MethodInvocation methodInvocation, AuthorizationResult result) {
-			Mask mask = AnnotationUtils.getAnnotation(methodInvocation.getMethod(), Mask.class);
-			if (mask == null) {
-				mask = AnnotationUtils.getAnnotation(methodInvocation.getMethod().getDeclaringClass(), Mask.class);
-			}
-			return this.maskValueResolver.resolveValue(mask, methodInvocation, null);
-		}
-
-		@Override
-		public Object handleDeniedInvocation(MethodInvocation methodInvocation,
-				AuthorizationResult authorizationResult) {
-			return handle(methodInvocation, authorizationResult);
-		}
-
-	}
-
-	class MaskAnnotationPostProcessor implements MethodAuthorizationDeniedHandler {
-
-		MaskValueResolver maskValueResolver;
-
-		MaskAnnotationPostProcessor(ApplicationContext context) {
-			this.maskValueResolver = new MaskValueResolver(context);
-		}
-
-		@Override
-		public Object handleDeniedInvocation(MethodInvocation mi, AuthorizationResult authorizationResult) {
-			Mask mask = AnnotationUtils.getAnnotation(mi.getMethod(), Mask.class);
-			if (mask == null) {
-				mask = AnnotationUtils.getAnnotation(mi.getMethod().getDeclaringClass(), Mask.class);
-			}
-			return this.maskValueResolver.resolveValue(mask, mi, null);
-		}
-
-		@Override
-		public Object handleDeniedInvocationResult(MethodInvocationResult methodInvocationResult,
-				AuthorizationResult authorizationResult) {
-			MethodInvocation mi = methodInvocationResult.getMethodInvocation();
-			Mask mask = AnnotationUtils.getAnnotation(mi.getMethod(), Mask.class);
-			if (mask == null) {
-				mask = AnnotationUtils.getAnnotation(mi.getMethod().getDeclaringClass(), Mask.class);
-			}
-			return this.maskValueResolver.resolveValue(mask, mi, methodInvocationResult.getResult());
-		}
-
-	}
-
-	class MaskValueResolver {
-
-		DefaultMethodSecurityExpressionHandler expressionHandler;
-
-		MaskValueResolver(ApplicationContext context) {
-			this.expressionHandler = new DefaultMethodSecurityExpressionHandler();
-			this.expressionHandler.setApplicationContext(context);
-		}
-
-		String resolveValue(Mask mask, MethodInvocation mi, Object returnObject) {
-			if (StringUtils.hasText(mask.value())) {
-				return mask.value();
-			}
-			Expression expression = this.expressionHandler.getExpressionParser().parseExpression(mask.expression());
-			EvaluationContext evaluationContext = this.expressionHandler
-				.createEvaluationContext(() -> SecurityContextHolder.getContext().getAuthentication(), mi);
-			if (returnObject != null) {
-				this.expressionHandler.setReturnObject(returnObject, evaluationContext);
-			}
-			return expression.getValue(evaluationContext, String.class);
-		}
-
-	}
-
-	class PostMaskingPostProcessor implements MethodAuthorizationDeniedHandler {
-
-		@Override
-		public Object handleDeniedInvocation(MethodInvocation methodInvocation,
-				AuthorizationResult authorizationResult) {
-			return "***";
-		}
-
-	}
-
-	class CardNumberMaskingPostProcessor implements MethodAuthorizationDeniedHandler {
-
-		static String MASK = "****-****-****-";
-
-		@Override
-		public Object handleDeniedInvocation(MethodInvocation methodInvocation,
-				AuthorizationResult authorizationResult) {
-			return "***";
-		}
-
-		@Override
-		public Object handleDeniedInvocationResult(MethodInvocationResult contextObject, AuthorizationResult result) {
-			String cardNumber = (String) contextObject.getResult();
-			return MASK + cardNumber.substring(cardNumber.length() - 4);
-		}
-
-	}
-
-	class NullPostProcessor implements MethodAuthorizationDeniedHandler {
-
-		@Override
-		public Object handleDeniedInvocation(MethodInvocation methodInvocation,
-				AuthorizationResult authorizationResult) {
-			return null;
-		}
-
-	}
-
-	@Target({ ElementType.METHOD, ElementType.TYPE })
-	@Retention(RetentionPolicy.RUNTIME)
-	@Inherited
-	@interface Mask {
-
-		String value() default "";
-
-		String expression() default "";
-
-	}
-
-	@Target({ ElementType.METHOD, ElementType.TYPE })
-	@Retention(RetentionPolicy.RUNTIME)
-	@Inherited
-	@PostAuthorize("hasRole('{role}')")
-	@HandleAuthorizationDenied(handlerClass = NullPostProcessor.class)
-	@interface NullDenied {
-
-		String role();
-
-	}
-
-	class UserFallbackDeniedHandler implements MethodAuthorizationDeniedHandler {
-
-		private static final UserRecordWithEmailProtected FALLBACK = new UserRecordWithEmailProtected("Protected",
-				"Protected");
-
-		@Override
-		public Object handleDeniedInvocation(MethodInvocation methodInvocation,
-				AuthorizationResult authorizationResult) {
-			return FALLBACK;
-		}
-
-	}
-
 }

+ 0 - 10
config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityServiceConfig.java

@@ -28,14 +28,4 @@ public class MethodSecurityServiceConfig {
 		return new MethodSecurityServiceImpl();
 	}
 
-	@Bean
-	ReactiveMethodSecurityService reactiveService() {
-		return new ReactiveMethodSecurityServiceImpl();
-	}
-
-	@Bean
-	Authz authz() {
-		return new Authz();
-	}
-
 }

+ 1 - 92
config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityServiceImpl.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2022 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,8 +18,6 @@ package org.springframework.security.config.annotation.method.configuration;
 
 import java.util.List;
 
-import org.springframework.security.authorization.AuthorizationDecision;
-import org.springframework.security.authorization.AuthorizationDeniedException;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.context.SecurityContextHolder;
 
@@ -58,11 +56,6 @@ public class MethodSecurityServiceImpl implements MethodSecurityService {
 		return null;
 	}
 
-	@Override
-	public String jsr250RolesAllowedUser() {
-		return null;
-	}
-
 	@Override
 	public Authentication runAs() {
 		return SecurityContextHolder.getContext().getAuthentication();
@@ -80,10 +73,6 @@ public class MethodSecurityServiceImpl implements MethodSecurityService {
 	public void preAuthorizeAdmin() {
 	}
 
-	@Override
-	public void preAuthorizeUser() {
-	}
-
 	@Override
 	public String preAuthorizePermitAll() {
 		return null;
@@ -119,88 +108,8 @@ public class MethodSecurityServiceImpl implements MethodSecurityService {
 		return object;
 	}
 
-	@Override
-	public List<String> allAnnotations(List<String> list) {
-		return null;
-	}
-
 	@Override
 	public void repeatedAnnotations() {
 	}
 
-	@Override
-	public String postAuthorizeGetCardNumberIfAdmin(String cardNumber) {
-		return cardNumber;
-	}
-
-	@Override
-	public String preAuthorizeGetCardNumberIfAdmin(String cardNumber) {
-		return cardNumber;
-	}
-
-	@Override
-	public String preAuthorizeWithHandlerChildGetCardNumberIfAdmin(String cardNumber) {
-		return cardNumber;
-	}
-
-	@Override
-	public String preAuthorizeThrowAccessDeniedManually() {
-		throw new AuthorizationDeniedException("Access Denied", new AuthorizationDecision(false));
-	}
-
-	@Override
-	public String postAuthorizeThrowAccessDeniedManually() {
-		throw new AuthorizationDeniedException("Access Denied", new AuthorizationDecision(false));
-	}
-
-	@Override
-	public String preAuthorizeDeniedMethodWithMaskAnnotation() {
-		return "ok";
-	}
-
-	@Override
-	public String preAuthorizeDeniedMethodWithNoMaskAnnotation() {
-		return "ok";
-	}
-
-	@Override
-	public String postAuthorizeDeniedWithNullDenied() {
-		return "ok";
-	}
-
-	@Override
-	public String postAuthorizeDeniedMethodWithMaskAnnotation() {
-		return "ok";
-	}
-
-	@Override
-	public String postAuthorizeDeniedMethodWithNoMaskAnnotation() {
-		return "ok";
-	}
-
-	@Override
-	public String preAuthorizeWithMaskAnnotationUsingBean() {
-		return "ok";
-	}
-
-	@Override
-	public String postAuthorizeWithMaskAnnotationUsingBean() {
-		return "ok";
-	}
-
-	@Override
-	public UserRecordWithEmailProtected getUserRecordWithEmailProtected() {
-		return new UserRecordWithEmailProtected("username", "useremail@example.com");
-	}
-
-	@Override
-	public UserRecordWithEmailProtected getUserWithFallbackWhenUnauthorized() {
-		return new UserRecordWithEmailProtected("username", "useremail@example.com");
-	}
-
-	@Override
-	public String checkCustomResult(boolean result) {
-		return "ok";
-	}
-
 }

+ 0 - 29
config/src/test/java/org/springframework/security/config/annotation/method/configuration/MyMasker.java

@@ -1,29 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.config.annotation.method.configuration;
-
-public class MyMasker {
-
-	public String getMask(String value) {
-		return value + "-masked";
-	}
-
-	public String getMask() {
-		return "mask";
-	}
-
-}

+ 2 - 855
config/src/test/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfigurationTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2023 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,14 +17,9 @@
 package org.springframework.security.config.annotation.method.configuration;
 
 import java.io.Serializable;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.Consumer;
 import java.util.function.Supplier;
 
@@ -41,7 +36,6 @@ import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.context.annotation.AdviceMode;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Import;
 import org.springframework.context.annotation.Role;
 import org.springframework.core.annotation.AnnotationConfigurationException;
 import org.springframework.security.access.AccessDeniedException;
@@ -52,24 +46,12 @@ import org.springframework.security.access.annotation.ExpressionProtectedBusines
 import org.springframework.security.access.annotation.Jsr250BusinessServiceImpl;
 import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
 import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
-import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
-import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
-import org.springframework.security.access.prepost.PostAuthorize;
-import org.springframework.security.access.prepost.PostFilter;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.security.access.prepost.PreFilter;
 import org.springframework.security.authorization.AuthorizationDecision;
 import org.springframework.security.authorization.AuthorizationEventPublisher;
 import org.springframework.security.authorization.AuthorizationManager;
-import org.springframework.security.authorization.method.AuthorizationAdvisorProxyFactory;
-import org.springframework.security.authorization.method.AuthorizationAdvisorProxyFactory.TargetVisitor;
 import org.springframework.security.authorization.method.AuthorizationInterceptorsOrder;
 import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
-import org.springframework.security.authorization.method.AuthorizeReturnObject;
-import org.springframework.security.authorization.method.MethodAuthorizationDeniedHandler;
 import org.springframework.security.authorization.method.MethodInvocationResult;
-import org.springframework.security.authorization.method.PrePostTemplateDefaults;
-import org.springframework.security.config.Customizer;
 import org.springframework.security.config.annotation.SecurityContextChangedListenerConfig;
 import org.springframework.security.config.core.GrantedAuthorityDefaults;
 import org.springframework.security.config.test.SpringTestContext;
@@ -88,12 +70,9 @@ import org.springframework.web.context.support.AnnotationConfigWebApplicationCon
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-import static org.assertj.core.api.Assertions.assertThatNoException;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
 /**
@@ -460,6 +439,7 @@ public class PrePostMethodSecurityConfigurationTests {
 		assertThat(this.spring.getContext().containsBean("annotationSecurityAspect$0")).isFalse();
 	}
 
+	// gh-13572
 	@Test
 	public void configureWhenBeanOverridingDisallowedThenWorks() {
 		this.spring.register(MethodSecurityServiceConfig.class, BusinessServiceConfig.class)
@@ -467,506 +447,10 @@ public class PrePostMethodSecurityConfigurationTests {
 			.autowire();
 	}
 
-	@WithMockUser(roles = "ADMIN")
-	@Test
-	public void methodSecurityAdminWhenRoleHierarchyBeanAvailableThenUses() {
-		this.spring.register(RoleHierarchyConfig.class, MethodSecurityServiceConfig.class).autowire();
-		this.methodSecurityService.preAuthorizeUser();
-		this.methodSecurityService.securedUser();
-		this.methodSecurityService.jsr250RolesAllowedUser();
-	}
-
-	@WithMockUser
-	@Test
-	public void methodSecurityUserWhenRoleHierarchyBeanAvailableThenUses() {
-		this.spring.register(RoleHierarchyConfig.class, MethodSecurityServiceConfig.class).autowire();
-		this.methodSecurityService.preAuthorizeUser();
-		this.methodSecurityService.securedUser();
-		this.methodSecurityService.jsr250RolesAllowedUser();
-	}
-
-	@WithMockUser(roles = "ADMIN")
-	@Test
-	public void methodSecurityAdminWhenAuthorizationEventPublisherBeanAvailableThenUses() {
-		this.spring
-			.register(RoleHierarchyConfig.class, MethodSecurityServiceConfig.class,
-					AuthorizationEventPublisherConfig.class)
-			.autowire();
-		this.methodSecurityService.preAuthorizeUser();
-		this.methodSecurityService.securedUser();
-		this.methodSecurityService.jsr250RolesAllowedUser();
-	}
-
-	@WithMockUser
-	@Test
-	public void methodSecurityUserWhenAuthorizationEventPublisherBeanAvailableThenUses() {
-		this.spring
-			.register(RoleHierarchyConfig.class, MethodSecurityServiceConfig.class,
-					AuthorizationEventPublisherConfig.class)
-			.autowire();
-		this.methodSecurityService.preAuthorizeUser();
-		this.methodSecurityService.securedUser();
-		this.methodSecurityService.jsr250RolesAllowedUser();
-	}
-
-	@Test
-	public void allAnnotationsWhenAdviceBeforeOffsetPreFilterThenReturnsFilteredList() {
-		this.spring.register(ReturnBeforeOffsetPreFilterConfig.class).autowire();
-		List<String> list = Arrays.asList("DropOnPreFilter", "DropOnPreAuthorize", "DropOnPostAuthorize",
-				"DropOnPostFilter", "DoNotDrop");
-		List<String> filtered = this.methodSecurityService.allAnnotations(new ArrayList<>(list));
-		assertThat(filtered).hasSize(5);
-		assertThat(filtered).containsExactly("DropOnPreFilter", "DropOnPreAuthorize", "DropOnPostAuthorize",
-				"DropOnPostFilter", "DoNotDrop");
-	}
-
-	@Test
-	public void allAnnotationsWhenAdviceBeforeOffsetPreAuthorizeThenReturnsFilteredList() {
-		this.spring.register(ReturnBeforeOffsetPreAuthorizeConfig.class).autowire();
-		List<String> list = Arrays.asList("DropOnPreFilter", "DropOnPreAuthorize", "DropOnPostAuthorize",
-				"DropOnPostFilter", "DoNotDrop");
-		List<String> filtered = this.methodSecurityService.allAnnotations(new ArrayList<>(list));
-		assertThat(filtered).hasSize(4);
-		assertThat(filtered).containsExactly("DropOnPreAuthorize", "DropOnPostAuthorize", "DropOnPostFilter",
-				"DoNotDrop");
-	}
-
-	@Test
-	public void allAnnotationsWhenAdviceBeforeOffsetSecuredThenReturnsFilteredList() {
-		this.spring.register(ReturnBeforeOffsetSecuredConfig.class).autowire();
-		List<String> list = Arrays.asList("DropOnPreFilter", "DropOnPreAuthorize", "DropOnPostAuthorize",
-				"DropOnPostFilter", "DoNotDrop");
-		List<String> filtered = this.methodSecurityService.allAnnotations(new ArrayList<>(list));
-		assertThat(filtered).hasSize(3);
-		assertThat(filtered).containsExactly("DropOnPostAuthorize", "DropOnPostFilter", "DoNotDrop");
-	}
-
-	@Test
-	@WithMockUser
-	public void allAnnotationsWhenAdviceBeforeOffsetJsr250WithInsufficientRolesThenFails() {
-		this.spring.register(ReturnBeforeOffsetJsr250Config.class).autowire();
-		List<String> list = Arrays.asList("DropOnPreFilter", "DropOnPreAuthorize", "DropOnPostAuthorize",
-				"DropOnPostFilter", "DoNotDrop");
-		assertThatExceptionOfType(AccessDeniedException.class)
-			.isThrownBy(() -> this.methodSecurityService.allAnnotations(new ArrayList<>(list)));
-	}
-
-	@Test
-	@WithMockUser(roles = "SECURED")
-	public void allAnnotationsWhenAdviceBeforeOffsetJsr250ThenReturnsFilteredList() {
-		this.spring.register(ReturnBeforeOffsetJsr250Config.class).autowire();
-		List<String> list = Arrays.asList("DropOnPreFilter", "DropOnPreAuthorize", "DropOnPostAuthorize",
-				"DropOnPostFilter", "DoNotDrop");
-		List<String> filtered = this.methodSecurityService.allAnnotations(new ArrayList<>(list));
-		assertThat(filtered).hasSize(3);
-		assertThat(filtered).containsExactly("DropOnPostAuthorize", "DropOnPostFilter", "DoNotDrop");
-	}
-
-	@Test
-	@WithMockUser(roles = { "SECURED" })
-	public void allAnnotationsWhenAdviceBeforeOffsetPostAuthorizeWithInsufficientRolesThenFails() {
-		this.spring.register(ReturnBeforeOffsetPostAuthorizeConfig.class).autowire();
-		List<String> list = Arrays.asList("DropOnPreFilter", "DropOnPreAuthorize", "DropOnPostAuthorize",
-				"DropOnPostFilter", "DoNotDrop");
-		assertThatExceptionOfType(AccessDeniedException.class)
-			.isThrownBy(() -> this.methodSecurityService.allAnnotations(new ArrayList<>(list)));
-	}
-
-	@Test
-	@WithMockUser(roles = { "SECURED", "JSR250" })
-	public void allAnnotationsWhenAdviceBeforeOffsetPostAuthorizeThenReturnsFilteredList() {
-		this.spring.register(ReturnBeforeOffsetPostAuthorizeConfig.class).autowire();
-		List<String> list = Arrays.asList("DropOnPreFilter", "DropOnPreAuthorize", "DropOnPostAuthorize",
-				"DropOnPostFilter", "DoNotDrop");
-		List<String> filtered = this.methodSecurityService.allAnnotations(new ArrayList<>(list));
-		assertThat(filtered).hasSize(3);
-		assertThat(filtered).containsExactly("DropOnPostAuthorize", "DropOnPostFilter", "DoNotDrop");
-	}
-
-	@Test
-	@WithMockUser(roles = { "SECURED", "JSR250" })
-	public void allAnnotationsWhenAdviceBeforeOffsetPostFilterThenReturnsFilteredList() {
-		this.spring.register(ReturnBeforeOffsetPostFilterConfig.class).autowire();
-		List<String> list = Arrays.asList("DropOnPreFilter", "DropOnPreAuthorize", "DropOnPostAuthorize",
-				"DropOnPostFilter", "DoNotDrop");
-		List<String> filtered = this.methodSecurityService.allAnnotations(new ArrayList<>(list));
-		assertThat(filtered).hasSize(2);
-		assertThat(filtered).containsExactly("DropOnPostFilter", "DoNotDrop");
-	}
-
-	@Test
-	@WithMockUser(roles = { "SECURED", "JSR250" })
-	public void allAnnotationsWhenAdviceAfterAllOffsetThenReturnsFilteredList() {
-		this.spring.register(ReturnAfterAllOffsetConfig.class).autowire();
-		List<String> list = Arrays.asList("DropOnPreFilter", "DropOnPreAuthorize", "DropOnPostAuthorize",
-				"DropOnPostFilter", "DoNotDrop");
-		List<String> filtered = this.methodSecurityService.allAnnotations(new ArrayList<>(list));
-		assertThat(filtered).hasSize(1);
-		assertThat(filtered).containsExactly("DoNotDrop");
-	}
-
-	@Test
-	@WithMockUser
-	public void methodeWhenParameterizedPreAuthorizeMetaAnnotationThenPasses() {
-		this.spring.register(MetaAnnotationPlaceholderConfig.class).autowire();
-		MetaAnnotationService service = this.spring.getContext().getBean(MetaAnnotationService.class);
-		assertThat(service.hasRole("USER")).isTrue();
-	}
-
-	@Test
-	@WithMockUser
-	public void methodRoleWhenPreAuthorizeMetaAnnotationHardcodedParameterThenPasses() {
-		this.spring.register(MetaAnnotationPlaceholderConfig.class).autowire();
-		MetaAnnotationService service = this.spring.getContext().getBean(MetaAnnotationService.class);
-		assertThat(service.hasUserRole()).isTrue();
-	}
-
-	@Test
-	public void methodWhenParameterizedAnnotationThenFails() {
-		this.spring.register(MetaAnnotationPlaceholderConfig.class).autowire();
-		MetaAnnotationService service = this.spring.getContext().getBean(MetaAnnotationService.class);
-		assertThatExceptionOfType(IllegalArgumentException.class)
-			.isThrownBy(service::placeholdersOnlyResolvedByMetaAnnotations);
-	}
-
-	@Test
-	@WithMockUser(authorities = "SCOPE_message:read")
-	public void methodWhenMultiplePlaceholdersHasAuthorityThenPasses() {
-		this.spring.register(MetaAnnotationPlaceholderConfig.class).autowire();
-		MetaAnnotationService service = this.spring.getContext().getBean(MetaAnnotationService.class);
-		assertThat(service.readMessage()).isEqualTo("message");
-	}
-
-	@Test
-	@WithMockUser(roles = "ADMIN")
-	public void methodWhenMultiplePlaceholdersHasRoleThenPasses() {
-		this.spring.register(MetaAnnotationPlaceholderConfig.class).autowire();
-		MetaAnnotationService service = this.spring.getContext().getBean(MetaAnnotationService.class);
-		assertThat(service.readMessage()).isEqualTo("message");
-	}
-
-	@Test
-	@WithMockUser
-	public void methodWhenPostAuthorizeMetaAnnotationThenAuthorizes() {
-		this.spring.register(MetaAnnotationPlaceholderConfig.class).autowire();
-		MetaAnnotationService service = this.spring.getContext().getBean(MetaAnnotationService.class);
-		service.startsWithDave("daveMatthews");
-		assertThatExceptionOfType(AccessDeniedException.class)
-			.isThrownBy(() -> service.startsWithDave("jenniferHarper"));
-	}
-
-	@Test
-	@WithMockUser
-	public void methodWhenPreFilterMetaAnnotationThenFilters() {
-		this.spring.register(MetaAnnotationPlaceholderConfig.class).autowire();
-		MetaAnnotationService service = this.spring.getContext().getBean(MetaAnnotationService.class);
-		assertThat(service.parametersContainDave(new ArrayList<>(List.of("dave", "carla", "vanessa", "paul"))))
-			.containsExactly("dave");
-	}
-
-	@Test
-	@WithMockUser
-	public void methodWhenPostFilterMetaAnnotationThenFilters() {
-		this.spring.register(MetaAnnotationPlaceholderConfig.class).autowire();
-		MetaAnnotationService service = this.spring.getContext().getBean(MetaAnnotationService.class);
-		assertThat(service.resultsContainDave(new ArrayList<>(List.of("dave", "carla", "vanessa", "paul"))))
-			.containsExactly("dave");
-	}
-
-	@Test
-	@WithMockUser(authorities = "airplane:read")
-	public void findByIdWhenAuthorizedResultThenAuthorizes() {
-		this.spring.register(AuthorizeResultConfig.class).autowire();
-		FlightRepository flights = this.spring.getContext().getBean(FlightRepository.class);
-		Flight flight = flights.findById("1");
-		assertThatNoException().isThrownBy(flight::getAltitude);
-		assertThatNoException().isThrownBy(flight::getSeats);
-	}
-
-	@Test
-	@WithMockUser(authorities = "seating:read")
-	public void findByIdWhenUnauthorizedResultThenDenies() {
-		this.spring.register(AuthorizeResultConfig.class).autowire();
-		FlightRepository flights = this.spring.getContext().getBean(FlightRepository.class);
-		Flight flight = flights.findById("1");
-		assertThatNoException().isThrownBy(flight::getSeats);
-		assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(flight::getAltitude);
-	}
-
-	@Test
-	@WithMockUser(authorities = "seating:read")
-	public void findAllWhenUnauthorizedResultThenDenies() {
-		this.spring.register(AuthorizeResultConfig.class).autowire();
-		FlightRepository flights = this.spring.getContext().getBean(FlightRepository.class);
-		flights.findAll().forEachRemaining((flight) -> {
-			assertThatNoException().isThrownBy(flight::getSeats);
-			assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(flight::getAltitude);
-		});
-	}
-
-	@Test
-	public void removeWhenAuthorizedResultThenRemoves() {
-		this.spring.register(AuthorizeResultConfig.class).autowire();
-		FlightRepository flights = this.spring.getContext().getBean(FlightRepository.class);
-		flights.remove("1");
-	}
-
-	@Test
-	@WithMockUser(authorities = "airplane:read")
-	public void findAllWhenPostFilterThenFilters() {
-		this.spring.register(AuthorizeResultConfig.class).autowire();
-		FlightRepository flights = this.spring.getContext().getBean(FlightRepository.class);
-		flights.findAll()
-			.forEachRemaining((flight) -> assertThat(flight.getPassengers()).extracting(Passenger::getName)
-				.doesNotContain("Kevin Mitnick"));
-	}
-
-	@Test
-	@WithMockUser(authorities = "airplane:read")
-	public void findAllWhenPreFilterThenFilters() {
-		this.spring.register(AuthorizeResultConfig.class).autowire();
-		FlightRepository flights = this.spring.getContext().getBean(FlightRepository.class);
-		flights.findAll().forEachRemaining((flight) -> {
-			flight.board(new ArrayList<>(List.of("John")));
-			assertThat(flight.getPassengers()).extracting(Passenger::getName).doesNotContain("John");
-			flight.board(new ArrayList<>(List.of("John Doe")));
-			assertThat(flight.getPassengers()).extracting(Passenger::getName).contains("John Doe");
-		});
-	}
-
-	@Test
-	@WithMockUser(authorities = "seating:read")
-	public void findAllWhenNestedPreAuthorizeThenAuthorizes() {
-		this.spring.register(AuthorizeResultConfig.class).autowire();
-		FlightRepository flights = this.spring.getContext().getBean(FlightRepository.class);
-		flights.findAll().forEachRemaining((flight) -> {
-			List<Passenger> passengers = flight.getPassengers();
-			passengers.forEach((passenger) -> assertThatExceptionOfType(AccessDeniedException.class)
-				.isThrownBy(passenger::getName));
-		});
-	}
-
-	@Test
-	@WithMockUser
-	void getCardNumberWhenPostAuthorizeAndNotAdminThenReturnMasked() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class,
-					MethodSecurityService.CardNumberMaskingPostProcessor.class)
-			.autowire();
-		MethodSecurityService service = this.spring.getContext().getBean(MethodSecurityService.class);
-		String cardNumber = service.postAuthorizeGetCardNumberIfAdmin("4444-3333-2222-1111");
-		assertThat(cardNumber).isEqualTo("****-****-****-1111");
-	}
-
-	@Test
-	@WithMockUser
-	void getCardNumberWhenPreAuthorizeAndNotAdminThenReturnMasked() {
-		this.spring.register(MethodSecurityServiceEnabledConfig.class, MethodSecurityService.StarMaskingHandler.class)
-			.autowire();
-		MethodSecurityService service = this.spring.getContext().getBean(MethodSecurityService.class);
-		String cardNumber = service.preAuthorizeGetCardNumberIfAdmin("4444-3333-2222-1111");
-		assertThat(cardNumber).isEqualTo("***");
-	}
-
-	@Test
-	@WithMockUser
-	void getCardNumberWhenPreAuthorizeAndNotAdminAndChildHandlerThenResolveCorrectHandlerAndReturnMasked() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class, MethodSecurityService.StarMaskingHandler.class,
-					MethodSecurityService.StartMaskingHandlerChild.class)
-			.autowire();
-		MethodSecurityService service = this.spring.getContext().getBean(MethodSecurityService.class);
-		String cardNumber = service.preAuthorizeWithHandlerChildGetCardNumberIfAdmin("4444-3333-2222-1111");
-		assertThat(cardNumber).isEqualTo("***-child");
-	}
-
-	@Test
-	@WithMockUser(roles = "ADMIN")
-	void preAuthorizeWhenHandlerAndAccessDeniedNotThrownFromPreAuthorizeThenHandled() {
-		this.spring.register(MethodSecurityServiceEnabledConfig.class, MethodSecurityService.StarMaskingHandler.class)
-			.autowire();
-		MethodSecurityService service = this.spring.getContext().getBean(MethodSecurityService.class);
-		assertThat(service.preAuthorizeThrowAccessDeniedManually()).isEqualTo("***");
-	}
-
-	@Test
-	@WithMockUser(roles = "ADMIN")
-	void postAuthorizeWhenHandlerAndAccessDeniedNotThrownFromPostAuthorizeThenHandled() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class, MethodSecurityService.PostMaskingPostProcessor.class)
-			.autowire();
-		MethodSecurityService service = this.spring.getContext().getBean(MethodSecurityService.class);
-		assertThat(service.postAuthorizeThrowAccessDeniedManually()).isEqualTo("***");
-	}
-
-	@Test
-	@WithMockUser
-	void preAuthorizeWhenDeniedAndHandlerWithCustomAnnotationThenHandlerCanUseMaskFromOtherAnnotation() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class, MethodSecurityService.MaskAnnotationHandler.class)
-			.autowire();
-		MethodSecurityService service = this.spring.getContext().getBean(MethodSecurityService.class);
-		String result = service.preAuthorizeDeniedMethodWithMaskAnnotation();
-		assertThat(result).isEqualTo("methodmask");
-	}
-
-	@Test
-	@WithMockUser
-	void preAuthorizeWhenDeniedAndHandlerWithCustomAnnotationInClassThenHandlerCanUseMaskFromOtherAnnotation() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class, MethodSecurityService.MaskAnnotationHandler.class)
-			.autowire();
-		MethodSecurityService service = this.spring.getContext().getBean(MethodSecurityService.class);
-		String result = service.preAuthorizeDeniedMethodWithNoMaskAnnotation();
-		assertThat(result).isEqualTo("classmask");
-	}
-
-	@Test
-	@WithMockUser
-	void postAuthorizeWhenNullDeniedMetaAnnotationThanWorks() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class, MetaAnnotationPlaceholderConfig.class,
-					MethodSecurityService.NullPostProcessor.class)
-			.autowire();
-		MethodSecurityService service = this.spring.getContext().getBean(MethodSecurityService.class);
-		String result = service.postAuthorizeDeniedWithNullDenied();
-		assertThat(result).isNull();
-	}
-
-	@Test
-	@WithMockUser
-	void postAuthorizeWhenDeniedAndHandlerWithCustomAnnotationThenHandlerCanUseMaskFromOtherAnnotation() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class, MethodSecurityService.MaskAnnotationPostProcessor.class)
-			.autowire();
-		MethodSecurityService service = this.spring.getContext().getBean(MethodSecurityService.class);
-		String result = service.postAuthorizeDeniedMethodWithMaskAnnotation();
-		assertThat(result).isEqualTo("methodmask");
-	}
-
-	@Test
-	@WithMockUser
-	void postAuthorizeWhenDeniedAndHandlerWithCustomAnnotationInClassThenHandlerCanUseMaskFromOtherAnnotation() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class, MethodSecurityService.MaskAnnotationPostProcessor.class)
-			.autowire();
-		MethodSecurityService service = this.spring.getContext().getBean(MethodSecurityService.class);
-		String result = service.postAuthorizeDeniedMethodWithNoMaskAnnotation();
-		assertThat(result).isEqualTo("classmask");
-	}
-
-	@Test
-	@WithMockUser
-	void postAuthorizeWhenDeniedAndHandlerWithCustomAnnotationUsingBeanThenHandlerCanUseMaskFromOtherAnnotation() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class, MethodSecurityService.MaskAnnotationPostProcessor.class,
-					MyMasker.class)
-			.autowire();
-		MethodSecurityService service = this.spring.getContext().getBean(MethodSecurityService.class);
-		String result = service.postAuthorizeWithMaskAnnotationUsingBean();
-		assertThat(result).isEqualTo("ok-masked");
-	}
-
-	@Test
-	@WithMockUser(roles = "ADMIN")
-	void postAuthorizeWhenAllowedAndHandlerWithCustomAnnotationUsingBeanThenInvokeMethodNormally() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class, MethodSecurityService.MaskAnnotationPostProcessor.class,
-					MyMasker.class)
-			.autowire();
-		MethodSecurityService service = this.spring.getContext().getBean(MethodSecurityService.class);
-		String result = service.postAuthorizeWithMaskAnnotationUsingBean();
-		assertThat(result).isEqualTo("ok");
-	}
-
-	@Test
-	@WithMockUser
-	void preAuthorizeWhenDeniedAndHandlerWithCustomAnnotationUsingBeanThenHandlerCanUseMaskFromOtherAnnotation() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class, MethodSecurityService.MaskAnnotationHandler.class,
-					MyMasker.class)
-			.autowire();
-		MethodSecurityService service = this.spring.getContext().getBean(MethodSecurityService.class);
-		String result = service.preAuthorizeWithMaskAnnotationUsingBean();
-		assertThat(result).isEqualTo("mask");
-	}
-
-	@Test
-	@WithMockUser(roles = "ADMIN")
-	void preAuthorizeWhenAllowedAndHandlerWithCustomAnnotationUsingBeanThenInvokeMethodNormally() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class, MethodSecurityService.MaskAnnotationHandler.class,
-					MyMasker.class)
-			.autowire();
-		MethodSecurityService service = this.spring.getContext().getBean(MethodSecurityService.class);
-		String result = service.preAuthorizeWithMaskAnnotationUsingBean();
-		assertThat(result).isEqualTo("ok");
-	}
-
-	@Test
-	@WithMockUser
-	void getUserWhenAuthorizedAndUserEmailIsProtectedAndNotAuthorizedThenReturnEmailMasked() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class,
-					UserRecordWithEmailProtected.EmailMaskingPostProcessor.class)
-			.autowire();
-		MethodSecurityService service = this.spring.getContext().getBean(MethodSecurityService.class);
-		UserRecordWithEmailProtected user = service.getUserRecordWithEmailProtected();
-		assertThat(user.email()).isEqualTo("use******@example.com");
-		assertThat(user.name()).isEqualTo("username");
-	}
-
-	@Test
-	@WithMockUser
-	void getUserWhenNotAuthorizedAndHandlerFallbackValueThenReturnFallbackValue() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class, MethodSecurityService.UserFallbackDeniedHandler.class)
-			.autowire();
-		MethodSecurityService service = this.spring.getContext().getBean(MethodSecurityService.class);
-		UserRecordWithEmailProtected user = service.getUserWithFallbackWhenUnauthorized();
-		assertThat(user.email()).isEqualTo("Protected");
-		assertThat(user.name()).isEqualTo("Protected");
-	}
-
-	@Test
-	@WithMockUser
-	void getUserWhenNotAuthorizedThenHandlerUsesCustomAuthorizationDecision() {
-		this.spring.register(MethodSecurityServiceConfig.class, CustomResultConfig.class).autowire();
-		MethodSecurityService service = this.spring.getContext().getBean(MethodSecurityService.class);
-		MethodAuthorizationDeniedHandler handler = this.spring.getContext()
-			.getBean(MethodAuthorizationDeniedHandler.class);
-		assertThat(service.checkCustomResult(false)).isNull();
-		verify(handler).handleDeniedInvocation(any(), any(Authz.AuthzResult.class));
-		verify(handler, never()).handleDeniedInvocationResult(any(), any(Authz.AuthzResult.class));
-		clearInvocations(handler);
-		assertThat(service.checkCustomResult(true)).isNull();
-		verify(handler).handleDeniedInvocationResult(any(), any(Authz.AuthzResult.class));
-		verify(handler, never()).handleDeniedInvocation(any(), any(Authz.AuthzResult.class));
-	}
-
 	private static Consumer<ConfigurableWebApplicationContext> disallowBeanOverriding() {
 		return (context) -> ((AnnotationConfigWebApplicationContext) context).setAllowBeanDefinitionOverriding(false);
 	}
 
-	private static Advisor returnAdvisor(int order) {
-		JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut();
-		pointcut.setPattern(".*MethodSecurityServiceImpl.*");
-		MethodInterceptor interceptor = (mi) -> mi.getArguments()[0];
-		DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, interceptor);
-		advisor.setOrder(order);
-		return advisor;
-	}
-
-	@Configuration
-	static class AuthzConfig {
-
-		@Bean
-		Authz authz() {
-			return new Authz();
-		}
-
-	}
-
 	@Configuration
 	@EnableCustomMethodSecurity
 	static class CustomMethodSecurityServiceConfig {
@@ -1143,341 +627,4 @@ public class PrePostMethodSecurityConfigurationTests {
 
 	}
 
-	@Configuration
-	@EnableMethodSecurity(jsr250Enabled = true, securedEnabled = true)
-	static class RoleHierarchyConfig {
-
-		@Bean
-		static RoleHierarchy roleHierarchy() {
-			RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl();
-			roleHierarchyImpl.setHierarchy("ROLE_ADMIN > ROLE_USER");
-			return roleHierarchyImpl;
-		}
-
-	}
-
-	@Import(OffsetConfig.class)
-	static class ReturnBeforeOffsetPreFilterConfig {
-
-		@Bean
-		@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-		Advisor returnBeforePreFilter() {
-			return returnAdvisor(AuthorizationInterceptorsOrder.PRE_FILTER.getOrder() + OffsetConfig.OFFSET - 1);
-		}
-
-	}
-
-	@Configuration
-	@Import(OffsetConfig.class)
-	static class ReturnBeforeOffsetPreAuthorizeConfig {
-
-		@Bean
-		@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-		Advisor returnBeforePreAuthorize() {
-			return returnAdvisor(AuthorizationInterceptorsOrder.PRE_AUTHORIZE.getOrder() + OffsetConfig.OFFSET - 1);
-		}
-
-	}
-
-	@Configuration
-	@Import(OffsetConfig.class)
-	static class ReturnBeforeOffsetSecuredConfig {
-
-		@Bean
-		@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-		Advisor returnBeforeSecured() {
-			return returnAdvisor(AuthorizationInterceptorsOrder.SECURED.getOrder() + OffsetConfig.OFFSET - 1);
-		}
-
-	}
-
-	@Configuration
-	@Import(OffsetConfig.class)
-	static class ReturnBeforeOffsetJsr250Config {
-
-		@Bean
-		@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-		Advisor returnBeforeJsr250() {
-			return returnAdvisor(AuthorizationInterceptorsOrder.JSR250.getOrder() + OffsetConfig.OFFSET - 1);
-		}
-
-	}
-
-	@Configuration
-	@Import(OffsetConfig.class)
-	static class ReturnBeforeOffsetPostAuthorizeConfig {
-
-		@Bean
-		@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-		Advisor returnBeforePreAuthorize() {
-			return returnAdvisor(AuthorizationInterceptorsOrder.POST_AUTHORIZE.getOrder() + OffsetConfig.OFFSET - 1);
-		}
-
-	}
-
-	@Configuration
-	@Import(OffsetConfig.class)
-	static class ReturnBeforeOffsetPostFilterConfig {
-
-		@Bean
-		@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-		Advisor returnBeforePostFilter() {
-			return returnAdvisor(AuthorizationInterceptorsOrder.POST_FILTER.getOrder() + OffsetConfig.OFFSET - 1);
-		}
-
-	}
-
-	@Configuration
-	@Import(OffsetConfig.class)
-	static class ReturnAfterAllOffsetConfig {
-
-		@Bean
-		@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-		Advisor returnAfterAll() {
-			return returnAdvisor(AuthorizationInterceptorsOrder.POST_FILTER.getOrder() + OffsetConfig.OFFSET + 1);
-		}
-
-	}
-
-	@Configuration
-	@EnableMethodSecurity(offset = OffsetConfig.OFFSET, jsr250Enabled = true, securedEnabled = true)
-	static class OffsetConfig {
-
-		static final int OFFSET = 2;
-
-		@Bean
-		MethodSecurityService methodSecurityService() {
-			return new MethodSecurityServiceImpl();
-		}
-
-		@Bean
-		Authz authz() {
-			return new Authz();
-		}
-
-	}
-
-	@Configuration
-	@EnableMethodSecurity
-	static class MetaAnnotationPlaceholderConfig {
-
-		@Bean
-		PrePostTemplateDefaults methodSecurityDefaults() {
-			return new PrePostTemplateDefaults();
-		}
-
-		@Bean
-		MetaAnnotationService metaAnnotationService() {
-			return new MetaAnnotationService();
-		}
-
-	}
-
-	static class MetaAnnotationService {
-
-		@RequireRole(role = "#role")
-		boolean hasRole(String role) {
-			return true;
-		}
-
-		@RequireRole(role = "'USER'")
-		boolean hasUserRole() {
-			return true;
-		}
-
-		@PreAuthorize("hasRole({role})")
-		void placeholdersOnlyResolvedByMetaAnnotations() {
-		}
-
-		@HasClaim(claim = "message:read", roles = { "'ADMIN'" })
-		String readMessage() {
-			return "message";
-		}
-
-		@ResultStartsWith("dave")
-		String startsWithDave(String value) {
-			return value;
-		}
-
-		@ParameterContains("dave")
-		List<String> parametersContainDave(List<String> list) {
-			return list;
-		}
-
-		@ResultContains("dave")
-		List<String> resultsContainDave(List<String> list) {
-			return list;
-		}
-
-	}
-
-	@Retention(RetentionPolicy.RUNTIME)
-	@PreAuthorize("hasRole({role})")
-	@interface RequireRole {
-
-		String role();
-
-	}
-
-	@Retention(RetentionPolicy.RUNTIME)
-	@PreAuthorize("hasAuthority('SCOPE_{claim}') || hasAnyRole({roles})")
-	@interface HasClaim {
-
-		String claim();
-
-		String[] roles() default {};
-
-	}
-
-	@Retention(RetentionPolicy.RUNTIME)
-	@PostAuthorize("returnObject.startsWith('{value}')")
-	@interface ResultStartsWith {
-
-		String value();
-
-	}
-
-	@Retention(RetentionPolicy.RUNTIME)
-	@PreFilter("filterObject.contains('{value}')")
-	@interface ParameterContains {
-
-		String value();
-
-	}
-
-	@Retention(RetentionPolicy.RUNTIME)
-	@PostFilter("filterObject.contains('{value}')")
-	@interface ResultContains {
-
-		String value();
-
-	}
-
-	@EnableMethodSecurity
-	@Configuration
-	static class AuthorizeResultConfig {
-
-		@Bean
-		@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-		static Customizer<AuthorizationAdvisorProxyFactory> skipValueTypes() {
-			return (f) -> f.setTargetVisitor(TargetVisitor.defaultsSkipValueTypes());
-		}
-
-		@Bean
-		FlightRepository flights() {
-			FlightRepository flights = new FlightRepository();
-			Flight one = new Flight("1", 35000d, 35);
-			one.board(new ArrayList<>(List.of("Marie Curie", "Kevin Mitnick", "Ada Lovelace")));
-			flights.save(one);
-			Flight two = new Flight("2", 32000d, 72);
-			two.board(new ArrayList<>(List.of("Albert Einstein")));
-			flights.save(two);
-			return flights;
-		}
-
-		@Bean
-		RoleHierarchy roleHierarchy() {
-			return RoleHierarchyImpl.withRolePrefix("").role("airplane:read").implies("seating:read").build();
-		}
-
-	}
-
-	@AuthorizeReturnObject
-	static class FlightRepository {
-
-		private final Map<String, Flight> flights = new ConcurrentHashMap<>();
-
-		Iterator<Flight> findAll() {
-			return this.flights.values().iterator();
-		}
-
-		Flight findById(String id) {
-			return this.flights.get(id);
-		}
-
-		Flight save(Flight flight) {
-			this.flights.put(flight.getId(), flight);
-			return flight;
-		}
-
-		void remove(String id) {
-			this.flights.remove(id);
-		}
-
-	}
-
-	@AuthorizeReturnObject
-	static class Flight {
-
-		private final String id;
-
-		private final Double altitude;
-
-		private final Integer seats;
-
-		private final List<Passenger> passengers = new ArrayList<>();
-
-		Flight(String id, Double altitude, Integer seats) {
-			this.id = id;
-			this.altitude = altitude;
-			this.seats = seats;
-		}
-
-		String getId() {
-			return this.id;
-		}
-
-		@PreAuthorize("hasAuthority('airplane:read')")
-		Double getAltitude() {
-			return this.altitude;
-		}
-
-		@PreAuthorize("hasAuthority('seating:read')")
-		Integer getSeats() {
-			return this.seats;
-		}
-
-		@PostAuthorize("hasAuthority('seating:read')")
-		@PostFilter("filterObject.name != 'Kevin Mitnick'")
-		List<Passenger> getPassengers() {
-			return this.passengers;
-		}
-
-		@PreAuthorize("hasAuthority('seating:read')")
-		@PreFilter("filterObject.contains(' ')")
-		void board(List<String> passengers) {
-			for (String passenger : passengers) {
-				this.passengers.add(new Passenger(passenger));
-			}
-		}
-
-	}
-
-	public static class Passenger {
-
-		String name;
-
-		public Passenger(String name) {
-			this.name = name;
-		}
-
-		@PreAuthorize("hasAuthority('airplane:read')")
-		public String getName() {
-			return this.name;
-		}
-
-	}
-
-	@EnableMethodSecurity
-	static class CustomResultConfig {
-
-		MethodAuthorizationDeniedHandler handler = mock(MethodAuthorizationDeniedHandler.class);
-
-		@Bean
-		MethodAuthorizationDeniedHandler methodAuthorizationDeniedHandler() {
-			return this.handler;
-		}
-
-	}
-
 }

+ 0 - 215
config/src/test/java/org/springframework/security/config/annotation/method/configuration/PrePostReactiveMethodSecurityConfigurationTests.java

@@ -1,215 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.config.annotation.method.configuration;
-
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import reactor.test.StepVerifier;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.security.config.test.SpringTestContext;
-import org.springframework.security.config.test.SpringTestContextExtension;
-import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners;
-import org.springframework.security.test.context.support.WithMockUser;
-import org.springframework.test.context.junit.jupiter.SpringExtension;
-
-@ExtendWith({ SpringExtension.class, SpringTestContextExtension.class })
-@SecurityTestExecutionListeners
-public class PrePostReactiveMethodSecurityConfigurationTests {
-
-	public final SpringTestContext spring = new SpringTestContext(this);
-
-	@Test
-	@WithMockUser
-	void getCardNumberWhenPostAuthorizeAndNotAdminThenReturnMasked() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class,
-					ReactiveMethodSecurityService.CardNumberMaskingPostProcessor.class)
-			.autowire();
-		ReactiveMethodSecurityService service = this.spring.getContext().getBean(ReactiveMethodSecurityService.class);
-		StepVerifier.create(service.postAuthorizeGetCardNumberIfAdmin("4444-3333-2222-1111"))
-			.expectNext("****-****-****-1111")
-			.verifyComplete();
-	}
-
-	@Test
-	@WithMockUser
-	void getCardNumberWhenPreAuthorizeAndNotAdminThenReturnMasked() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class, ReactiveMethodSecurityService.StarMaskingHandler.class)
-			.autowire();
-		ReactiveMethodSecurityService service = this.spring.getContext().getBean(ReactiveMethodSecurityService.class);
-		StepVerifier.create(service.preAuthorizeGetCardNumberIfAdmin("4444-3333-2222-1111"))
-			.expectNext("***")
-			.verifyComplete();
-	}
-
-	@Test
-	@WithMockUser
-	void getCardNumberWhenPreAuthorizeAndNotAdminAndChildHandlerThenResolveCorrectHandlerAndReturnMasked() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class, ReactiveMethodSecurityService.StarMaskingHandler.class,
-					ReactiveMethodSecurityService.StartMaskingHandlerChild.class)
-			.autowire();
-		ReactiveMethodSecurityService service = this.spring.getContext().getBean(ReactiveMethodSecurityService.class);
-		StepVerifier.create(service.preAuthorizeWithHandlerChildGetCardNumberIfAdmin("4444-3333-2222-1111"))
-			.expectNext("***-child")
-			.verifyComplete();
-	}
-
-	@Test
-	@WithMockUser
-	void preAuthorizeWhenDeniedAndHandlerWithCustomAnnotationThenHandlerCanUseMaskFromOtherAnnotation() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class,
-					ReactiveMethodSecurityService.MaskAnnotationHandler.class)
-			.autowire();
-		ReactiveMethodSecurityService service = this.spring.getContext().getBean(ReactiveMethodSecurityService.class);
-		StepVerifier.create(service.preAuthorizeDeniedMethodWithMaskAnnotation())
-			.expectNext("methodmask")
-			.verifyComplete();
-	}
-
-	@Test
-	@WithMockUser
-	void preAuthorizeWhenDeniedAndHandlerWithCustomAnnotationInClassThenHandlerCanUseMaskFromOtherAnnotation() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class,
-					ReactiveMethodSecurityService.MaskAnnotationHandler.class)
-			.autowire();
-		ReactiveMethodSecurityService service = this.spring.getContext().getBean(ReactiveMethodSecurityService.class);
-		StepVerifier.create(service.preAuthorizeDeniedMethodWithNoMaskAnnotation())
-			.expectNext("classmask")
-			.verifyComplete();
-	}
-
-	@Test
-	@WithMockUser(roles = "ADMIN")
-	void postAuthorizeWhenHandlerAndAccessDeniedNotThrownFromPostAuthorizeThenNotHandled() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class,
-					ReactiveMethodSecurityService.PostMaskingPostProcessor.class)
-			.autowire();
-		ReactiveMethodSecurityService service = this.spring.getContext().getBean(ReactiveMethodSecurityService.class);
-		StepVerifier.create(service.postAuthorizeThrowAccessDeniedManually()).expectNext("***").verifyComplete();
-	}
-
-	@Test
-	@WithMockUser(roles = "ADMIN")
-	void preAuthorizeWhenHandlerAndAccessDeniedNotThrownFromPreAuthorizeThenHandled() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class, ReactiveMethodSecurityService.StarMaskingHandler.class)
-			.autowire();
-		ReactiveMethodSecurityService service = this.spring.getContext().getBean(ReactiveMethodSecurityService.class);
-		StepVerifier.create(service.preAuthorizeThrowAccessDeniedManually()).expectNext("***").verifyComplete();
-	}
-
-	@Test
-	@WithMockUser
-	void postAuthorizeWhenNullDeniedMetaAnnotationThanWorks() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class, ReactiveMethodSecurityService.NullPostProcessor.class)
-			.autowire();
-		ReactiveMethodSecurityService service = this.spring.getContext().getBean(ReactiveMethodSecurityService.class);
-		StepVerifier.create(service.postAuthorizeDeniedWithNullDenied()).verifyComplete();
-	}
-
-	@Test
-	@WithMockUser
-	void postAuthorizeWhenDeniedAndHandlerWithCustomAnnotationThenHandlerCanUseMaskFromOtherAnnotation() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class,
-					ReactiveMethodSecurityService.MaskAnnotationPostProcessor.class)
-			.autowire();
-		ReactiveMethodSecurityService service = this.spring.getContext().getBean(ReactiveMethodSecurityService.class);
-		StepVerifier.create(service.postAuthorizeDeniedMethodWithMaskAnnotation())
-			.expectNext("methodmask")
-			.verifyComplete();
-	}
-
-	@Test
-	@WithMockUser
-	void postAuthorizeWhenDeniedAndHandlerWithCustomAnnotationInClassThenHandlerCanUseMaskFromOtherAnnotation() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class,
-					ReactiveMethodSecurityService.MaskAnnotationPostProcessor.class)
-			.autowire();
-		ReactiveMethodSecurityService service = this.spring.getContext().getBean(ReactiveMethodSecurityService.class);
-		StepVerifier.create(service.postAuthorizeDeniedMethodWithNoMaskAnnotation())
-			.expectNext("classmask")
-			.verifyComplete();
-	}
-
-	@Test
-	@WithMockUser
-	void postAuthorizeWhenDeniedAndHandlerWithCustomAnnotationUsingBeanThenHandlerCanUseMaskFromOtherAnnotation() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class,
-					ReactiveMethodSecurityService.MaskAnnotationPostProcessor.class, MyMasker.class)
-			.autowire();
-		ReactiveMethodSecurityService service = this.spring.getContext().getBean(ReactiveMethodSecurityService.class);
-		StepVerifier.create(service.postAuthorizeWithMaskAnnotationUsingBean())
-			.expectNext("ok-masked")
-			.verifyComplete();
-	}
-
-	@Test
-	@WithMockUser(roles = "ADMIN")
-	void postAuthorizeWhenAllowedAndHandlerWithCustomAnnotationUsingBeanThenInvokeMethodNormally() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class,
-					ReactiveMethodSecurityService.MaskAnnotationPostProcessor.class, MyMasker.class)
-			.autowire();
-		ReactiveMethodSecurityService service = this.spring.getContext().getBean(ReactiveMethodSecurityService.class);
-		StepVerifier.create(service.postAuthorizeWithMaskAnnotationUsingBean()).expectNext("ok").verifyComplete();
-	}
-
-	@Test
-	@WithMockUser
-	void preAuthorizeWhenDeniedAndHandlerWithCustomAnnotationUsingBeanThenHandlerCanUseMaskFromOtherAnnotation() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class,
-					ReactiveMethodSecurityService.MaskAnnotationHandler.class, MyMasker.class)
-			.autowire();
-		ReactiveMethodSecurityService service = this.spring.getContext().getBean(ReactiveMethodSecurityService.class);
-		StepVerifier.create(service.preAuthorizeWithMaskAnnotationUsingBean()).expectNext("mask").verifyComplete();
-	}
-
-	@Test
-	@WithMockUser(roles = "ADMIN")
-	void preAuthorizeWhenAllowedAndHandlerWithCustomAnnotationUsingBeanThenInvokeMethodNormally() {
-		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class,
-					ReactiveMethodSecurityService.MaskAnnotationHandler.class, MyMasker.class)
-			.autowire();
-		ReactiveMethodSecurityService service = this.spring.getContext().getBean(ReactiveMethodSecurityService.class);
-		StepVerifier.create(service.preAuthorizeWithMaskAnnotationUsingBean()).expectNext("ok").verifyComplete();
-	}
-
-	@Configuration
-	@EnableReactiveMethodSecurity
-	static class MethodSecurityServiceEnabledConfig {
-
-		@Bean
-		ReactiveMethodSecurityService methodSecurityService() {
-			return new ReactiveMethodSecurityServiceImpl();
-		}
-
-	}
-
-}

+ 9 - 289
config/src/test/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityConfigurationTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2019 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,53 +16,22 @@
 
 package org.springframework.security.config.annotation.method.configuration;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.function.Consumer;
-import java.util.function.Function;
-
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-import reactor.test.StepVerifier;
 
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Role;
 import org.springframework.expression.EvaluationContext;
-import org.springframework.security.access.AccessDeniedException;
 import org.springframework.security.access.expression.SecurityExpressionRoot;
 import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
 import org.springframework.security.access.intercept.method.MockMethodInvocation;
-import org.springframework.security.access.prepost.PostAuthorize;
-import org.springframework.security.access.prepost.PostFilter;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.security.access.prepost.PreFilter;
-import org.springframework.security.authentication.TestAuthentication;
-import org.springframework.security.authorization.method.AuthorizationAdvisorProxyFactory;
-import org.springframework.security.authorization.method.AuthorizationAdvisorProxyFactory.TargetVisitor;
-import org.springframework.security.authorization.method.AuthorizeReturnObject;
-import org.springframework.security.authorization.method.MethodAuthorizationDeniedHandler;
-import org.springframework.security.config.Customizer;
+import org.springframework.security.authentication.TestingAuthenticationToken;
 import org.springframework.security.config.core.GrantedAuthorityDefaults;
 import org.springframework.security.config.test.SpringTestContext;
 import org.springframework.security.config.test.SpringTestContextExtension;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.ReactiveSecurityContextHolder;
-import org.springframework.security.core.userdetails.User;
-import org.springframework.security.test.context.support.WithMockUser;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
 
 /**
  * @author Tadaya Tsuyukubo
@@ -72,13 +41,14 @@ public class ReactiveMethodSecurityConfigurationTests {
 
 	public final SpringTestContext spring = new SpringTestContext(this);
 
-	@Autowired(required = false)
+	@Autowired
 	DefaultMethodSecurityExpressionHandler methodSecurityExpressionHandler;
 
 	@Test
 	public void rolePrefixWithGrantedAuthorityDefaults() throws NoSuchMethodException {
 		this.spring.register(WithRolePrefixConfiguration.class).autowire();
-		Authentication authentication = TestAuthentication.authenticatedUser(authorities("CUSTOM_ABC"));
+		TestingAuthenticationToken authentication = new TestingAuthenticationToken("principal", "credential",
+				"CUSTOM_ABC");
 		MockMethodInvocation methodInvocation = new MockMethodInvocation(new Foo(), Foo.class, "bar", String.class);
 		EvaluationContext context = this.methodSecurityExpressionHandler.createEvaluationContext(authentication,
 				methodInvocation);
@@ -92,7 +62,8 @@ public class ReactiveMethodSecurityConfigurationTests {
 	@Test
 	public void rolePrefixWithDefaultConfig() throws NoSuchMethodException {
 		this.spring.register(ReactiveMethodSecurityConfiguration.class).autowire();
-		Authentication authentication = TestAuthentication.authenticatedUser(authorities("ROLE_ABC"));
+		TestingAuthenticationToken authentication = new TestingAuthenticationToken("principal", "credential",
+				"ROLE_ABC");
 		MockMethodInvocation methodInvocation = new MockMethodInvocation(new Foo(), Foo.class, "bar", String.class);
 		EvaluationContext context = this.methodSecurityExpressionHandler.createEvaluationContext(authentication,
 				methodInvocation);
@@ -104,7 +75,8 @@ public class ReactiveMethodSecurityConfigurationTests {
 	@Test
 	public void rolePrefixWithGrantedAuthorityDefaultsAndSubclassWithProxyingEnabled() throws NoSuchMethodException {
 		this.spring.register(SubclassConfig.class).autowire();
-		Authentication authentication = TestAuthentication.authenticatedUser(authorities("ROLE_ABC"));
+		TestingAuthenticationToken authentication = new TestingAuthenticationToken("principal", "credential",
+				"ROLE_ABC");
 		MockMethodInvocation methodInvocation = new MockMethodInvocation(new Foo(), Foo.class, "bar", String.class);
 		EvaluationContext context = this.methodSecurityExpressionHandler.createEvaluationContext(authentication,
 				methodInvocation);
@@ -113,132 +85,6 @@ public class ReactiveMethodSecurityConfigurationTests {
 		assertThat(root.hasRole("ABC")).isTrue();
 	}
 
-	@Test
-	public void findByIdWhenAuthorizedResultThenAuthorizes() {
-		this.spring.register(AuthorizeResultConfig.class).autowire();
-		FlightRepository flights = this.spring.getContext().getBean(FlightRepository.class);
-		Authentication pilot = TestAuthentication.authenticatedUser(authorities("airplane:read"));
-		StepVerifier
-			.create(flights.findById("1")
-				.flatMap(Flight::getAltitude)
-				.contextWrite(ReactiveSecurityContextHolder.withAuthentication(pilot)))
-			.expectNextCount(1)
-			.verifyComplete();
-		StepVerifier
-			.create(flights.findById("1")
-				.flatMap(Flight::getSeats)
-				.contextWrite(ReactiveSecurityContextHolder.withAuthentication(pilot)))
-			.expectNextCount(1)
-			.verifyComplete();
-	}
-
-	@Test
-	public void findByIdWhenUnauthorizedResultThenDenies() {
-		this.spring.register(AuthorizeResultConfig.class).autowire();
-		FlightRepository flights = this.spring.getContext().getBean(FlightRepository.class);
-		Authentication pilot = TestAuthentication.authenticatedUser(authorities("seating:read"));
-		StepVerifier
-			.create(flights.findById("1")
-				.flatMap(Flight::getSeats)
-				.contextWrite(ReactiveSecurityContextHolder.withAuthentication(pilot)))
-			.expectNextCount(1)
-			.verifyComplete();
-		StepVerifier
-			.create(flights.findById("1")
-				.flatMap(Flight::getAltitude)
-				.contextWrite(ReactiveSecurityContextHolder.withAuthentication(pilot)))
-			.verifyError(AccessDeniedException.class);
-	}
-
-	@Test
-	public void findAllWhenUnauthorizedResultThenDenies() {
-		this.spring.register(AuthorizeResultConfig.class).autowire();
-		FlightRepository flights = this.spring.getContext().getBean(FlightRepository.class);
-		Authentication pilot = TestAuthentication.authenticatedUser(authorities("seating:read"));
-		StepVerifier
-			.create(flights.findAll()
-				.flatMap(Flight::getSeats)
-				.contextWrite(ReactiveSecurityContextHolder.withAuthentication(pilot)))
-			.expectNextCount(2)
-			.verifyComplete();
-		StepVerifier
-			.create(flights.findAll()
-				.flatMap(Flight::getAltitude)
-				.contextWrite(ReactiveSecurityContextHolder.withAuthentication(pilot)))
-			.verifyError(AccessDeniedException.class);
-	}
-
-	@Test
-	public void removeWhenAuthorizedResultThenRemoves() {
-		this.spring.register(AuthorizeResultConfig.class).autowire();
-		FlightRepository flights = this.spring.getContext().getBean(FlightRepository.class);
-		Authentication pilot = TestAuthentication.authenticatedUser(authorities("seating:read"));
-		StepVerifier.create(flights.remove("1").contextWrite(ReactiveSecurityContextHolder.withAuthentication(pilot)))
-			.verifyComplete();
-	}
-
-	@Test
-	public void findAllWhenPostFilterThenFilters() {
-		this.spring.register(AuthorizeResultConfig.class).autowire();
-		FlightRepository flights = this.spring.getContext().getBean(FlightRepository.class);
-		Authentication pilot = TestAuthentication.authenticatedUser(authorities("airplane:read"));
-		StepVerifier
-			.create(flights.findAll()
-				.flatMap(Flight::getPassengers)
-				.flatMap(Passenger::getName)
-				.contextWrite(ReactiveSecurityContextHolder.withAuthentication(pilot)))
-			.expectNext("Marie Curie", "Ada Lovelace", "Albert Einstein")
-			.verifyComplete();
-	}
-
-	@Test
-	public void findAllWhenPreFilterThenFilters() {
-		this.spring.register(AuthorizeResultConfig.class).autowire();
-		FlightRepository flights = this.spring.getContext().getBean(FlightRepository.class);
-		Authentication pilot = TestAuthentication.authenticatedUser(authorities("airplane:read"));
-		StepVerifier
-			.create(flights.findAll()
-				.flatMap((flight) -> flight.board(Flux.just("John Doe", "John")).then(Mono.just(flight)))
-				.flatMap(Flight::getPassengers)
-				.flatMap(Passenger::getName)
-				.contextWrite(ReactiveSecurityContextHolder.withAuthentication(pilot)))
-			.expectNext("Marie Curie", "Ada Lovelace", "John Doe", "Albert Einstein", "John Doe")
-			.verifyComplete();
-	}
-
-	@Test
-	public void findAllWhenNestedPreAuthorizeThenAuthorizes() {
-		this.spring.register(AuthorizeResultConfig.class).autowire();
-		FlightRepository flights = this.spring.getContext().getBean(FlightRepository.class);
-		Authentication pilot = TestAuthentication.authenticatedUser(authorities("seating:read"));
-		StepVerifier
-			.create(flights.findAll()
-				.flatMap(Flight::getPassengers)
-				.flatMap(Passenger::getName)
-				.contextWrite(ReactiveSecurityContextHolder.withAuthentication(pilot)))
-			.verifyError(AccessDeniedException.class);
-	}
-
-	@Test
-	@WithMockUser
-	void getUserWhenNotAuthorizedThenHandlerUsesCustomAuthorizationDecision() {
-		this.spring.register(MethodSecurityServiceConfig.class, CustomResultConfig.class).autowire();
-		ReactiveMethodSecurityService service = this.spring.getContext().getBean(ReactiveMethodSecurityService.class);
-		MethodAuthorizationDeniedHandler handler = this.spring.getContext()
-			.getBean(MethodAuthorizationDeniedHandler.class);
-		assertThat(service.checkCustomResult(false).block()).isNull();
-		verify(handler).handleDeniedInvocation(any(), any(Authz.AuthzResult.class));
-		verify(handler, never()).handleDeniedInvocationResult(any(), any(Authz.AuthzResult.class));
-		clearInvocations(handler);
-		assertThat(service.checkCustomResult(true).block()).isNull();
-		verify(handler).handleDeniedInvocationResult(any(), any(Authz.AuthzResult.class));
-		verify(handler, never()).handleDeniedInvocation(any(), any(Authz.AuthzResult.class));
-	}
-
-	private static Consumer<User.UserBuilder> authorities(String... authorities) {
-		return (builder) -> builder.authorities(authorities);
-	}
-
 	@Configuration
 	@EnableReactiveMethodSecurity // this imports ReactiveMethodSecurityConfiguration
 	static class WithRolePrefixConfiguration {
@@ -262,130 +108,4 @@ public class ReactiveMethodSecurityConfigurationTests {
 
 	}
 
-	@EnableReactiveMethodSecurity
-	@Configuration
-	static class AuthorizeResultConfig {
-
-		@Bean
-		@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-		static Customizer<AuthorizationAdvisorProxyFactory> skipValueTypes() {
-			return (factory) -> factory.setTargetVisitor(TargetVisitor.defaultsSkipValueTypes());
-		}
-
-		@Bean
-		FlightRepository flights() {
-			FlightRepository flights = new FlightRepository();
-			Flight one = new Flight("1", 35000d, 35);
-			one.board(Flux.just("Marie Curie", "Kevin Mitnick", "Ada Lovelace")).block();
-			flights.save(one).block();
-			Flight two = new Flight("2", 32000d, 72);
-			two.board(Flux.just("Albert Einstein")).block();
-			flights.save(two).block();
-			return flights;
-		}
-
-		@Bean
-		Function<Passenger, Mono<Boolean>> isNotKevin() {
-			return (passenger) -> passenger.getName().map((name) -> !name.equals("Kevin Mitnick"));
-		}
-
-	}
-
-	@AuthorizeReturnObject
-	static class FlightRepository {
-
-		private final Map<String, Flight> flights = new ConcurrentHashMap<>();
-
-		Flux<Flight> findAll() {
-			return Flux.fromIterable(this.flights.values());
-		}
-
-		Mono<Flight> findById(String id) {
-			return Mono.just(this.flights.get(id));
-		}
-
-		Mono<Flight> save(Flight flight) {
-			this.flights.put(flight.getId(), flight);
-			return Mono.just(flight);
-		}
-
-		Mono<Void> remove(String id) {
-			this.flights.remove(id);
-			return Mono.empty();
-		}
-
-	}
-
-	@AuthorizeReturnObject
-	static class Flight {
-
-		private final String id;
-
-		private final Double altitude;
-
-		private final Integer seats;
-
-		private final List<Passenger> passengers = new ArrayList<>();
-
-		Flight(String id, Double altitude, Integer seats) {
-			this.id = id;
-			this.altitude = altitude;
-			this.seats = seats;
-		}
-
-		String getId() {
-			return this.id;
-		}
-
-		@PreAuthorize("hasAuthority('airplane:read')")
-		Mono<Double> getAltitude() {
-			return Mono.just(this.altitude);
-		}
-
-		@PreAuthorize("hasAnyAuthority('seating:read', 'airplane:read')")
-		Mono<Integer> getSeats() {
-			return Mono.just(this.seats);
-		}
-
-		@PostAuthorize("hasAnyAuthority('seating:read', 'airplane:read')")
-		@PostFilter("@isNotKevin.apply(filterObject)")
-		Flux<Passenger> getPassengers() {
-			return Flux.fromIterable(this.passengers);
-		}
-
-		@PreAuthorize("hasAnyAuthority('seating:read', 'airplane:read')")
-		@PreFilter("filterObject.contains(' ')")
-		Mono<Void> board(Flux<String> passengers) {
-			return passengers.doOnNext((passenger) -> this.passengers.add(new Passenger(passenger))).then();
-		}
-
-	}
-
-	public static class Passenger {
-
-		String name;
-
-		public Passenger(String name) {
-			this.name = name;
-		}
-
-		@PreAuthorize("hasAuthority('airplane:read')")
-		public Mono<String> getName() {
-			return Mono.just(this.name);
-		}
-
-	}
-
-	@EnableReactiveMethodSecurity
-	static class CustomResultConfig {
-
-		MethodAuthorizationDeniedHandler handler = mock(MethodAuthorizationDeniedHandler.class);
-
-		@Bean
-		MethodAuthorizationDeniedHandler methodAuthorizationDeniedHandler() {
-			return this.handler;
-		}
-
-	}
-
 }

+ 0 - 255
config/src/test/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityService.java

@@ -1,255 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.config.annotation.method.configuration;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-import org.aopalliance.intercept.MethodInvocation;
-import reactor.core.publisher.Mono;
-
-import org.springframework.context.ApplicationContext;
-import org.springframework.core.annotation.AnnotationUtils;
-import org.springframework.expression.EvaluationContext;
-import org.springframework.expression.Expression;
-import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
-import org.springframework.security.access.prepost.PostAuthorize;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.security.authorization.AuthorizationResult;
-import org.springframework.security.authorization.method.HandleAuthorizationDenied;
-import org.springframework.security.authorization.method.MethodAuthorizationDeniedHandler;
-import org.springframework.security.authorization.method.MethodInvocationResult;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.util.StringUtils;
-
-/**
- * @author Rob Winch
- */
-@ReactiveMethodSecurityService.Mask("classmask")
-public interface ReactiveMethodSecurityService {
-
-	@PreAuthorize("hasRole('ADMIN')")
-	@HandleAuthorizationDenied(handlerClass = StarMaskingHandler.class)
-	Mono<String> preAuthorizeGetCardNumberIfAdmin(String cardNumber);
-
-	@PreAuthorize("hasRole('ADMIN')")
-	@HandleAuthorizationDenied(handlerClass = StartMaskingHandlerChild.class)
-	Mono<String> preAuthorizeWithHandlerChildGetCardNumberIfAdmin(String cardNumber);
-
-	@PreAuthorize("hasRole('ADMIN')")
-	@HandleAuthorizationDenied(handlerClass = StarMaskingHandler.class)
-	Mono<String> preAuthorizeThrowAccessDeniedManually();
-
-	@PostAuthorize("hasRole('ADMIN')")
-	@HandleAuthorizationDenied(handlerClass = CardNumberMaskingPostProcessor.class)
-	Mono<String> postAuthorizeGetCardNumberIfAdmin(String cardNumber);
-
-	@PostAuthorize("hasRole('ADMIN')")
-	@HandleAuthorizationDenied(handlerClass = PostMaskingPostProcessor.class)
-	Mono<String> postAuthorizeThrowAccessDeniedManually();
-
-	@PreAuthorize("denyAll()")
-	@Mask("methodmask")
-	@HandleAuthorizationDenied(handlerClass = MaskAnnotationHandler.class)
-	Mono<String> preAuthorizeDeniedMethodWithMaskAnnotation();
-
-	@PreAuthorize("denyAll()")
-	@HandleAuthorizationDenied(handlerClass = MaskAnnotationHandler.class)
-	Mono<String> preAuthorizeDeniedMethodWithNoMaskAnnotation();
-
-	@NullDenied(role = "ADMIN")
-	Mono<String> postAuthorizeDeniedWithNullDenied();
-
-	@PostAuthorize("denyAll()")
-	@Mask("methodmask")
-	@HandleAuthorizationDenied(handlerClass = MaskAnnotationPostProcessor.class)
-	Mono<String> postAuthorizeDeniedMethodWithMaskAnnotation();
-
-	@PostAuthorize("denyAll()")
-	@HandleAuthorizationDenied(handlerClass = MaskAnnotationPostProcessor.class)
-	Mono<String> postAuthorizeDeniedMethodWithNoMaskAnnotation();
-
-	@PreAuthorize("hasRole('ADMIN')")
-	@Mask(expression = "@myMasker.getMask()")
-	@HandleAuthorizationDenied(handlerClass = MaskAnnotationHandler.class)
-	Mono<String> preAuthorizeWithMaskAnnotationUsingBean();
-
-	@PostAuthorize("hasRole('ADMIN')")
-	@Mask(expression = "@myMasker.getMask(returnObject)")
-	@HandleAuthorizationDenied(handlerClass = MaskAnnotationPostProcessor.class)
-	Mono<String> postAuthorizeWithMaskAnnotationUsingBean();
-
-	@PreAuthorize("@authz.checkReactiveResult(#result)")
-	@PostAuthorize("@authz.checkReactiveResult(!#result)")
-	@HandleAuthorizationDenied(handlerClass = MethodAuthorizationDeniedHandler.class)
-	Mono<String> checkCustomResult(boolean result);
-
-	class StarMaskingHandler implements MethodAuthorizationDeniedHandler {
-
-		@Override
-		public Object handleDeniedInvocation(MethodInvocation methodInvocation, AuthorizationResult result) {
-			return "***";
-		}
-
-	}
-
-	class StartMaskingHandlerChild extends StarMaskingHandler {
-
-		@Override
-		public Object handleDeniedInvocation(MethodInvocation methodInvocation, AuthorizationResult result) {
-			return super.handleDeniedInvocation(methodInvocation, result) + "-child";
-		}
-
-	}
-
-	class MaskAnnotationHandler implements MethodAuthorizationDeniedHandler {
-
-		MaskValueResolver maskValueResolver;
-
-		MaskAnnotationHandler(ApplicationContext context) {
-			this.maskValueResolver = new MaskValueResolver(context);
-		}
-
-		@Override
-		public Object handleDeniedInvocation(MethodInvocation methodInvocation, AuthorizationResult result) {
-			Mask mask = AnnotationUtils.getAnnotation(methodInvocation.getMethod(), Mask.class);
-			if (mask == null) {
-				mask = AnnotationUtils.getAnnotation(methodInvocation.getMethod().getDeclaringClass(), Mask.class);
-			}
-			return this.maskValueResolver.resolveValue(mask, methodInvocation, null);
-		}
-
-	}
-
-	class MaskAnnotationPostProcessor implements MethodAuthorizationDeniedHandler {
-
-		MaskValueResolver maskValueResolver;
-
-		MaskAnnotationPostProcessor(ApplicationContext context) {
-			this.maskValueResolver = new MaskValueResolver(context);
-		}
-
-		@Override
-		public Object handleDeniedInvocation(MethodInvocation mi, AuthorizationResult authorizationResult) {
-			Mask mask = AnnotationUtils.getAnnotation(mi.getMethod(), Mask.class);
-			if (mask == null) {
-				mask = AnnotationUtils.getAnnotation(mi.getMethod().getDeclaringClass(), Mask.class);
-			}
-			return this.maskValueResolver.resolveValue(mask, mi, null);
-		}
-
-		@Override
-		public Object handleDeniedInvocationResult(MethodInvocationResult methodInvocationResult,
-				AuthorizationResult authorizationResult) {
-			MethodInvocation mi = methodInvocationResult.getMethodInvocation();
-			Mask mask = AnnotationUtils.getAnnotation(mi.getMethod(), Mask.class);
-			if (mask == null) {
-				mask = AnnotationUtils.getAnnotation(mi.getMethod().getDeclaringClass(), Mask.class);
-			}
-			return this.maskValueResolver.resolveValue(mask, mi, methodInvocationResult.getResult());
-		}
-
-	}
-
-	class MaskValueResolver {
-
-		DefaultMethodSecurityExpressionHandler expressionHandler;
-
-		MaskValueResolver(ApplicationContext context) {
-			this.expressionHandler = new DefaultMethodSecurityExpressionHandler();
-			this.expressionHandler.setApplicationContext(context);
-		}
-
-		Mono<String> resolveValue(Mask mask, MethodInvocation mi, Object returnObject) {
-			if (StringUtils.hasText(mask.value())) {
-				return Mono.just(mask.value());
-			}
-			Expression expression = this.expressionHandler.getExpressionParser().parseExpression(mask.expression());
-			EvaluationContext evaluationContext = this.expressionHandler
-				.createEvaluationContext(() -> SecurityContextHolder.getContext().getAuthentication(), mi);
-			if (returnObject != null) {
-				this.expressionHandler.setReturnObject(returnObject, evaluationContext);
-			}
-			return Mono.just(expression.getValue(evaluationContext, String.class));
-		}
-
-	}
-
-	class PostMaskingPostProcessor implements MethodAuthorizationDeniedHandler {
-
-		@Override
-		public Object handleDeniedInvocation(MethodInvocation methodInvocation,
-				AuthorizationResult authorizationResult) {
-			return "***";
-		}
-
-	}
-
-	class CardNumberMaskingPostProcessor implements MethodAuthorizationDeniedHandler {
-
-		static String MASK = "****-****-****-";
-
-		@Override
-		public Object handleDeniedInvocation(MethodInvocation methodInvocation,
-				AuthorizationResult authorizationResult) {
-			return "***";
-		}
-
-		@Override
-		public Object handleDeniedInvocationResult(MethodInvocationResult contextObject, AuthorizationResult result) {
-			String cardNumber = (String) contextObject.getResult();
-			return MASK + cardNumber.substring(cardNumber.length() - 4);
-		}
-
-	}
-
-	class NullPostProcessor implements MethodAuthorizationDeniedHandler {
-
-		@Override
-		public Object handleDeniedInvocation(MethodInvocation methodInvocation,
-				AuthorizationResult authorizationResult) {
-			return null;
-		}
-
-	}
-
-	@Target({ ElementType.METHOD, ElementType.TYPE })
-	@Retention(RetentionPolicy.RUNTIME)
-	@Inherited
-	@interface Mask {
-
-		String value() default "";
-
-		String expression() default "";
-
-	}
-
-	@Target({ ElementType.METHOD, ElementType.TYPE })
-	@Retention(RetentionPolicy.RUNTIME)
-	@Inherited
-	@PostAuthorize("hasRole('{value}')")
-	@HandleAuthorizationDenied(handlerClass = NullPostProcessor.class)
-	@interface NullDenied {
-
-		String role();
-
-	}
-
-}

+ 0 - 91
config/src/test/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityServiceImpl.java

@@ -1,91 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.config.annotation.method.configuration;
-
-import reactor.core.publisher.Mono;
-
-import org.springframework.security.authorization.AuthorizationDecision;
-import org.springframework.security.authorization.AuthorizationDeniedException;
-
-public class ReactiveMethodSecurityServiceImpl implements ReactiveMethodSecurityService {
-
-	@Override
-	public Mono<String> preAuthorizeGetCardNumberIfAdmin(String cardNumber) {
-		return Mono.just(cardNumber);
-	}
-
-	@Override
-	public Mono<String> preAuthorizeWithHandlerChildGetCardNumberIfAdmin(String cardNumber) {
-		return Mono.just(cardNumber);
-	}
-
-	@Override
-	public Mono<String> preAuthorizeThrowAccessDeniedManually() {
-		return Mono.error(new AuthorizationDeniedException("Access Denied", new AuthorizationDecision(false)));
-	}
-
-	@Override
-	public Mono<String> postAuthorizeGetCardNumberIfAdmin(String cardNumber) {
-		return Mono.just(cardNumber);
-	}
-
-	@Override
-	public Mono<String> postAuthorizeThrowAccessDeniedManually() {
-		return Mono.error(new AuthorizationDeniedException("Access Denied", new AuthorizationDecision(false)));
-	}
-
-	@Override
-	public Mono<String> preAuthorizeDeniedMethodWithMaskAnnotation() {
-		return Mono.just("ok");
-	}
-
-	@Override
-	public Mono<String> preAuthorizeDeniedMethodWithNoMaskAnnotation() {
-		return Mono.just("ok");
-	}
-
-	@Override
-	public Mono<String> postAuthorizeDeniedWithNullDenied() {
-		return Mono.just("ok");
-	}
-
-	@Override
-	public Mono<String> postAuthorizeDeniedMethodWithMaskAnnotation() {
-		return Mono.just("ok");
-	}
-
-	@Override
-	public Mono<String> postAuthorizeDeniedMethodWithNoMaskAnnotation() {
-		return Mono.just("ok");
-	}
-
-	@Override
-	public Mono<String> preAuthorizeWithMaskAnnotationUsingBean() {
-		return Mono.just("ok");
-	}
-
-	@Override
-	public Mono<String> postAuthorizeWithMaskAnnotationUsingBean() {
-		return Mono.just("ok");
-	}
-
-	@Override
-	public Mono<String> checkCustomResult(boolean result) {
-		return Mono.just("ok");
-	}
-
-}

+ 0 - 65
config/src/test/java/org/springframework/security/config/annotation/method/configuration/UserRecordWithEmailProtected.java

@@ -1,65 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.config.annotation.method.configuration;
-
-import org.aopalliance.intercept.MethodInvocation;
-
-import org.springframework.security.access.prepost.PostAuthorize;
-import org.springframework.security.authorization.AuthorizationResult;
-import org.springframework.security.authorization.method.HandleAuthorizationDenied;
-import org.springframework.security.authorization.method.MethodAuthorizationDeniedHandler;
-import org.springframework.security.authorization.method.MethodInvocationResult;
-
-public class UserRecordWithEmailProtected {
-
-	private final String name;
-
-	private final String email;
-
-	public UserRecordWithEmailProtected(String name, String email) {
-		this.name = name;
-		this.email = email;
-	}
-
-	public String name() {
-		return this.name;
-	}
-
-	@PostAuthorize("hasRole('ADMIN')")
-	@HandleAuthorizationDenied(handlerClass = EmailMaskingPostProcessor.class)
-	public String email() {
-		return this.email;
-	}
-
-	public static class EmailMaskingPostProcessor implements MethodAuthorizationDeniedHandler {
-
-		@Override
-		public Object handleDeniedInvocation(MethodInvocation methodInvocation,
-				AuthorizationResult authorizationResult) {
-			return "***";
-		}
-
-		@Override
-		public Object handleDeniedInvocationResult(MethodInvocationResult methodInvocationResult,
-				AuthorizationResult authorizationResult) {
-			String email = (String) methodInvocationResult.getResult();
-			return email.replaceAll("(^[^@]{3}|(?!^)\\G)[^@]", "$1*");
-		}
-
-	}
-
-}

+ 0 - 68
config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/ApplicationConfig.java

@@ -1,68 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.config.annotation.method.configuration.issue14637;
-
-import javax.sql.DataSource;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
-import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
-import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
-import org.springframework.orm.jpa.JpaTransactionManager;
-import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
-import org.springframework.orm.jpa.vendor.Database;
-import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
-import org.springframework.security.config.annotation.method.configuration.issue14637.domain.Entry;
-import org.springframework.transaction.PlatformTransactionManager;
-import org.springframework.transaction.annotation.EnableTransactionManagement;
-
-/**
- * @author Josh Cummings
- */
-@Configuration
-@EnableJpaRepositories("org.springframework.security.config.annotation.method.configuration.issue14637.repo")
-@EnableTransactionManagement
-public class ApplicationConfig {
-
-	@Bean
-	public DataSource dataSource() {
-		EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
-		return builder.setType(EmbeddedDatabaseType.HSQL).build();
-	}
-
-	@Bean
-	public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
-		HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
-		vendorAdapter.setDatabase(Database.HSQL);
-		vendorAdapter.setGenerateDdl(true);
-		vendorAdapter.setShowSql(true);
-		LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
-		factory.setJpaVendorAdapter(vendorAdapter);
-		factory.setPackagesToScan(Entry.class.getPackage().getName());
-		factory.setDataSource(dataSource());
-		return factory;
-	}
-
-	@Bean
-	public PlatformTransactionManager transactionManager() {
-		JpaTransactionManager txManager = new JpaTransactionManager();
-		txManager.setEntityManagerFactory(entityManagerFactory().getObject());
-		return txManager;
-	}
-
-}

+ 0 - 50
config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/Issue14637Tests.java

@@ -1,50 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.config.annotation.method.configuration.issue14637;
-
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.AccessDeniedException;
-import org.springframework.security.config.annotation.method.configuration.issue14637.domain.Entry;
-import org.springframework.security.config.annotation.method.configuration.issue14637.repo.EntryRepository;
-import org.springframework.security.test.context.support.WithMockUser;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit.jupiter.SpringExtension;
-
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-
-/**
- * @author Josh Cummings
- */
-@ExtendWith(SpringExtension.class)
-@ContextConfiguration(classes = { ApplicationConfig.class, SecurityConfig.class })
-public class Issue14637Tests {
-
-	@Autowired
-	private EntryRepository entries;
-
-	@Test
-	@WithMockUser
-	public void authenticateWhenInvalidPasswordThenBadCredentialsException() {
-		Entry entry = new Entry();
-		entry.setId(123L);
-		assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(() -> this.entries.save(entry));
-	}
-
-}

+ 0 - 29
config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/SecurityConfig.java

@@ -1,29 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.config.annotation.method.configuration.issue14637;
-
-import org.springframework.context.annotation.Configuration;
-import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
-
-/**
- * @author Josh Cummings
- */
-@Configuration
-@EnableMethodSecurity
-public class SecurityConfig {
-
-}

+ 0 - 42
config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/domain/Entry.java

@@ -1,42 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.config.annotation.method.configuration.issue14637.domain;
-
-import jakarta.persistence.Entity;
-import jakarta.persistence.GeneratedValue;
-import jakarta.persistence.GenerationType;
-import jakarta.persistence.Id;
-
-/**
- * @author Josh Cummings
- */
-@Entity
-public class Entry {
-
-	@Id
-	@GeneratedValue(strategy = GenerationType.AUTO)
-	private Long id;
-
-	public Long getId() {
-		return this.id;
-	}
-
-	public void setId(Long id) {
-		this.id = id;
-	}
-
-}

+ 0 - 31
config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/repo/EntryRepository.java

@@ -1,31 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.config.annotation.method.configuration.issue14637.repo;
-
-import org.springframework.data.repository.CrudRepository;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.security.config.annotation.method.configuration.issue14637.domain.Entry;
-
-/**
- * @author Josh Cummings
- */
-public interface EntryRepository extends CrudRepository<Entry, String> {
-
-	@PreAuthorize("#entry.id == null")
-	Entry save(Entry entry);
-
-}

+ 2 - 88
config/src/test/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfigurationTests.java

@@ -47,9 +47,6 @@ import org.springframework.security.authentication.TestingAuthenticationToken;
 import org.springframework.security.authentication.event.AbstractAuthenticationEvent;
 import org.springframework.security.authentication.event.AbstractAuthenticationFailureEvent;
 import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
-import org.springframework.security.authentication.password.CompromisedPasswordCheckResult;
-import org.springframework.security.authentication.password.CompromisedPasswordChecker;
-import org.springframework.security.authentication.password.CompromisedPasswordException;
 import org.springframework.security.config.Customizer;
 import org.springframework.security.config.annotation.SecurityContextChangedListenerConfig;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
@@ -63,8 +60,8 @@ import org.springframework.security.core.AuthenticationException;
 import org.springframework.security.core.context.SecurityContextHolderStrategy;
 import org.springframework.security.core.userdetails.User;
 import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.security.provisioning.InMemoryUserDetailsManager;
-import org.springframework.security.provisioning.UserDetailsManager;
 import org.springframework.security.test.web.servlet.RequestCacheResultMatcher;
 import org.springframework.security.web.SecurityFilterChain;
 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@@ -398,41 +395,6 @@ public class HttpSecurityConfigurationTests {
 		this.mockMvc.perform(formLogin()).andExpectAll(status().isNotFound(), unauthenticated());
 	}
 
-	@Test
-	void loginWhenCompromisePasswordCheckerConfiguredAndPasswordCompromisedThenUnauthorized() throws Exception {
-		this.spring
-			.register(SecurityEnabledConfig.class, UserDetailsConfig.class, CompromisedPasswordCheckerConfig.class)
-			.autowire();
-		this.mockMvc.perform(formLogin().password("password"))
-			.andExpectAll(status().isFound(), redirectedUrl("/login?error"), unauthenticated());
-	}
-
-	@Test
-	void loginWhenCompromisedPasswordAndRedirectIfPasswordExceptionThenRedirectedToResetPassword() throws Exception {
-		this.spring
-			.register(SecurityEnabledRedirectIfPasswordExceptionConfig.class, UserDetailsConfig.class,
-					CompromisedPasswordCheckerConfig.class)
-			.autowire();
-		this.mockMvc.perform(formLogin().password("password"))
-			.andExpectAll(status().isFound(), redirectedUrl("/reset-password"), unauthenticated());
-	}
-
-	@Test
-	void loginWhenCompromisePasswordCheckerConfiguredAndPasswordNotCompromisedThenSuccess() throws Exception {
-		this.spring
-			.register(SecurityEnabledConfig.class, UserDetailsConfig.class, CompromisedPasswordCheckerConfig.class)
-			.autowire();
-		UserDetailsManager userDetailsManager = this.spring.getContext().getBean(UserDetailsManager.class);
-		UserDetails notCompromisedPwUser = User.withDefaultPasswordEncoder()
-			.username("user2")
-			.password("password2")
-			.roles("USER")
-			.build();
-		userDetailsManager.createUser(notCompromisedPwUser);
-		this.mockMvc.perform(formLogin().user("user2").password("password2"))
-			.andExpectAll(status().isFound(), redirectedUrl("/"), authenticated());
-	}
-
 	@RestController
 	static class NameController {
 
@@ -493,7 +455,7 @@ public class HttpSecurityConfigurationTests {
 	static class UserDetailsConfig {
 
 		@Bean
-		InMemoryUserDetailsManager userDetailsService() {
+		UserDetailsService userDetailsService() {
 			// @formatter:off
 			UserDetails user = User.withDefaultPasswordEncoder()
 					.username("user")
@@ -770,52 +732,4 @@ public class HttpSecurityConfigurationTests {
 
 	}
 
-	@Configuration(proxyBeanMethods = false)
-	static class CompromisedPasswordCheckerConfig {
-
-		@Bean
-		TestCompromisedPasswordChecker compromisedPasswordChecker() {
-			return new TestCompromisedPasswordChecker();
-		}
-
-	}
-
-	@Configuration(proxyBeanMethods = false)
-	@EnableWebSecurity
-	static class SecurityEnabledRedirectIfPasswordExceptionConfig {
-
-		@Bean
-		SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
-			// @formatter:off
-			return http
-					.authorizeHttpRequests((authorize) -> authorize
-							.anyRequest().authenticated()
-					)
-					.formLogin((form) -> form
-							.failureHandler((request, response, exception) -> {
-								if (exception instanceof CompromisedPasswordException) {
-									response.sendRedirect("/reset-password");
-									return;
-								}
-								response.sendRedirect("/login?error");
-							})
-					)
-					.build();
-			// @formatter:on
-		}
-
-	}
-
-	private static class TestCompromisedPasswordChecker implements CompromisedPasswordChecker {
-
-		@Override
-		public CompromisedPasswordCheckResult check(String password) {
-			if ("password".equals(password)) {
-				return new CompromisedPasswordCheckResult(true);
-			}
-			return new CompromisedPasswordCheckResult(false);
-		}
-
-	}
-
 }

+ 83 - 76
config/src/test/java/org/springframework/security/config/annotation/web/configuration/OAuth2AuthorizedClientManagerConfigurationTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2023 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -38,6 +38,8 @@ import org.springframework.context.annotation.Configuration;
 import org.springframework.mock.web.MockHttpServletRequest;
 import org.springframework.mock.web.MockHttpServletResponse;
 import org.springframework.security.authentication.TestingAuthenticationToken;
+import org.springframework.security.config.Customizer;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.oauth2.client.CommonOAuth2Provider;
 import org.springframework.security.config.test.SpringTestContext;
 import org.springframework.security.oauth2.client.AuthorizationCodeOAuth2AuthorizedClientProvider;
@@ -50,7 +52,6 @@ import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
 import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
 import org.springframework.security.oauth2.client.PasswordOAuth2AuthorizedClientProvider;
 import org.springframework.security.oauth2.client.RefreshTokenOAuth2AuthorizedClientProvider;
-import org.springframework.security.oauth2.client.TokenExchangeOAuth2AuthorizedClientProvider;
 import org.springframework.security.oauth2.client.endpoint.AbstractOAuth2AuthorizationGrantRequest;
 import org.springframework.security.oauth2.client.endpoint.JwtBearerGrantRequest;
 import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
@@ -58,14 +59,17 @@ import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCo
 import org.springframework.security.oauth2.client.endpoint.OAuth2ClientCredentialsGrantRequest;
 import org.springframework.security.oauth2.client.endpoint.OAuth2PasswordGrantRequest;
 import org.springframework.security.oauth2.client.endpoint.OAuth2RefreshTokenGrantRequest;
-import org.springframework.security.oauth2.client.endpoint.TokenExchangeGrantRequest;
+import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
+import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
 import org.springframework.security.oauth2.client.registration.ClientRegistration;
 import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
 import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
+import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
+import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
+import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
 import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager;
 import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
 import org.springframework.security.oauth2.core.AuthorizationGrantType;
-import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
 import org.springframework.security.oauth2.core.OAuth2AccessToken;
 import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
 import org.springframework.security.oauth2.core.OAuth2Error;
@@ -73,10 +77,13 @@ import org.springframework.security.oauth2.core.TestOAuth2RefreshTokens;
 import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
 import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
 import org.springframework.security.oauth2.core.endpoint.TestOAuth2AccessTokenResponses;
+import org.springframework.security.oauth2.core.oidc.user.OidcUser;
+import org.springframework.security.oauth2.core.user.OAuth2User;
 import org.springframework.security.oauth2.jwt.JoseHeaderNames;
 import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.security.oauth2.jwt.JwtClaimNames;
 import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
+import org.springframework.security.web.SecurityFilterChain;
 import org.springframework.util.StringUtils;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -320,47 +327,6 @@ public class OAuth2AuthorizedClientManagerConfigurationTests {
 		assertThat(grantRequest.getJwt().getSubject()).isEqualTo("user");
 	}
 
-	@Test
-	public void authorizeWhenTokenExchangeAccessTokenResponseClientBeanThenUsed() {
-		this.spring.register(CustomAccessTokenResponseClientsConfig.class).autowire();
-		testTokenExchangeGrant();
-	}
-
-	@Test
-	public void authorizeWhenTokenExchangeAuthorizedClientProviderBeanThenUsed() {
-		this.spring.register(CustomAuthorizedClientProvidersConfig.class).autowire();
-		testTokenExchangeGrant();
-	}
-
-	private void testTokenExchangeGrant() {
-		OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build();
-		given(MOCK_RESPONSE_CLIENT.getTokenResponse(any(TokenExchangeGrantRequest.class)))
-			.willReturn(accessTokenResponse);
-
-		JwtAuthenticationToken authentication = new JwtAuthenticationToken(getJwt());
-		ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId("auth0");
-		// @formatter:off
-		OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest
-				.withClientRegistrationId(clientRegistration.getRegistrationId())
-				.principal(authentication)
-				.attribute(HttpServletRequest.class.getName(), this.request)
-				.attribute(HttpServletResponse.class.getName(), this.response)
-				.build();
-		// @formatter:on
-		OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest);
-		assertThat(authorizedClient).isNotNull();
-
-		ArgumentCaptor<TokenExchangeGrantRequest> grantRequestCaptor = ArgumentCaptor
-			.forClass(TokenExchangeGrantRequest.class);
-		verify(MOCK_RESPONSE_CLIENT).getTokenResponse(grantRequestCaptor.capture());
-
-		TokenExchangeGrantRequest grantRequest = grantRequestCaptor.getValue();
-		assertThat(grantRequest.getClientRegistration().getRegistrationId())
-			.isEqualTo(clientRegistration.getRegistrationId());
-		assertThat(grantRequest.getGrantType()).isEqualTo(AuthorizationGrantType.TOKEN_EXCHANGE);
-		assertThat(grantRequest.getSubjectToken()).isEqualTo(authentication.getToken());
-	}
-
 	private static OAuth2AccessToken getExpiredAccessToken() {
 		Instant expiresAt = Instant.now().minusSeconds(60);
 		Instant issuedAt = expiresAt.minus(Duration.ofDays(1));
@@ -387,32 +353,37 @@ public class OAuth2AuthorizedClientManagerConfigurationTests {
 
 		@Bean
 		OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> authorizationCodeTokenResponseClient() {
-			return new MockAccessTokenResponseClient<>();
+			return new MockAuthorizationCodeClient();
 		}
 
 		@Bean
 		OAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> refreshTokenTokenResponseClient() {
-			return new MockAccessTokenResponseClient<>();
+			return new MockRefreshTokenClient();
 		}
 
 		@Bean
 		OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> clientCredentialsTokenResponseClient() {
-			return new MockAccessTokenResponseClient<>();
+			return new MockClientCredentialsClient();
 		}
 
 		@Bean
 		OAuth2AccessTokenResponseClient<OAuth2PasswordGrantRequest> passwordTokenResponseClient() {
-			return new MockAccessTokenResponseClient<>();
+			return new MockPasswordClient();
 		}
 
 		@Bean
 		OAuth2AccessTokenResponseClient<JwtBearerGrantRequest> jwtBearerTokenResponseClient() {
-			return new MockAccessTokenResponseClient<>();
+			return new MockJwtBearerClient();
+		}
+
+		@Bean
+		OAuth2UserService<OAuth2UserRequest, OAuth2User> oauth2UserService() {
+			return mock(DefaultOAuth2UserService.class);
 		}
 
 		@Bean
-		OAuth2AccessTokenResponseClient<TokenExchangeGrantRequest> tokenExchangeTokenResponseClient() {
-			return new MockAccessTokenResponseClient<>();
+		OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService() {
+			return mock(OidcUserService.class);
 		}
 
 	}
@@ -429,35 +400,28 @@ public class OAuth2AuthorizedClientManagerConfigurationTests {
 		@Bean
 		RefreshTokenOAuth2AuthorizedClientProvider refreshTokenProvider() {
 			RefreshTokenOAuth2AuthorizedClientProvider authorizedClientProvider = new RefreshTokenOAuth2AuthorizedClientProvider();
-			authorizedClientProvider.setAccessTokenResponseClient(new MockAccessTokenResponseClient<>());
+			authorizedClientProvider.setAccessTokenResponseClient(new MockRefreshTokenClient());
 			return authorizedClientProvider;
 		}
 
 		@Bean
 		ClientCredentialsOAuth2AuthorizedClientProvider clientCredentialsProvider() {
 			ClientCredentialsOAuth2AuthorizedClientProvider authorizedClientProvider = new ClientCredentialsOAuth2AuthorizedClientProvider();
-			authorizedClientProvider.setAccessTokenResponseClient(new MockAccessTokenResponseClient<>());
+			authorizedClientProvider.setAccessTokenResponseClient(new MockClientCredentialsClient());
 			return authorizedClientProvider;
 		}
 
 		@Bean
 		PasswordOAuth2AuthorizedClientProvider passwordProvider() {
 			PasswordOAuth2AuthorizedClientProvider authorizedClientProvider = new PasswordOAuth2AuthorizedClientProvider();
-			authorizedClientProvider.setAccessTokenResponseClient(new MockAccessTokenResponseClient<>());
+			authorizedClientProvider.setAccessTokenResponseClient(new MockPasswordClient());
 			return authorizedClientProvider;
 		}
 
 		@Bean
 		JwtBearerOAuth2AuthorizedClientProvider jwtBearerAuthorizedClientProvider() {
 			JwtBearerOAuth2AuthorizedClientProvider authorizedClientProvider = new JwtBearerOAuth2AuthorizedClientProvider();
-			authorizedClientProvider.setAccessTokenResponseClient(new MockAccessTokenResponseClient<>());
-			return authorizedClientProvider;
-		}
-
-		@Bean
-		TokenExchangeOAuth2AuthorizedClientProvider tokenExchangeAuthorizedClientProvider() {
-			TokenExchangeOAuth2AuthorizedClientProvider authorizedClientProvider = new TokenExchangeOAuth2AuthorizedClientProvider();
-			authorizedClientProvider.setAccessTokenResponseClient(new MockAccessTokenResponseClient<>());
+			authorizedClientProvider.setAccessTokenResponseClient(new MockJwtBearerClient());
 			return authorizedClientProvider;
 		}
 
@@ -465,10 +429,21 @@ public class OAuth2AuthorizedClientManagerConfigurationTests {
 
 	abstract static class OAuth2ClientBaseConfig {
 
+		@Bean
+		SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeHttpRequests((authorize) -> authorize.anyRequest().authenticated())
+				.oauth2Login(Customizer.withDefaults())
+				.oauth2Client(Customizer.withDefaults());
+			return http.build();
+			// @formatter:on
+		}
+
 		@Bean
 		ClientRegistrationRepository clientRegistrationRepository() {
 			// @formatter:off
-			return new InMemoryClientRegistrationRepository(
+			return new InMemoryClientRegistrationRepository(Arrays.asList(
 					CommonOAuth2Provider.GOOGLE.getBuilder("google")
 							.clientId("google-client-id")
 							.clientSecret("google-client-secret")
@@ -488,15 +463,7 @@ public class OAuth2AuthorizedClientManagerConfigurationTests {
 							.clientId("okta-client-id")
 							.clientSecret("okta-client-secret")
 							.authorizationGrantType(AuthorizationGrantType.JWT_BEARER)
-							.build(),
-					ClientRegistration.withRegistrationId("auth0")
-							.clientName("Auth0")
-							.clientId("auth0-client-id")
-							.clientSecret("auth0-client-secret")
-							.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
-							.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE)
-							.scope("user.read", "user.write")
-							.build());
+							.build()));
 			// @formatter:on
 		}
 
@@ -527,11 +494,51 @@ public class OAuth2AuthorizedClientManagerConfigurationTests {
 
 	}
 
-	private static class MockAccessTokenResponseClient<T extends AbstractOAuth2AuthorizationGrantRequest>
-			implements OAuth2AccessTokenResponseClient<T> {
+	private static class MockAuthorizationCodeClient
+			implements OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> {
+
+		@Override
+		public OAuth2AccessTokenResponse getTokenResponse(
+				OAuth2AuthorizationCodeGrantRequest authorizationGrantRequest) {
+			return MOCK_RESPONSE_CLIENT.getTokenResponse(authorizationGrantRequest);
+		}
+
+	}
+
+	private static class MockRefreshTokenClient
+			implements OAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> {
+
+		@Override
+		public OAuth2AccessTokenResponse getTokenResponse(OAuth2RefreshTokenGrantRequest authorizationGrantRequest) {
+			return MOCK_RESPONSE_CLIENT.getTokenResponse(authorizationGrantRequest);
+		}
+
+	}
+
+	private static class MockClientCredentialsClient
+			implements OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> {
+
+		@Override
+		public OAuth2AccessTokenResponse getTokenResponse(
+				OAuth2ClientCredentialsGrantRequest authorizationGrantRequest) {
+			return MOCK_RESPONSE_CLIENT.getTokenResponse(authorizationGrantRequest);
+		}
+
+	}
+
+	private static class MockPasswordClient implements OAuth2AccessTokenResponseClient<OAuth2PasswordGrantRequest> {
+
+		@Override
+		public OAuth2AccessTokenResponse getTokenResponse(OAuth2PasswordGrantRequest authorizationGrantRequest) {
+			return MOCK_RESPONSE_CLIENT.getTokenResponse(authorizationGrantRequest);
+		}
+
+	}
+
+	private static class MockJwtBearerClient implements OAuth2AccessTokenResponseClient<JwtBearerGrantRequest> {
 
 		@Override
-		public OAuth2AccessTokenResponse getTokenResponse(T authorizationGrantRequest) {
+		public OAuth2AccessTokenResponse getTokenResponse(JwtBearerGrantRequest authorizationGrantRequest) {
 			return MOCK_RESPONSE_CLIENT.getTokenResponse(authorizationGrantRequest);
 		}
 

+ 0 - 51
config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurerTests.java

@@ -40,10 +40,8 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
 import org.springframework.security.config.core.GrantedAuthorityDefaults;
 import org.springframework.security.config.test.SpringTestContext;
 import org.springframework.security.config.test.SpringTestContextExtension;
-import org.springframework.security.core.Authentication;
 import org.springframework.security.core.authority.AuthorityUtils;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
-import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.security.provisioning.InMemoryUserDetailsManager;
 import org.springframework.security.web.SecurityFilterChain;
@@ -545,17 +543,6 @@ public class AuthorizeHttpRequestsConfigurerTests {
 		this.mvc.perform(request).andExpect(status().isOk());
 		request = get("/user/deny");
 		this.mvc.perform(request).andExpect(status().isUnauthorized());
-
-		UserDetails user = TestAuthentication.withUsername("taehong").build();
-		Authentication authentication = TestAuthentication.authenticated(user);
-		request = get("/v2/user/{username}", user.getUsername()).with(authentication(authentication));
-		this.mvc.perform(request).andExpect(status().isOk());
-
-		request = get("/v2/user/{username}", "withNoAuthentication");
-		this.mvc.perform(request).andExpect(status().isUnauthorized());
-
-		request = get("/v2/user/{username}", "another").with(authentication(authentication));
-		this.mvc.perform(request).andExpect(status().isForbidden());
 	}
 
 	private static RequestPostProcessor remoteAddress(String remoteAddress) {
@@ -609,20 +596,6 @@ public class AuthorizeHttpRequestsConfigurerTests {
 		this.mvc.perform(requestWithUser).andExpect(status().isForbidden());
 	}
 
-	@Test
-	public void getWhenNotConfigAndAuthenticatedThenRespondsWithForbidden() throws Exception {
-		this.spring.register(NotConfig.class, BasicController.class).autowire();
-		MockHttpServletRequestBuilder requestWithUser = get("/").with(user("user"));
-		this.mvc.perform(requestWithUser).andExpect(status().isForbidden());
-	}
-
-	@Test
-	public void getWhenNotConfigAndNotAuthenticatedThenRespondsWithOk() throws Exception {
-		this.spring.register(NotConfig.class, BasicController.class).autowire();
-		MockHttpServletRequestBuilder requestWithUser = get("/");
-		this.mvc.perform(requestWithUser).andExpect(status().isOk());
-	}
-
 	@Configuration
 	@EnableWebSecurity
 	static class GrantedAuthorityDefaultHasRoleConfig {
@@ -1080,7 +1053,6 @@ public class AuthorizeHttpRequestsConfigurerTests {
 				.httpBasic(withDefaults())
 				.authorizeHttpRequests((requests) -> requests
 					.requestMatchers("/user/{username}").access(new WebExpressionAuthorizationManager("#username == 'user'"))
-					.requestMatchers("/v2/user/{username}").hasVariable("username").equalTo(Authentication::getName)
 				);
 			// @formatter:on
 			return http.build();
@@ -1094,11 +1066,6 @@ public class AuthorizeHttpRequestsConfigurerTests {
 				return username;
 			}
 
-			@RequestMapping("/v2/user/{username}")
-			String pathV2(@PathVariable("username") String username) {
-				return username;
-			}
-
 		}
 
 	}
@@ -1169,24 +1136,6 @@ public class AuthorizeHttpRequestsConfigurerTests {
 
 	}
 
-	@Configuration
-	@EnableWebSecurity
-	static class NotConfig {
-
-		@Bean
-		SecurityFilterChain chain(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.httpBasic(withDefaults())
-				.authorizeHttpRequests((requests) -> requests
-					.anyRequest().not().authenticated()
-				);
-			// @formatter:on
-			return http.build();
-		}
-
-	}
-
 	@Configuration
 	static class AuthorizationEventPublisherConfig {
 

+ 0 - 589
config/src/test/java/org/springframework/security/config/annotation/web/reactive/ReactiveOAuth2AuthorizedClientManagerConfigurationTests.java

@@ -1,589 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.config.annotation.web.reactive;
-
-import java.time.Duration;
-import java.time.Instant;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Objects;
-import java.util.function.Consumer;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.mockito.ArgumentCaptor;
-import reactor.core.publisher.Mono;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.http.MediaType;
-import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
-import org.springframework.mock.web.server.MockServerWebExchange;
-import org.springframework.security.authentication.TestingAuthenticationToken;
-import org.springframework.security.config.oauth2.client.CommonOAuth2Provider;
-import org.springframework.security.config.test.SpringTestContext;
-import org.springframework.security.oauth2.client.AuthorizationCodeReactiveOAuth2AuthorizedClientProvider;
-import org.springframework.security.oauth2.client.ClientAuthorizationRequiredException;
-import org.springframework.security.oauth2.client.ClientCredentialsReactiveOAuth2AuthorizedClientProvider;
-import org.springframework.security.oauth2.client.JwtBearerReactiveOAuth2AuthorizedClientProvider;
-import org.springframework.security.oauth2.client.OAuth2AuthorizationContext;
-import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest;
-import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
-import org.springframework.security.oauth2.client.PasswordReactiveOAuth2AuthorizedClientProvider;
-import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientManager;
-import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientService;
-import org.springframework.security.oauth2.client.RefreshTokenReactiveOAuth2AuthorizedClientProvider;
-import org.springframework.security.oauth2.client.TokenExchangeReactiveOAuth2AuthorizedClientProvider;
-import org.springframework.security.oauth2.client.endpoint.AbstractOAuth2AuthorizationGrantRequest;
-import org.springframework.security.oauth2.client.endpoint.JwtBearerGrantRequest;
-import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest;
-import org.springframework.security.oauth2.client.endpoint.OAuth2ClientCredentialsGrantRequest;
-import org.springframework.security.oauth2.client.endpoint.OAuth2PasswordGrantRequest;
-import org.springframework.security.oauth2.client.endpoint.OAuth2RefreshTokenGrantRequest;
-import org.springframework.security.oauth2.client.endpoint.ReactiveOAuth2AccessTokenResponseClient;
-import org.springframework.security.oauth2.client.endpoint.TokenExchangeGrantRequest;
-import org.springframework.security.oauth2.client.registration.ClientRegistration;
-import org.springframework.security.oauth2.client.registration.InMemoryReactiveClientRegistrationRepository;
-import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
-import org.springframework.security.oauth2.client.web.DefaultReactiveOAuth2AuthorizedClientManager;
-import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository;
-import org.springframework.security.oauth2.client.web.server.WebSessionServerOAuth2AuthorizedClientRepository;
-import org.springframework.security.oauth2.core.AuthorizationGrantType;
-import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
-import org.springframework.security.oauth2.core.OAuth2AccessToken;
-import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
-import org.springframework.security.oauth2.core.OAuth2Error;
-import org.springframework.security.oauth2.core.TestOAuth2RefreshTokens;
-import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
-import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
-import org.springframework.security.oauth2.core.endpoint.TestOAuth2AccessTokenResponses;
-import org.springframework.security.oauth2.jwt.JoseHeaderNames;
-import org.springframework.security.oauth2.jwt.Jwt;
-import org.springframework.security.oauth2.jwt.JwtClaimNames;
-import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
-import org.springframework.util.StringUtils;
-import org.springframework.web.server.ServerWebExchange;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.BDDMockito.given;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-
-/**
- * Tests for
- * {@link ReactiveOAuth2ClientConfiguration.ReactiveOAuth2AuthorizedClientManagerConfiguration}.
- *
- * @author Steve Riesenberg
- */
-public class ReactiveOAuth2AuthorizedClientManagerConfigurationTests {
-
-	private static ReactiveOAuth2AccessTokenResponseClient<? super AbstractOAuth2AuthorizationGrantRequest> MOCK_RESPONSE_CLIENT;
-
-	public final SpringTestContext spring = new SpringTestContext(this);
-
-	@Autowired
-	private ReactiveOAuth2AuthorizedClientManager authorizedClientManager;
-
-	@Autowired
-	private ReactiveClientRegistrationRepository clientRegistrationRepository;
-
-	@Autowired(required = false)
-	private ServerOAuth2AuthorizedClientRepository authorizedClientRepository;
-
-	@Autowired(required = false)
-	private ReactiveOAuth2AuthorizedClientService authorizedClientService;
-
-	@Autowired(required = false)
-	private AuthorizationCodeReactiveOAuth2AuthorizedClientProvider authorizationCodeAuthorizedClientProvider;
-
-	private MockServerWebExchange exchange;
-
-	@BeforeEach
-	@SuppressWarnings("unchecked")
-	public void setUp() {
-		MOCK_RESPONSE_CLIENT = mock(ReactiveOAuth2AccessTokenResponseClient.class);
-		MockServerHttpRequest request = MockServerHttpRequest.get("/").build();
-		this.exchange = MockServerWebExchange.builder(request).build();
-	}
-
-	@Test
-	public void loadContextWhenOAuth2ClientEnabledThenConfigured() {
-		this.spring.register(MinimalOAuth2ClientConfig.class).autowire();
-		assertThat(this.authorizedClientManager).isNotNull();
-	}
-
-	@Test
-	public void authorizeWhenAuthorizationCodeAuthorizedClientProviderBeanThenUsed() {
-		this.spring.register(CustomAuthorizedClientProvidersConfig.class).autowire();
-
-		TestingAuthenticationToken authentication = new TestingAuthenticationToken("user", null, "ROLE_USER");
-		// @formatter:off
-		OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest
-				.withClientRegistrationId("google")
-				.principal(authentication)
-				.attribute(ServerWebExchange.class.getName(), this.exchange)
-				.build();
-		assertThatExceptionOfType(ClientAuthorizationRequiredException.class)
-				.isThrownBy(() -> this.authorizedClientManager.authorize(authorizeRequest).block())
-				.extracting(OAuth2AuthorizationException::getError)
-				.extracting(OAuth2Error::getErrorCode)
-				.isEqualTo("client_authorization_required");
-		// @formatter:on
-
-		verify(this.authorizationCodeAuthorizedClientProvider).authorize(any(OAuth2AuthorizationContext.class));
-	}
-
-	@Test
-	public void authorizeWhenAuthorizedClientServiceBeanThenUsed() {
-		this.spring.register(CustomAuthorizedClientServiceConfig.class).autowire();
-
-		TestingAuthenticationToken authentication = new TestingAuthenticationToken("user", null, "ROLE_USER");
-		// @formatter:off
-		OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest
-				.withClientRegistrationId("google")
-				.principal(authentication)
-				.attribute(ServerWebExchange.class.getName(), this.exchange)
-				.build();
-		assertThatExceptionOfType(ClientAuthorizationRequiredException.class)
-				.isThrownBy(() -> this.authorizedClientManager.authorize(authorizeRequest).block())
-				.extracting(OAuth2AuthorizationException::getError)
-				.extracting(OAuth2Error::getErrorCode)
-				.isEqualTo("client_authorization_required");
-		// @formatter:on
-
-		verify(this.authorizedClientService).loadAuthorizedClient(authorizeRequest.getClientRegistrationId(),
-				authentication.getName());
-	}
-
-	@Test
-	public void authorizeWhenRefreshTokenAccessTokenResponseClientBeanThenUsed() {
-		this.spring.register(CustomAccessTokenResponseClientsConfig.class).autowire();
-		testRefreshTokenGrant();
-	}
-
-	@Test
-	public void authorizeWhenRefreshTokenAuthorizedClientProviderBeanThenUsed() {
-		this.spring.register(CustomAuthorizedClientProvidersConfig.class).autowire();
-		testRefreshTokenGrant();
-	}
-
-	private void testRefreshTokenGrant() {
-		OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build();
-		given(MOCK_RESPONSE_CLIENT.getTokenResponse(any(OAuth2RefreshTokenGrantRequest.class)))
-			.willReturn(Mono.just(accessTokenResponse));
-
-		TestingAuthenticationToken authentication = new TestingAuthenticationToken("user", null, "ROLE_USER");
-		ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId("google")
-			.block();
-		assertThat(clientRegistration).isNotNull();
-		OAuth2AuthorizedClient existingAuthorizedClient = new OAuth2AuthorizedClient(clientRegistration,
-				authentication.getName(), getExpiredAccessToken(), TestOAuth2RefreshTokens.refreshToken());
-		this.authorizedClientRepository.saveAuthorizedClient(existingAuthorizedClient, authentication, this.exchange)
-			.block();
-		// @formatter:off
-		OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest
-				.withClientRegistrationId(clientRegistration.getRegistrationId())
-				.principal(authentication)
-				.attribute(ServerWebExchange.class.getName(), this.exchange)
-				.build();
-		// @formatter:on
-		OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest).block();
-		assertThat(authorizedClient).isNotNull();
-
-		ArgumentCaptor<OAuth2RefreshTokenGrantRequest> grantRequestCaptor = ArgumentCaptor
-			.forClass(OAuth2RefreshTokenGrantRequest.class);
-		verify(MOCK_RESPONSE_CLIENT).getTokenResponse(grantRequestCaptor.capture());
-
-		OAuth2RefreshTokenGrantRequest grantRequest = grantRequestCaptor.getValue();
-		assertThat(grantRequest.getClientRegistration().getRegistrationId())
-			.isEqualTo(clientRegistration.getRegistrationId());
-		assertThat(grantRequest.getGrantType()).isEqualTo(AuthorizationGrantType.REFRESH_TOKEN);
-		assertThat(grantRequest.getAccessToken()).isEqualTo(existingAuthorizedClient.getAccessToken());
-		assertThat(grantRequest.getRefreshToken()).isEqualTo(existingAuthorizedClient.getRefreshToken());
-	}
-
-	@Test
-	public void authorizeWhenClientCredentialsAccessTokenResponseClientBeanThenUsed() {
-		this.spring.register(CustomAccessTokenResponseClientsConfig.class).autowire();
-		testClientCredentialsGrant();
-	}
-
-	@Test
-	public void authorizeWhenClientCredentialsAuthorizedClientProviderBeanThenUsed() {
-		this.spring.register(CustomAuthorizedClientProvidersConfig.class).autowire();
-		testClientCredentialsGrant();
-	}
-
-	private void testClientCredentialsGrant() {
-		OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build();
-		given(MOCK_RESPONSE_CLIENT.getTokenResponse(any(OAuth2ClientCredentialsGrantRequest.class)))
-			.willReturn(Mono.just(accessTokenResponse));
-
-		TestingAuthenticationToken authentication = new TestingAuthenticationToken("user", null, "ROLE_USER");
-		ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId("github")
-			.block();
-		assertThat(clientRegistration).isNotNull();
-		// @formatter:off
-		OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest
-				.withClientRegistrationId(clientRegistration.getRegistrationId())
-				.principal(authentication)
-				.attribute(ServerWebExchange.class.getName(), this.exchange)
-				.build();
-		// @formatter:on
-		OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest).block();
-		assertThat(authorizedClient).isNotNull();
-
-		ArgumentCaptor<OAuth2ClientCredentialsGrantRequest> grantRequestCaptor = ArgumentCaptor
-			.forClass(OAuth2ClientCredentialsGrantRequest.class);
-		verify(MOCK_RESPONSE_CLIENT).getTokenResponse(grantRequestCaptor.capture());
-
-		OAuth2ClientCredentialsGrantRequest grantRequest = grantRequestCaptor.getValue();
-		assertThat(grantRequest.getClientRegistration().getRegistrationId())
-			.isEqualTo(clientRegistration.getRegistrationId());
-		assertThat(grantRequest.getGrantType()).isEqualTo(AuthorizationGrantType.CLIENT_CREDENTIALS);
-	}
-
-	@Test
-	public void authorizeWhenPasswordAccessTokenResponseClientBeanThenUsed() {
-		this.spring.register(CustomAccessTokenResponseClientsConfig.class).autowire();
-		testPasswordGrant();
-	}
-
-	@Test
-	public void authorizeWhenPasswordAuthorizedClientProviderBeanThenUsed() {
-		this.spring.register(CustomAuthorizedClientProvidersConfig.class).autowire();
-		testPasswordGrant();
-	}
-
-	private void testPasswordGrant() {
-		OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build();
-		given(MOCK_RESPONSE_CLIENT.getTokenResponse(any(OAuth2PasswordGrantRequest.class)))
-			.willReturn(Mono.just(accessTokenResponse));
-
-		TestingAuthenticationToken authentication = new TestingAuthenticationToken("user", "password", "ROLE_USER");
-		ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId("facebook")
-			.block();
-		assertThat(clientRegistration).isNotNull();
-		MockServerHttpRequest request = MockServerHttpRequest.post("/")
-			.contentType(MediaType.APPLICATION_FORM_URLENCODED)
-			.body("username=user&password=password");
-		this.exchange = MockServerWebExchange.builder(request).build();
-		// @formatter:off
-		OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest
-				.withClientRegistrationId(clientRegistration.getRegistrationId())
-				.principal(authentication)
-				.attribute(ServerWebExchange.class.getName(), this.exchange)
-				.build();
-		// @formatter:on
-		OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest).block();
-		assertThat(authorizedClient).isNotNull();
-
-		ArgumentCaptor<OAuth2PasswordGrantRequest> grantRequestCaptor = ArgumentCaptor
-			.forClass(OAuth2PasswordGrantRequest.class);
-		verify(MOCK_RESPONSE_CLIENT).getTokenResponse(grantRequestCaptor.capture());
-
-		OAuth2PasswordGrantRequest grantRequest = grantRequestCaptor.getValue();
-		assertThat(grantRequest.getClientRegistration().getRegistrationId())
-			.isEqualTo(clientRegistration.getRegistrationId());
-		assertThat(grantRequest.getGrantType()).isEqualTo(AuthorizationGrantType.PASSWORD);
-		assertThat(grantRequest.getUsername()).isEqualTo("user");
-		assertThat(grantRequest.getPassword()).isEqualTo("password");
-	}
-
-	@Test
-	public void authorizeWhenJwtBearerAccessTokenResponseClientBeanThenUsed() {
-		this.spring.register(CustomAccessTokenResponseClientsConfig.class).autowire();
-		testJwtBearerGrant();
-	}
-
-	@Test
-	public void authorizeWhenJwtBearerAuthorizedClientProviderBeanThenUsed() {
-		this.spring.register(CustomAuthorizedClientProvidersConfig.class).autowire();
-		testJwtBearerGrant();
-	}
-
-	private void testJwtBearerGrant() {
-		OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build();
-		given(MOCK_RESPONSE_CLIENT.getTokenResponse(any(JwtBearerGrantRequest.class)))
-			.willReturn(Mono.just(accessTokenResponse));
-
-		JwtAuthenticationToken authentication = new JwtAuthenticationToken(getJwt());
-		ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId("okta").block();
-		assertThat(clientRegistration).isNotNull();
-		// @formatter:off
-		OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest
-				.withClientRegistrationId(clientRegistration.getRegistrationId())
-				.principal(authentication)
-				.attribute(ServerWebExchange.class.getName(), this.exchange)
-				.build();
-		// @formatter:on
-		OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest).block();
-		assertThat(authorizedClient).isNotNull();
-
-		ArgumentCaptor<JwtBearerGrantRequest> grantRequestCaptor = ArgumentCaptor.forClass(JwtBearerGrantRequest.class);
-		verify(MOCK_RESPONSE_CLIENT).getTokenResponse(grantRequestCaptor.capture());
-
-		JwtBearerGrantRequest grantRequest = grantRequestCaptor.getValue();
-		assertThat(grantRequest.getClientRegistration().getRegistrationId())
-			.isEqualTo(clientRegistration.getRegistrationId());
-		assertThat(grantRequest.getGrantType()).isEqualTo(AuthorizationGrantType.JWT_BEARER);
-		assertThat(grantRequest.getJwt().getSubject()).isEqualTo("user");
-	}
-
-	@Test
-	public void authorizeWhenTokenExchangeAccessTokenResponseClientBeanThenUsed() {
-		this.spring.register(CustomAccessTokenResponseClientsConfig.class).autowire();
-		testTokenExchangeGrant();
-	}
-
-	@Test
-	public void authorizeWhenTokenExchangeAuthorizedClientProviderBeanThenUsed() {
-		this.spring.register(CustomAuthorizedClientProvidersConfig.class).autowire();
-		testTokenExchangeGrant();
-	}
-
-	private void testTokenExchangeGrant() {
-		OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build();
-		given(MOCK_RESPONSE_CLIENT.getTokenResponse(any(TokenExchangeGrantRequest.class)))
-			.willReturn(Mono.just(accessTokenResponse));
-
-		JwtAuthenticationToken authentication = new JwtAuthenticationToken(getJwt());
-		ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId("auth0").block();
-		assertThat(clientRegistration).isNotNull();
-		// @formatter:off
-		OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest
-				.withClientRegistrationId(clientRegistration.getRegistrationId())
-				.principal(authentication)
-				.attribute(ServerWebExchange.class.getName(), this.exchange)
-				.build();
-		// @formatter:on
-		OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest).block();
-		assertThat(authorizedClient).isNotNull();
-
-		ArgumentCaptor<TokenExchangeGrantRequest> grantRequestCaptor = ArgumentCaptor
-			.forClass(TokenExchangeGrantRequest.class);
-		verify(MOCK_RESPONSE_CLIENT).getTokenResponse(grantRequestCaptor.capture());
-
-		TokenExchangeGrantRequest grantRequest = grantRequestCaptor.getValue();
-		assertThat(grantRequest.getClientRegistration().getRegistrationId())
-			.isEqualTo(clientRegistration.getRegistrationId());
-		assertThat(grantRequest.getGrantType()).isEqualTo(AuthorizationGrantType.TOKEN_EXCHANGE);
-		assertThat(grantRequest.getSubjectToken()).isEqualTo(authentication.getToken());
-	}
-
-	private static OAuth2AccessToken getExpiredAccessToken() {
-		Instant expiresAt = Instant.now().minusSeconds(60);
-		Instant issuedAt = expiresAt.minus(Duration.ofDays(1));
-		return new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "scopes", issuedAt, expiresAt,
-				new HashSet<>(Arrays.asList("read", "write")));
-	}
-
-	private static Jwt getJwt() {
-		Instant issuedAt = Instant.now();
-		return new Jwt("token", issuedAt, issuedAt.plusSeconds(300),
-				Collections.singletonMap(JoseHeaderNames.ALG, "RS256"),
-				Collections.singletonMap(JwtClaimNames.SUB, "user"));
-	}
-
-	@Configuration
-	@EnableWebFluxSecurity
-	static class MinimalOAuth2ClientConfig extends OAuth2ClientBaseConfig {
-
-		@Bean
-		ServerOAuth2AuthorizedClientRepository authorizedClientRepository() {
-			return new WebSessionServerOAuth2AuthorizedClientRepository();
-		}
-
-	}
-
-	@Configuration
-	@EnableWebFluxSecurity
-	static class CustomAuthorizedClientServiceConfig extends OAuth2ClientBaseConfig {
-
-		@Bean
-		ReactiveOAuth2AuthorizedClientService authorizedClientService() {
-			ReactiveOAuth2AuthorizedClientService authorizedClientService = mock(
-					ReactiveOAuth2AuthorizedClientService.class);
-			given(authorizedClientService.loadAuthorizedClient(anyString(), anyString())).willReturn(Mono.empty());
-			return authorizedClientService;
-		}
-
-	}
-
-	@Configuration
-	@EnableWebFluxSecurity
-	static class CustomAccessTokenResponseClientsConfig extends MinimalOAuth2ClientConfig {
-
-		@Bean
-		ReactiveOAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> authorizationCodeAccessTokenResponseClient() {
-			return new MockAccessTokenResponseClient<>();
-		}
-
-		@Bean
-		ReactiveOAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> refreshTokenTokenAccessResponseClient() {
-			return new MockAccessTokenResponseClient<>();
-		}
-
-		@Bean
-		ReactiveOAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> clientCredentialsAccessTokenResponseClient() {
-			return new MockAccessTokenResponseClient<>();
-		}
-
-		@Bean
-		ReactiveOAuth2AccessTokenResponseClient<OAuth2PasswordGrantRequest> passwordAccessTokenResponseClient() {
-			return new MockAccessTokenResponseClient<>();
-		}
-
-		@Bean
-		ReactiveOAuth2AccessTokenResponseClient<JwtBearerGrantRequest> jwtBearerAccessTokenResponseClient() {
-			return new MockAccessTokenResponseClient<>();
-		}
-
-		@Bean
-		ReactiveOAuth2AccessTokenResponseClient<TokenExchangeGrantRequest> tokenExchangeAccessTokenResponseClient() {
-			return new MockAccessTokenResponseClient<>();
-		}
-
-	}
-
-	@Configuration
-	@EnableWebFluxSecurity
-	static class CustomAuthorizedClientProvidersConfig extends MinimalOAuth2ClientConfig {
-
-		@Bean
-		AuthorizationCodeReactiveOAuth2AuthorizedClientProvider authorizationCode() {
-			return spy(new AuthorizationCodeReactiveOAuth2AuthorizedClientProvider());
-		}
-
-		@Bean
-		RefreshTokenReactiveOAuth2AuthorizedClientProvider refreshToken() {
-			RefreshTokenReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = new RefreshTokenReactiveOAuth2AuthorizedClientProvider();
-			authorizedClientProvider.setAccessTokenResponseClient(new MockAccessTokenResponseClient<>());
-			return authorizedClientProvider;
-		}
-
-		@Bean
-		ClientCredentialsReactiveOAuth2AuthorizedClientProvider clientCredentials() {
-			ClientCredentialsReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = new ClientCredentialsReactiveOAuth2AuthorizedClientProvider();
-			authorizedClientProvider.setAccessTokenResponseClient(new MockAccessTokenResponseClient<>());
-			return authorizedClientProvider;
-		}
-
-		@Bean
-		PasswordReactiveOAuth2AuthorizedClientProvider password() {
-			PasswordReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = new PasswordReactiveOAuth2AuthorizedClientProvider();
-			authorizedClientProvider.setAccessTokenResponseClient(new MockAccessTokenResponseClient<>());
-			return authorizedClientProvider;
-		}
-
-		@Bean
-		JwtBearerReactiveOAuth2AuthorizedClientProvider jwtBearer() {
-			JwtBearerReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = new JwtBearerReactiveOAuth2AuthorizedClientProvider();
-			authorizedClientProvider.setAccessTokenResponseClient(new MockAccessTokenResponseClient<>());
-			return authorizedClientProvider;
-		}
-
-		@Bean
-		TokenExchangeReactiveOAuth2AuthorizedClientProvider tokenExchange() {
-			TokenExchangeReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = new TokenExchangeReactiveOAuth2AuthorizedClientProvider();
-			authorizedClientProvider.setAccessTokenResponseClient(new MockAccessTokenResponseClient<>());
-			return authorizedClientProvider;
-		}
-
-	}
-
-	abstract static class OAuth2ClientBaseConfig {
-
-		@Bean
-		ReactiveClientRegistrationRepository clientRegistrationRepository() {
-			// @formatter:off
-			return new InMemoryReactiveClientRegistrationRepository(
-					CommonOAuth2Provider.GOOGLE.getBuilder("google")
-						.clientId("google-client-id")
-						.clientSecret("google-client-secret")
-						.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
-						.build(),
-					CommonOAuth2Provider.GITHUB.getBuilder("github")
-						.clientId("github-client-id")
-						.clientSecret("github-client-secret")
-						.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
-						.build(),
-					CommonOAuth2Provider.FACEBOOK.getBuilder("facebook")
-						.clientId("facebook-client-id")
-						.clientSecret("facebook-client-secret")
-						.authorizationGrantType(AuthorizationGrantType.PASSWORD)
-						.build(),
-					CommonOAuth2Provider.OKTA.getBuilder("okta")
-						.clientId("okta-client-id")
-						.clientSecret("okta-client-secret")
-						.authorizationGrantType(AuthorizationGrantType.JWT_BEARER)
-						.build(),
-					ClientRegistration.withRegistrationId("auth0")
-						.clientName("Auth0")
-						.clientId("auth0-client-id")
-						.clientSecret("auth0-client-secret")
-						.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
-						.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE)
-						.scope("user.read", "user.write")
-						.build());
-			// @formatter:on
-		}
-
-		@Bean
-		Consumer<DefaultReactiveOAuth2AuthorizedClientManager> authorizedClientManagerConsumer() {
-			return (authorizedClientManager) -> authorizedClientManager
-				.setContextAttributesMapper((authorizeRequest) -> {
-					ServerWebExchange exchange = Objects
-						.requireNonNull(authorizeRequest.getAttribute(ServerWebExchange.class.getName()));
-					return exchange.getFormData().map((parameters) -> {
-						String username = parameters.getFirst(OAuth2ParameterNames.USERNAME);
-						String password = parameters.getFirst(OAuth2ParameterNames.PASSWORD);
-
-						Map<String, Object> attributes = Collections.emptyMap();
-						if (StringUtils.hasText(username) && StringUtils.hasText(password)) {
-							attributes = new HashMap<>();
-							attributes.put(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, username);
-							attributes.put(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, password);
-						}
-
-						return attributes;
-					});
-				});
-
-		}
-
-	}
-
-	private static class MockAccessTokenResponseClient<T extends AbstractOAuth2AuthorizationGrantRequest>
-			implements ReactiveOAuth2AccessTokenResponseClient<T> {
-
-		@Override
-		public Mono<OAuth2AccessTokenResponse> getTokenResponse(T grantRequest) {
-			return MOCK_RESPONSE_CLIENT.getTokenResponse(grantRequest);
-		}
-
-	}
-
-}

+ 0 - 175
config/src/test/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfigurationTests.java

@@ -16,39 +16,16 @@
 
 package org.springframework.security.config.annotation.web.reactive;
 
-import java.net.URI;
-
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
-import reactor.core.publisher.Mono;
 
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.security.authentication.password.CompromisedPasswordCheckResult;
-import org.springframework.security.authentication.password.CompromisedPasswordException;
-import org.springframework.security.authentication.password.ReactiveCompromisedPasswordChecker;
-import org.springframework.security.config.Customizer;
 import org.springframework.security.config.test.SpringTestContext;
 import org.springframework.security.config.test.SpringTestContextExtension;
 import org.springframework.security.config.users.ReactiveAuthenticationTestConfiguration;
 import org.springframework.security.config.web.server.ServerHttpSecurity;
-import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
-import org.springframework.security.core.userdetails.PasswordEncodedUser;
-import org.springframework.security.core.userdetails.User;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.web.server.DefaultServerRedirectStrategy;
-import org.springframework.security.web.server.SecurityWebFilterChain;
-import org.springframework.test.web.reactive.server.WebTestClient;
-import org.springframework.util.LinkedMultiValueMap;
-import org.springframework.util.MultiValueMap;
-import org.springframework.web.reactive.config.EnableWebFlux;
-import org.springframework.web.reactive.function.BodyInserters;
-import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.csrf;
 
 /**
  * Tests for {@link ServerHttpSecurityConfiguration}.
@@ -60,16 +37,6 @@ public class ServerHttpSecurityConfigurationTests {
 
 	public final SpringTestContext spring = new SpringTestContext(this);
 
-	WebTestClient webClient;
-
-	@Autowired
-	void setup(ApplicationContext context) {
-		if (!context.containsBean(WebHttpHandlerBuilder.WEB_HANDLER_BEAN_NAME)) {
-			return;
-		}
-		this.webClient = WebTestClient.bindToApplicationContext(context).configureClient().build();
-	}
-
 	@Test
 	public void loadConfigWhenReactiveUserDetailsServiceConfiguredThenServerHttpSecurityExists() {
 		this.spring
@@ -90,151 +57,9 @@ public class ServerHttpSecurityConfigurationTests {
 		assertThat(serverHttpSecurity).isNotNull();
 	}
 
-	@Test
-	void loginWhenCompromisePasswordCheckerConfiguredAndPasswordCompromisedThenUnauthorized() {
-		this.spring.register(FormLoginConfig.class, UserDetailsConfig.class, CompromisedPasswordCheckerConfig.class)
-			.autowire();
-		MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
-		data.add("username", "user");
-		data.add("password", "password");
-		// @formatter:off
-		this.webClient.mutateWith(csrf())
-				.post()
-				.uri("/login")
-				.body(BodyInserters.fromFormData(data))
-				.exchange()
-				.expectStatus().is3xxRedirection()
-				.expectHeader().location("/login?error");
-		// @formatter:on
-	}
-
-	@Test
-	void loginWhenCompromisePasswordCheckerConfiguredAndPasswordNotCompromisedThenUnauthorized() {
-		this.spring.register(FormLoginConfig.class, UserDetailsConfig.class, CompromisedPasswordCheckerConfig.class)
-			.autowire();
-		MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
-		data.add("username", "admin");
-		data.add("password", "password2");
-		// @formatter:off
-		this.webClient.mutateWith(csrf())
-				.post()
-				.uri("/login")
-				.body(BodyInserters.fromFormData(data))
-				.exchange()
-				.expectStatus().is3xxRedirection()
-				.expectHeader().location("/");
-		// @formatter:on
-	}
-
-	@Test
-	void loginWhenCompromisedPasswordAndRedirectIfPasswordExceptionThenRedirectedToResetPassword() {
-		this.spring
-			.register(FormLoginRedirectToResetPasswordConfig.class, UserDetailsConfig.class,
-					CompromisedPasswordCheckerConfig.class)
-			.autowire();
-		MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
-		data.add("username", "user");
-		data.add("password", "password");
-		// @formatter:off
-		this.webClient.mutateWith(csrf())
-				.post()
-				.uri("/login")
-				.body(BodyInserters.fromFormData(data))
-				.exchange()
-				.expectStatus().is3xxRedirection()
-				.expectHeader().location("/reset-password");
-		// @formatter:on
-	}
-
 	@Configuration
 	static class SubclassConfig extends ServerHttpSecurityConfiguration {
 
 	}
 
-	@Configuration(proxyBeanMethods = false)
-	@EnableWebFlux
-	@EnableWebFluxSecurity
-	static class FormLoginConfig {
-
-		@Bean
-		SecurityWebFilterChain filterChain(ServerHttpSecurity http) {
-			// @formatter:off
-			http
-					.authorizeExchange((exchange) -> exchange
-						.anyExchange().authenticated()
-					)
-					.formLogin(Customizer.withDefaults());
-			// @formatter:on
-			return http.build();
-		}
-
-	}
-
-	@Configuration(proxyBeanMethods = false)
-	@EnableWebFlux
-	@EnableWebFluxSecurity
-	static class FormLoginRedirectToResetPasswordConfig {
-
-		@Bean
-		SecurityWebFilterChain filterChain(ServerHttpSecurity http) {
-			// @formatter:off
-			http
-					.authorizeExchange((exchange) -> exchange
-						.anyExchange().authenticated()
-					)
-					.formLogin((form) -> form
-							.authenticationFailureHandler((webFilterExchange, exception) -> {
-								String redirectUrl = "/login?error";
-								if (exception instanceof CompromisedPasswordException) {
-									redirectUrl = "/reset-password";
-								}
-								return new DefaultServerRedirectStrategy().sendRedirect(webFilterExchange.getExchange(), URI.create(redirectUrl));
-							})
-					);
-			// @formatter:on
-			return http.build();
-		}
-
-	}
-
-	@Configuration(proxyBeanMethods = false)
-	static class UserDetailsConfig {
-
-		@Bean
-		MapReactiveUserDetailsService userDetailsService() {
-			// @formatter:off
-			UserDetails user = PasswordEncodedUser.user();
-			UserDetails admin = User.withDefaultPasswordEncoder()
-					.username("admin")
-					.password("password2")
-					.roles("USER", "ADMIN")
-					.build();
-			// @formatter:on
-			return new MapReactiveUserDetailsService(user, admin);
-		}
-
-	}
-
-	@Configuration(proxyBeanMethods = false)
-	static class CompromisedPasswordCheckerConfig {
-
-		@Bean
-		TestReactivePasswordChecker compromisedPasswordChecker() {
-			return new TestReactivePasswordChecker();
-		}
-
-	}
-
-	static class TestReactivePasswordChecker implements ReactiveCompromisedPasswordChecker {
-
-		@Override
-		public Mono<CompromisedPasswordCheckResult> check(String password) {
-			if ("password".equals(password)) {
-				return Mono.just(new CompromisedPasswordCheckResult(true));
-			}
-			return Mono.just(new CompromisedPasswordCheckResult(false));
-		}
-
-	}
-
 }

+ 3 - 3
config/src/test/java/org/springframework/security/config/doc/XsdDocumentedTests.java

@@ -65,7 +65,7 @@ public class XsdDocumentedTests {
 
 	String schema31xDocumentLocation = "org/springframework/security/config/spring-security-3.1.xsd";
 
-	String schemaDocumentLocation = "org/springframework/security/config/spring-security-6.3.xsd";
+	String schemaDocumentLocation = "org/springframework/security/config/spring-security-6.2.xsd";
 
 	XmlSupport xml = new XmlSupport();
 
@@ -151,8 +151,8 @@ public class XsdDocumentedTests {
 				.list((dir, name) -> name.endsWith(".xsd"));
 		// @formatter:on
 		assertThat(schemas.length)
-			.withFailMessage("the count is equal to 25, if not then schemaDocument needs updating")
-			.isEqualTo(25);
+			.withFailMessage("the count is equal to 24, if not then schemaDocument needs updating")
+			.isEqualTo(24);
 	}
 
 	/**

+ 51 - 72
config/src/test/java/org/springframework/security/config/http/OAuth2AuthorizedClientManagerRegistrarTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2023 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -49,20 +49,18 @@ import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
 import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
 import org.springframework.security.oauth2.client.PasswordOAuth2AuthorizedClientProvider;
 import org.springframework.security.oauth2.client.RefreshTokenOAuth2AuthorizedClientProvider;
-import org.springframework.security.oauth2.client.TokenExchangeOAuth2AuthorizedClientProvider;
 import org.springframework.security.oauth2.client.endpoint.AbstractOAuth2AuthorizationGrantRequest;
 import org.springframework.security.oauth2.client.endpoint.JwtBearerGrantRequest;
 import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
+import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest;
 import org.springframework.security.oauth2.client.endpoint.OAuth2ClientCredentialsGrantRequest;
 import org.springframework.security.oauth2.client.endpoint.OAuth2PasswordGrantRequest;
 import org.springframework.security.oauth2.client.endpoint.OAuth2RefreshTokenGrantRequest;
-import org.springframework.security.oauth2.client.endpoint.TokenExchangeGrantRequest;
 import org.springframework.security.oauth2.client.registration.ClientRegistration;
 import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
 import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager;
 import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
 import org.springframework.security.oauth2.core.AuthorizationGrantType;
-import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
 import org.springframework.security.oauth2.core.OAuth2AccessToken;
 import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
 import org.springframework.security.oauth2.core.OAuth2Error;
@@ -318,47 +316,6 @@ public class OAuth2AuthorizedClientManagerRegistrarTests {
 		assertThat(grantRequest.getJwt().getSubject()).isEqualTo("user");
 	}
 
-	@Test
-	public void authorizeWhenTokenExchangeAccessTokenResponseClientBeanThenUsed() {
-		this.spring.configLocations(xml("clients")).autowire();
-		testTokenExchangeGrant();
-	}
-
-	@Test
-	public void authorizeWhenTokenExchangeAuthorizedClientProviderBeanThenUsed() {
-		this.spring.configLocations(xml("providers")).autowire();
-		testTokenExchangeGrant();
-	}
-
-	private void testTokenExchangeGrant() {
-		OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build();
-		given(MOCK_RESPONSE_CLIENT.getTokenResponse(any(TokenExchangeGrantRequest.class)))
-			.willReturn(accessTokenResponse);
-
-		JwtAuthenticationToken authentication = new JwtAuthenticationToken(getJwt());
-		ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId("auth0");
-		// @formatter:off
-		OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest
-				.withClientRegistrationId(clientRegistration.getRegistrationId())
-				.principal(authentication)
-				.attribute(HttpServletRequest.class.getName(), this.request)
-				.attribute(HttpServletResponse.class.getName(), this.response)
-				.build();
-		// @formatter:on
-		OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest);
-		assertThat(authorizedClient).isNotNull();
-
-		ArgumentCaptor<TokenExchangeGrantRequest> grantRequestCaptor = ArgumentCaptor
-			.forClass(TokenExchangeGrantRequest.class);
-		verify(MOCK_RESPONSE_CLIENT).getTokenResponse(grantRequestCaptor.capture());
-
-		TokenExchangeGrantRequest grantRequest = grantRequestCaptor.getValue();
-		assertThat(grantRequest.getClientRegistration().getRegistrationId())
-			.isEqualTo(clientRegistration.getRegistrationId());
-		assertThat(grantRequest.getGrantType()).isEqualTo(AuthorizationGrantType.TOKEN_EXCHANGE);
-		assertThat(grantRequest.getSubjectToken()).isEqualTo(authentication.getToken());
-	}
-
 	private static OAuth2AccessToken getExpiredAccessToken() {
 		Instant expiresAt = Instant.now().minusSeconds(60);
 		Instant issuedAt = expiresAt.minus(Duration.ofDays(1));
@@ -399,14 +356,6 @@ public class OAuth2AuthorizedClientManagerRegistrarTests {
 						.clientId("okta-client-id")
 						.clientSecret("okta-client-secret")
 						.authorizationGrantType(AuthorizationGrantType.JWT_BEARER)
-						.build(),
-				ClientRegistration.withRegistrationId("auth0")
-						.clientName("Auth0")
-						.clientId("auth0-client-id")
-						.clientSecret("auth0-client-secret")
-						.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
-						.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE)
-						.scope("user.read", "user.write")
 						.build());
 		// @formatter:on
 	}
@@ -429,65 +378,95 @@ public class OAuth2AuthorizedClientManagerRegistrarTests {
 		});
 	}
 
-	public static AuthorizationCodeOAuth2AuthorizedClientProvider authorizationCode() {
+	public static AuthorizationCodeOAuth2AuthorizedClientProvider authorizationCodeAuthorizedClientProvider() {
 		return spy(new AuthorizationCodeOAuth2AuthorizedClientProvider());
 	}
 
-	public static RefreshTokenOAuth2AuthorizedClientProvider refreshToken() {
+	public static RefreshTokenOAuth2AuthorizedClientProvider refreshTokenAuthorizedClientProvider() {
 		RefreshTokenOAuth2AuthorizedClientProvider authorizedClientProvider = new RefreshTokenOAuth2AuthorizedClientProvider();
 		authorizedClientProvider.setAccessTokenResponseClient(refreshTokenAccessTokenResponseClient());
 		return authorizedClientProvider;
 	}
 
-	public static OAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> refreshTokenAccessTokenResponseClient() {
-		return new MockAccessTokenResponseClient<>();
+	public static MockRefreshTokenClient refreshTokenAccessTokenResponseClient() {
+		return new MockRefreshTokenClient();
 	}
 
-	public static ClientCredentialsOAuth2AuthorizedClientProvider clientCredentials() {
+	public static ClientCredentialsOAuth2AuthorizedClientProvider clientCredentialsAuthorizedClientProvider() {
 		ClientCredentialsOAuth2AuthorizedClientProvider authorizedClientProvider = new ClientCredentialsOAuth2AuthorizedClientProvider();
 		authorizedClientProvider.setAccessTokenResponseClient(clientCredentialsAccessTokenResponseClient());
 		return authorizedClientProvider;
 	}
 
 	public static OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> clientCredentialsAccessTokenResponseClient() {
-		return new MockAccessTokenResponseClient<>();
+		return new MockClientCredentialsClient();
 	}
 
-	public static PasswordOAuth2AuthorizedClientProvider password() {
+	public static PasswordOAuth2AuthorizedClientProvider passwordAuthorizedClientProvider() {
 		PasswordOAuth2AuthorizedClientProvider authorizedClientProvider = new PasswordOAuth2AuthorizedClientProvider();
 		authorizedClientProvider.setAccessTokenResponseClient(passwordAccessTokenResponseClient());
 		return authorizedClientProvider;
 	}
 
 	public static OAuth2AccessTokenResponseClient<OAuth2PasswordGrantRequest> passwordAccessTokenResponseClient() {
-		return new MockAccessTokenResponseClient<>();
+		return new MockPasswordClient();
 	}
 
-	public static JwtBearerOAuth2AuthorizedClientProvider jwtBearer() {
+	public static JwtBearerOAuth2AuthorizedClientProvider jwtBearerAuthorizedClientProvider() {
 		JwtBearerOAuth2AuthorizedClientProvider authorizedClientProvider = new JwtBearerOAuth2AuthorizedClientProvider();
 		authorizedClientProvider.setAccessTokenResponseClient(jwtBearerAccessTokenResponseClient());
 		return authorizedClientProvider;
 	}
 
 	public static OAuth2AccessTokenResponseClient<JwtBearerGrantRequest> jwtBearerAccessTokenResponseClient() {
-		return new MockAccessTokenResponseClient<>();
+		return new MockJwtBearerClient();
 	}
 
-	public static TokenExchangeOAuth2AuthorizedClientProvider tokenExchange() {
-		TokenExchangeOAuth2AuthorizedClientProvider authorizedClientProvider = new TokenExchangeOAuth2AuthorizedClientProvider();
-		authorizedClientProvider.setAccessTokenResponseClient(tokenExchangeAccessTokenResponseClient());
-		return authorizedClientProvider;
+	private static class MockAuthorizationCodeClient
+			implements OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> {
+
+		@Override
+		public OAuth2AccessTokenResponse getTokenResponse(
+				OAuth2AuthorizationCodeGrantRequest authorizationGrantRequest) {
+			return MOCK_RESPONSE_CLIENT.getTokenResponse(authorizationGrantRequest);
+		}
+
 	}
 
-	public static OAuth2AccessTokenResponseClient<TokenExchangeGrantRequest> tokenExchangeAccessTokenResponseClient() {
-		return new MockAccessTokenResponseClient<>();
+	private static class MockRefreshTokenClient
+			implements OAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> {
+
+		@Override
+		public OAuth2AccessTokenResponse getTokenResponse(OAuth2RefreshTokenGrantRequest authorizationGrantRequest) {
+			return MOCK_RESPONSE_CLIENT.getTokenResponse(authorizationGrantRequest);
+		}
+
+	}
+
+	private static class MockClientCredentialsClient
+			implements OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> {
+
+		@Override
+		public OAuth2AccessTokenResponse getTokenResponse(
+				OAuth2ClientCredentialsGrantRequest authorizationGrantRequest) {
+			return MOCK_RESPONSE_CLIENT.getTokenResponse(authorizationGrantRequest);
+		}
+
+	}
+
+	private static class MockPasswordClient implements OAuth2AccessTokenResponseClient<OAuth2PasswordGrantRequest> {
+
+		@Override
+		public OAuth2AccessTokenResponse getTokenResponse(OAuth2PasswordGrantRequest authorizationGrantRequest) {
+			return MOCK_RESPONSE_CLIENT.getTokenResponse(authorizationGrantRequest);
+		}
+
 	}
 
-	private static class MockAccessTokenResponseClient<T extends AbstractOAuth2AuthorizationGrantRequest>
-			implements OAuth2AccessTokenResponseClient<T> {
+	private static class MockJwtBearerClient implements OAuth2AccessTokenResponseClient<JwtBearerGrantRequest> {
 
 		@Override
-		public OAuth2AccessTokenResponse getTokenResponse(T authorizationGrantRequest) {
+		public OAuth2AccessTokenResponse getTokenResponse(JwtBearerGrantRequest authorizationGrantRequest) {
 			return MOCK_RESPONSE_CLIENT.getTokenResponse(authorizationGrantRequest);
 		}
 

+ 0 - 20
config/src/test/java/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests.java

@@ -16,7 +16,6 @@
 
 package org.springframework.security.config.saml2;
 
-import jakarta.servlet.http.HttpServletRequest;
 import okhttp3.mockwebserver.MockResponse;
 import okhttp3.mockwebserver.MockWebServer;
 import org.junit.jupiter.api.AfterEach;
@@ -24,21 +23,16 @@ import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.core.convert.converter.Converter;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.MediaType;
-import org.springframework.mock.web.MockHttpServletRequest;
 import org.springframework.security.config.test.SpringTestContext;
 import org.springframework.security.config.test.SpringTestContextExtension;
 import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository;
 import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
 import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
 import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
-import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.verify;
 
 /**
  * Tests for {@link RelyingPartyRegistrationsBeanDefinitionParser}.
@@ -124,7 +118,6 @@ public class RelyingPartyRegistrationsBeanDefinitionParserTests {
 	// @formatter:on
 
 	@Autowired
-	@Qualifier("registrations")
 	private RelyingPartyRegistrationRepository relyingPartyRegistrationRepository;
 
 	public final SpringTestContext spring = new SpringTestContext(this);
@@ -275,19 +268,6 @@ public class RelyingPartyRegistrationsBeanDefinitionParserTests {
 				"http://www.w3.org/2001/04/xmldsig-more#rsa-sha384");
 	}
 
-	@Test
-	public void parseWhenRelayStateResolverThenUses() {
-		this.spring.configLocations(xml("RelayStateResolver")).autowire();
-		Converter<HttpServletRequest, String> relayStateResolver = this.spring.getContext().getBean(Converter.class);
-		OpenSaml4AuthenticationRequestResolver authenticationRequestResolver = this.spring.getContext()
-			.getBean(OpenSaml4AuthenticationRequestResolver.class);
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		request.setRequestURI("/saml2/authenticate/one");
-		request.setServletPath("/saml2/authenticate/one");
-		authenticationRequestResolver.resolve(request);
-		verify(relayStateResolver).convert(request);
-	}
-
 	private static MockResponse xmlResponse(String xml) {
 		return new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE).setBody(xml);
 	}

+ 2 - 8
config/src/test/java/org/springframework/security/config/web/server/ServerHttpSecurityTests.java

@@ -56,11 +56,9 @@ import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
 import org.springframework.security.web.server.ServerRedirectStrategy;
 import org.springframework.security.web.server.WebFilterChainProxy;
 import org.springframework.security.web.server.authentication.AnonymousAuthenticationWebFilterTests;
-import org.springframework.security.web.server.authentication.DelegatingServerAuthenticationSuccessHandler;
 import org.springframework.security.web.server.authentication.HttpBasicServerAuthenticationEntryPoint;
 import org.springframework.security.web.server.authentication.HttpStatusServerEntryPoint;
 import org.springframework.security.web.server.authentication.ServerAuthenticationFailureHandler;
-import org.springframework.security.web.server.authentication.ServerAuthenticationSuccessHandler;
 import org.springframework.security.web.server.authentication.ServerX509AuthenticationConverter;
 import org.springframework.security.web.server.authentication.logout.DelegatingServerLogoutHandler;
 import org.springframework.security.web.server.authentication.logout.LogoutWebFilter;
@@ -594,7 +592,6 @@ public class ServerHttpSecurityTests {
 	}
 
 	@Test
-	@SuppressWarnings("unchecked")
 	public void shouldConfigureRequestCacheForOAuth2LoginAuthenticationEntryPointAndSuccessHandler() {
 		ServerRequestCache requestCache = spy(new WebSessionServerRequestCache());
 		ReactiveClientRegistrationRepository clientRegistrationRepository = mock(
@@ -616,11 +613,8 @@ public class ServerHttpSecurityTests {
 		OAuth2LoginAuthenticationWebFilter authenticationWebFilter = getWebFilter(securityFilterChain,
 				OAuth2LoginAuthenticationWebFilter.class)
 			.get();
-		DelegatingServerAuthenticationSuccessHandler handler = (DelegatingServerAuthenticationSuccessHandler) ReflectionTestUtils
-			.getField(authenticationWebFilter, "authenticationSuccessHandler");
-		List<ServerAuthenticationSuccessHandler> delegates = (List<ServerAuthenticationSuccessHandler>) ReflectionTestUtils
-			.getField(handler, "delegates");
-		assertThat(ReflectionTestUtils.getField(delegates.get(0), "requestCache")).isSameAs(requestCache);
+		Object handler = ReflectionTestUtils.getField(authenticationWebFilter, "authenticationSuccessHandler");
+		assertThat(ReflectionTestUtils.getField(handler, "requestCache")).isSameAs(requestCache);
 	}
 
 	@Test

+ 0 - 587
config/src/test/java/org/springframework/security/config/web/server/SessionManagementSpecTests.java

@@ -1,587 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.config.web.server;
-
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import reactor.core.publisher.Mono;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Import;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseCookie;
-import org.springframework.security.authentication.ReactiveAuthenticationManager;
-import org.springframework.security.authentication.TestingAuthenticationToken;
-import org.springframework.security.config.Customizer;
-import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
-import org.springframework.security.config.test.SpringTestContext;
-import org.springframework.security.config.test.SpringTestContextExtension;
-import org.springframework.security.config.users.ReactiveAuthenticationTestConfiguration;
-import org.springframework.security.core.session.InMemoryReactiveSessionRegistry;
-import org.springframework.security.core.session.ReactiveSessionRegistry;
-import org.springframework.security.oauth2.client.authentication.OAuth2LoginAuthenticationToken;
-import org.springframework.security.oauth2.client.registration.InMemoryReactiveClientRegistrationRepository;
-import org.springframework.security.oauth2.client.registration.TestClientRegistrations;
-import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizationRequestResolver;
-import org.springframework.security.oauth2.core.OAuth2AccessToken;
-import org.springframework.security.oauth2.core.TestOAuth2AccessTokens;
-import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationExchange;
-import org.springframework.security.oauth2.core.endpoint.TestOAuth2AuthorizationExchanges;
-import org.springframework.security.oauth2.core.user.OAuth2User;
-import org.springframework.security.oauth2.core.user.TestOAuth2Users;
-import org.springframework.security.web.server.SecurityWebFilterChain;
-import org.springframework.security.web.server.authentication.InvalidateLeastUsedServerMaximumSessionsExceededHandler;
-import org.springframework.security.web.server.authentication.PreventLoginServerMaximumSessionsExceededHandler;
-import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler;
-import org.springframework.security.web.server.authentication.ServerAuthenticationConverter;
-import org.springframework.security.web.server.authentication.SessionLimit;
-import org.springframework.security.web.server.context.WebSessionServerSecurityContextRepository;
-import org.springframework.test.context.junit.jupiter.SpringExtension;
-import org.springframework.test.web.reactive.server.WebTestClient;
-import org.springframework.util.LinkedMultiValueMap;
-import org.springframework.util.MultiValueMap;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.reactive.config.EnableWebFlux;
-import org.springframework.web.reactive.function.BodyInserters;
-import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
-import org.springframework.web.server.session.DefaultWebSessionManager;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.BDDMockito.given;
-import static org.mockito.Mockito.mock;
-import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.csrf;
-
-@ExtendWith({ SpringExtension.class, SpringTestContextExtension.class })
-public class SessionManagementSpecTests {
-
-	public final SpringTestContext spring = new SpringTestContext(this);
-
-	WebTestClient client;
-
-	@Autowired
-	public void setApplicationContext(ApplicationContext context) {
-		this.client = WebTestClient.bindToApplicationContext(context).build();
-	}
-
-	@Test
-	void loginWhenMaxSessionPreventsLoginThenSecondLoginFails() {
-		this.spring.register(ConcurrentSessionsMaxSessionPreventsLoginConfig.class).autowire();
-
-		MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
-		data.add("username", "user");
-		data.add("password", "password");
-
-		ResponseCookie firstLoginSessionCookie = loginReturningCookie(data);
-
-		// second login should fail
-		ResponseCookie secondLoginSessionCookie = this.client.mutateWith(csrf())
-			.post()
-			.uri("/login")
-			.contentType(MediaType.MULTIPART_FORM_DATA)
-			.body(BodyInserters.fromFormData(data))
-			.exchange()
-			.expectHeader()
-			.location("/login?error")
-			.returnResult(Void.class)
-			.getResponseCookies()
-			.getFirst("SESSION");
-
-		assertThat(secondLoginSessionCookie).isNull();
-
-		// first login should still be valid
-		this.client.mutateWith(csrf())
-			.get()
-			.uri("/")
-			.cookie(firstLoginSessionCookie.getName(), firstLoginSessionCookie.getValue())
-			.exchange()
-			.expectStatus()
-			.isOk();
-	}
-
-	@Test
-	void httpBasicWhenUsingSavingAuthenticationInWebSessionAndPreventLoginThenSecondRequestFails() {
-		this.spring.register(ConcurrentSessionsHttpBasicWithWebSessionMaxSessionPreventsLoginConfig.class).autowire();
-
-		MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
-		data.add("username", "user");
-		data.add("password", "password");
-
-		// first request be successful
-		ResponseCookie sessionCookie = this.client.get()
-			.uri("/")
-			.headers((headers) -> headers.setBasicAuth("user", "password"))
-			.exchange()
-			.expectStatus()
-			.isOk()
-			.expectCookie()
-			.exists("SESSION")
-			.returnResult(Void.class)
-			.getResponseCookies()
-			.getFirst("SESSION");
-
-		// request with no session should fail
-		this.client.get()
-			.uri("/")
-			.headers((headers) -> headers.setBasicAuth("user", "password"))
-			.exchange()
-			.expectStatus()
-			.isUnauthorized();
-
-		// request with session obtained from first request should be successful
-		this.client.get()
-			.uri("/")
-			.headers((headers) -> headers.setBasicAuth("user", "password"))
-			.cookie(sessionCookie.getName(), sessionCookie.getValue())
-			.exchange()
-			.expectStatus()
-			.isOk();
-	}
-
-	@Test
-	void loginWhenMaxSessionPerAuthenticationThenUserLoginFailsAndAdminLoginSucceeds() {
-		ConcurrentSessionsMaxSessionPreventsLoginConfig.sessionLimit = (authentication) -> {
-			if (authentication.getName().equals("admin")) {
-				return Mono.empty();
-			}
-			return Mono.just(1);
-		};
-		this.spring.register(ConcurrentSessionsMaxSessionPreventsLoginConfig.class).autowire();
-
-		MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
-		data.add("username", "user");
-		data.add("password", "password");
-		MultiValueMap<String, String> adminCreds = new LinkedMultiValueMap<>();
-		adminCreds.add("username", "admin");
-		adminCreds.add("password", "password");
-
-		ResponseCookie userFirstLoginSessionCookie = loginReturningCookie(data);
-		ResponseCookie adminFirstLoginSessionCookie = loginReturningCookie(adminCreds);
-		// second user login should fail
-		this.client.mutateWith(csrf())
-			.post()
-			.uri("/login")
-			.contentType(MediaType.MULTIPART_FORM_DATA)
-			.body(BodyInserters.fromFormData(data))
-			.exchange()
-			.expectHeader()
-			.location("/login?error");
-		// first login should still be valid
-		this.client.mutateWith(csrf())
-			.get()
-			.uri("/")
-			.cookie(userFirstLoginSessionCookie.getName(), userFirstLoginSessionCookie.getValue())
-			.exchange()
-			.expectStatus()
-			.isOk();
-		ResponseCookie adminSecondLoginSessionCookie = loginReturningCookie(adminCreds);
-		this.client.mutateWith(csrf())
-			.get()
-			.uri("/")
-			.cookie(adminFirstLoginSessionCookie.getName(), adminFirstLoginSessionCookie.getValue())
-			.exchange()
-			.expectStatus()
-			.isOk();
-		this.client.mutateWith(csrf())
-			.get()
-			.uri("/")
-			.cookie(adminSecondLoginSessionCookie.getName(), adminSecondLoginSessionCookie.getValue())
-			.exchange()
-			.expectStatus()
-			.isOk();
-	}
-
-	@Test
-	void loginWhenMaxSessionDoesNotPreventLoginThenSecondLoginSucceedsAndFirstSessionIsInvalidated() {
-		ConcurrentSessionsMaxSessionPreventsLoginFalseConfig.sessionLimit = SessionLimit.of(1);
-		this.spring.register(ConcurrentSessionsMaxSessionPreventsLoginFalseConfig.class).autowire();
-
-		MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
-		data.add("username", "user");
-		data.add("password", "password");
-
-		ResponseCookie firstLoginSessionCookie = loginReturningCookie(data);
-		ResponseCookie secondLoginSessionCookie = loginReturningCookie(data);
-
-		// first login should not be valid
-		this.client.get()
-			.uri("/")
-			.cookie(firstLoginSessionCookie.getName(), firstLoginSessionCookie.getValue())
-			.exchange()
-			.expectStatus()
-			.isFound()
-			.expectHeader()
-			.location("/login");
-
-		// second login should be valid
-		this.client.get()
-			.uri("/")
-			.cookie(secondLoginSessionCookie.getName(), secondLoginSessionCookie.getValue())
-			.exchange()
-			.expectStatus()
-			.isOk();
-	}
-
-	@Test
-	void loginWhenMaxSessionDoesNotPreventLoginThenLeastRecentlyUsedSessionIsInvalidated() {
-		ConcurrentSessionsMaxSessionPreventsLoginFalseConfig.sessionLimit = SessionLimit.of(2);
-		this.spring.register(ConcurrentSessionsMaxSessionPreventsLoginFalseConfig.class).autowire();
-
-		MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
-		data.add("username", "user");
-		data.add("password", "password");
-
-		ResponseCookie firstLoginSessionCookie = loginReturningCookie(data);
-		ResponseCookie secondLoginSessionCookie = loginReturningCookie(data);
-
-		// update last access time for first request
-		this.client.get()
-			.uri("/")
-			.cookie(firstLoginSessionCookie.getName(), firstLoginSessionCookie.getValue())
-			.exchange()
-			.expectStatus()
-			.isOk();
-
-		ResponseCookie thirdLoginSessionCookie = loginReturningCookie(data);
-
-		// second login should be invalid, it is the least recently used session
-		this.client.get()
-			.uri("/")
-			.cookie(secondLoginSessionCookie.getName(), secondLoginSessionCookie.getValue())
-			.exchange()
-			.expectStatus()
-			.isFound()
-			.expectHeader()
-			.location("/login");
-
-		// first login should be valid
-		this.client.get()
-			.uri("/")
-			.cookie(firstLoginSessionCookie.getName(), firstLoginSessionCookie.getValue())
-			.exchange()
-			.expectStatus()
-			.isOk();
-
-		// third login should be valid
-		this.client.get()
-			.uri("/")
-			.cookie(thirdLoginSessionCookie.getName(), thirdLoginSessionCookie.getValue())
-			.exchange()
-			.expectStatus()
-			.isOk();
-	}
-
-	@Test
-	void oauth2LoginWhenMaxSessionsThenPreventLogin() {
-		OAuth2LoginConcurrentSessionsConfig.maxSessions = 1;
-		OAuth2LoginConcurrentSessionsConfig.preventLogin = true;
-		this.spring.register(OAuth2LoginConcurrentSessionsConfig.class).autowire();
-		prepareOAuth2Config();
-		// @formatter:off
-		ResponseCookie sessionCookie = this.client.get()
-				.uri("/login/oauth2/code/client-credentials")
-				.exchange()
-				.expectStatus().is3xxRedirection()
-				.expectHeader().valueEquals("Location", "/")
-				.expectCookie().exists("SESSION")
-				.returnResult(Void.class)
-				.getResponseCookies()
-				.getFirst("SESSION");
-
-		this.client.get()
-				.uri("/login/oauth2/code/client-credentials")
-				.exchange()
-				.expectHeader().location("/login?error");
-
-		this.client.get().uri("/")
-				.cookie(sessionCookie.getName(), sessionCookie.getValue())
-				.exchange()
-				.expectStatus().isOk()
-				.expectBody(String.class).isEqualTo("ok");
-		// @formatter:on
-	}
-
-	@Test
-	void oauth2LoginWhenMaxSessionDoesNotPreventLoginThenSecondLoginSucceedsAndFirstSessionIsInvalidated() {
-		OAuth2LoginConcurrentSessionsConfig.maxSessions = 1;
-		OAuth2LoginConcurrentSessionsConfig.preventLogin = false;
-		this.spring.register(OAuth2LoginConcurrentSessionsConfig.class).autowire();
-		prepareOAuth2Config();
-		// @formatter:off
-		ResponseCookie firstLoginCookie = this.client.get()
-				.uri("/login/oauth2/code/client-credentials")
-				.exchange()
-				.expectStatus().is3xxRedirection()
-				.expectHeader().valueEquals("Location", "/")
-				.expectCookie().exists("SESSION")
-				.returnResult(Void.class)
-				.getResponseCookies()
-				.getFirst("SESSION");
-		ResponseCookie secondLoginCookie = this.client.get()
-				.uri("/login/oauth2/code/client-credentials")
-				.exchange()
-				.expectStatus().is3xxRedirection()
-				.expectHeader().valueEquals("Location", "/")
-				.expectCookie().exists("SESSION")
-				.returnResult(Void.class)
-				.getResponseCookies()
-				.getFirst("SESSION");
-
-		this.client.get().uri("/")
-				.cookie(firstLoginCookie.getName(), firstLoginCookie.getValue())
-				.exchange()
-				.expectStatus().isFound()
-				.expectHeader().location("/login");
-
-		this.client.get().uri("/")
-				.cookie(secondLoginCookie.getName(), secondLoginCookie.getValue())
-				.exchange()
-				.expectStatus().isOk()
-				.expectBody(String.class).isEqualTo("ok");
-		// @formatter:on
-	}
-
-	@Test
-	void loginWhenAuthenticationSuccessHandlerOverriddenThenConcurrentSessionHandlersBackOff() {
-		this.spring.register(ConcurrentSessionsFormLoginOverrideAuthenticationSuccessHandlerConfig.class).autowire();
-		MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
-		data.add("username", "user");
-		data.add("password", "password");
-		// first login should be successful
-		login(data).expectStatus().isFound().expectHeader().location("/");
-		// second login should be successful, there should be no concurrent session
-		// control
-		login(data).expectStatus().isFound().expectHeader().location("/");
-	}
-
-	private void prepareOAuth2Config() {
-		OAuth2LoginConcurrentSessionsConfig config = this.spring.getContext()
-			.getBean(OAuth2LoginConcurrentSessionsConfig.class);
-		ServerAuthenticationConverter converter = config.authenticationConverter;
-		ReactiveAuthenticationManager manager = config.manager;
-		ServerOAuth2AuthorizationRequestResolver resolver = config.resolver;
-		OAuth2AuthorizationExchange exchange = TestOAuth2AuthorizationExchanges.success();
-		OAuth2User user = TestOAuth2Users.create();
-		OAuth2AccessToken accessToken = TestOAuth2AccessTokens.noScopes();
-		OAuth2LoginAuthenticationToken result = new OAuth2LoginAuthenticationToken(
-				TestClientRegistrations.clientRegistration().build(), exchange, user, user.getAuthorities(),
-				accessToken);
-		given(converter.convert(any())).willReturn(Mono.just(new TestingAuthenticationToken("a", "b", "c")));
-		given(manager.authenticate(any())).willReturn(Mono.just(result));
-		given(resolver.resolve(any())).willReturn(Mono.empty());
-	}
-
-	private ResponseCookie loginReturningCookie(MultiValueMap<String, String> data) {
-		return login(data).expectCookie()
-			.exists("SESSION")
-			.returnResult(Void.class)
-			.getResponseCookies()
-			.getFirst("SESSION");
-	}
-
-	private WebTestClient.ResponseSpec login(MultiValueMap<String, String> data) {
-		return this.client.mutateWith(csrf())
-			.post()
-			.uri("/login")
-			.contentType(MediaType.MULTIPART_FORM_DATA)
-			.body(BodyInserters.fromFormData(data))
-			.exchange();
-	}
-
-	@Configuration
-	@EnableWebFlux
-	@EnableWebFluxSecurity
-	@Import(Config.class)
-	static class ConcurrentSessionsMaxSessionPreventsLoginConfig {
-
-		static SessionLimit sessionLimit = SessionLimit.of(1);
-
-		@Bean
-		SecurityWebFilterChain springSecurity(ServerHttpSecurity http) {
-			// @formatter:off
-			http
-				.authorizeExchange((exchanges) -> exchanges.anyExchange().authenticated())
-				.formLogin(Customizer.withDefaults())
-				.sessionManagement((sessionManagement) -> sessionManagement
-					.concurrentSessions((concurrentSessions) -> concurrentSessions
-						.maximumSessions(sessionLimit)
-						.maximumSessionsExceededHandler(new PreventLoginServerMaximumSessionsExceededHandler())
-					)
-				);
-			// @formatter:on
-			return http.build();
-		}
-
-	}
-
-	@Configuration
-	@EnableWebFlux
-	@EnableWebFluxSecurity
-	@Import(Config.class)
-	static class OAuth2LoginConcurrentSessionsConfig {
-
-		static int maxSessions = 1;
-
-		static boolean preventLogin = true;
-
-		ReactiveAuthenticationManager manager = mock(ReactiveAuthenticationManager.class);
-
-		ServerAuthenticationConverter authenticationConverter = mock(ServerAuthenticationConverter.class);
-
-		ServerOAuth2AuthorizationRequestResolver resolver = mock(ServerOAuth2AuthorizationRequestResolver.class);
-
-		@Bean
-		SecurityWebFilterChain springSecurityFilter(ServerHttpSecurity http,
-				DefaultWebSessionManager webSessionManager) {
-			// @formatter:off
-			http
-					.authorizeExchange((exchanges) -> exchanges
-						.anyExchange().authenticated()
-					)
-					.oauth2Login((oauth2Login) -> oauth2Login
-						.authenticationConverter(this.authenticationConverter)
-						.authenticationManager(this.manager)
-						.authorizationRequestResolver(this.resolver)
-					)
-					.sessionManagement((sessionManagement) -> sessionManagement
-						.concurrentSessions((concurrentSessions) -> concurrentSessions
-								.maximumSessions(SessionLimit.of(maxSessions))
-								.maximumSessionsExceededHandler(preventLogin
-										? new PreventLoginServerMaximumSessionsExceededHandler()
-										: new InvalidateLeastUsedServerMaximumSessionsExceededHandler(webSessionManager.getSessionStore()))
-						)
-					);
-			// @formatter:on
-			return http.build();
-		}
-
-		@Bean
-		InMemoryReactiveClientRegistrationRepository clientRegistrationRepository() {
-			return new InMemoryReactiveClientRegistrationRepository(
-					TestClientRegistrations.clientCredentials().build());
-		}
-
-	}
-
-	@Configuration
-	@EnableWebFlux
-	@EnableWebFluxSecurity
-	@Import(Config.class)
-	static class ConcurrentSessionsMaxSessionPreventsLoginFalseConfig {
-
-		static SessionLimit sessionLimit = SessionLimit.of(1);
-
-		@Bean
-		SecurityWebFilterChain springSecurity(ServerHttpSecurity http) {
-			// @formatter:off
-			http
-				.authorizeExchange((exchanges) -> exchanges.anyExchange().authenticated())
-				.formLogin(Customizer.withDefaults())
-				.sessionManagement((sessionManagement) -> sessionManagement
-					.concurrentSessions((concurrentSessions) -> concurrentSessions
-						.maximumSessions(sessionLimit)
-					)
-				);
-			// @formatter:on
-			return http.build();
-		}
-
-	}
-
-	@Configuration
-	@EnableWebFlux
-	@EnableWebFluxSecurity
-	@Import(Config.class)
-	static class ConcurrentSessionsFormLoginOverrideAuthenticationSuccessHandlerConfig {
-
-		@Bean
-		SecurityWebFilterChain springSecurity(ServerHttpSecurity http) {
-			// @formatter:off
-			http
-				.authorizeExchange((exchanges) -> exchanges.anyExchange().authenticated())
-				.formLogin((login) -> login
-						.authenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler("/"))
-				)
-				.sessionManagement((sessionManagement) -> sessionManagement
-					.concurrentSessions((concurrentSessions) -> concurrentSessions
-						.maximumSessions(SessionLimit.of(1))
-						.maximumSessionsExceededHandler(new PreventLoginServerMaximumSessionsExceededHandler())
-					)
-				);
-			// @formatter:on
-			return http.build();
-		}
-
-	}
-
-	@Configuration
-	@EnableWebFlux
-	@EnableWebFluxSecurity
-	@Import(Config.class)
-	static class ConcurrentSessionsHttpBasicWithWebSessionMaxSessionPreventsLoginConfig {
-
-		@Bean
-		SecurityWebFilterChain springSecurity(ServerHttpSecurity http) {
-			// @formatter:off
-			http
-					.authorizeExchange((exchanges) -> exchanges.anyExchange().authenticated())
-					.httpBasic((basic) -> basic
-							.securityContextRepository(new WebSessionServerSecurityContextRepository())
-					)
-					.sessionManagement((sessionManagement) -> sessionManagement
-							.concurrentSessions((concurrentSessions) -> concurrentSessions
-									.maximumSessions(SessionLimit.of(1))
-									.maximumSessionsExceededHandler(new PreventLoginServerMaximumSessionsExceededHandler())
-							)
-					);
-			// @formatter:on
-			return http.build();
-		}
-
-	}
-
-	@Configuration
-	@Import({ ReactiveAuthenticationTestConfiguration.class, DefaultController.class })
-	static class Config {
-
-		@Bean(WebHttpHandlerBuilder.WEB_SESSION_MANAGER_BEAN_NAME)
-		DefaultWebSessionManager webSessionManager() {
-			return new DefaultWebSessionManager();
-		}
-
-		@Bean
-		ReactiveSessionRegistry reactiveSessionRegistry() {
-			return new InMemoryReactiveSessionRegistry();
-		}
-
-	}
-
-	@RestController
-	static class DefaultController {
-
-		@GetMapping("/")
-		String index() {
-			return "ok";
-		}
-
-	}
-
-}

+ 0 - 37
config/src/test/kotlin/org/springframework/security/config/annotation/web/AuthorizeHttpRequestsDslTests.kt

@@ -816,41 +816,4 @@ class AuthorizeHttpRequestsDslTests {
         }
 
     }
-
-    @Test
-    fun `request when ip address does not match then responds with forbidden`() {
-        this.spring.register(HasIpAddressConfig::class.java).autowire()
-
-        this.mockMvc.perform(get("/path")
-            .with { request ->
-                request.setAttribute(WebUtils.ERROR_REQUEST_URI_ATTRIBUTE, "/error")
-                request.apply {
-                    dispatcherType = DispatcherType.ERROR
-                }
-            })
-            .andExpect(status().isForbidden)
-    }
-
-    @Configuration
-    @EnableWebSecurity
-    @EnableWebMvc
-    open class HasIpAddressConfig {
-
-        @Bean
-        open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
-            http {
-                authorizeHttpRequests {
-                    authorize(anyRequest, hasIpAddress("10.0.0.0/24"))
-                }
-            }
-            return http.build()
-        }
-
-        @RestController
-        internal class PathController {
-            @RequestMapping("/path")
-            fun path() {
-            }
-        }
-    }
 }

+ 1 - 46
config/src/test/kotlin/org/springframework/security/config/annotation/web/FormLoginDslTests.kt

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2023 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -33,7 +33,6 @@ import org.springframework.security.config.test.SpringTestContextExtension
 import org.springframework.security.core.userdetails.User
 import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin
 import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf
-import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated
 import org.springframework.security.web.SecurityFilterChain
 import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler
 import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler
@@ -368,50 +367,6 @@ class FormLoginDslTests {
         verify(exactly = 1) { CustomAuthenticationDetailsSourceConfig.AUTHENTICATION_DETAILS_SOURCE.buildDetails(any()) }
     }
 
-    @Configuration
-    @EnableWebSecurity
-    open class CustomUsernameParameterConfig {
-        @Bean
-        open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
-            http {
-                formLogin {
-                    usernameParameter = "custom-username"
-                }
-            }
-            return http.build()
-        }
-    }
-
-    @Test
-    fun `form login when custom username parameter then used`() {
-        this.spring.register(CustomUsernameParameterConfig::class.java, UserConfig::class.java).autowire()
-
-        this.mockMvc.perform(formLogin().userParameter("custom-username"))
-                .andExpect(authenticated())
-    }
-
-    @Configuration
-    @EnableWebSecurity
-    open class CustomPasswordParameterConfig {
-        @Bean
-        open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
-            http {
-                formLogin {
-                    passwordParameter = "custom-password"
-                }
-            }
-            return http.build()
-        }
-    }
-
-    @Test
-    fun `form login when custom password parameter then used`() {
-        this.spring.register(CustomPasswordParameterConfig::class.java, UserConfig::class.java).autowire()
-
-        this.mockMvc.perform(formLogin().passwordParam("custom-password"))
-                .andExpect(authenticated())
-    }
-
     @Configuration
     @EnableWebSecurity
     open class CustomAuthenticationDetailsSourceConfig {

+ 0 - 126
config/src/test/kotlin/org/springframework/security/config/annotation/web/Saml2LogoutDslTests.kt

@@ -1,126 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.config.annotation.web
-
-import org.assertj.core.api.Assertions
-import org.junit.jupiter.api.Test
-import org.junit.jupiter.api.extension.ExtendWith
-import org.springframework.beans.factory.BeanCreationException
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.context.annotation.Bean
-import org.springframework.context.annotation.Configuration
-import org.springframework.security.authentication.TestAuthentication
-import org.springframework.security.config.annotation.web.builders.HttpSecurity
-import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
-import org.springframework.security.config.test.SpringTestContext
-import org.springframework.security.config.test.SpringTestContextExtension
-import org.springframework.security.core.authority.AuthorityUtils
-import org.springframework.security.saml2.provider.service.authentication.DefaultSaml2AuthenticatedPrincipal
-import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication
-import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository
-import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations
-import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors
-import org.springframework.security.web.SecurityFilterChain
-import org.springframework.test.web.servlet.MockMvc
-import org.springframework.test.web.servlet.MvcResult
-import org.springframework.test.web.servlet.request.MockMvcRequestBuilders
-import org.springframework.test.web.servlet.result.MockMvcResultMatchers
-import java.util.*
-
-/**
- * Tests for [Saml2LogoutDsl]
- *
- * @author Josh Cummings
- */
-@ExtendWith(SpringTestContextExtension::class)
-class Saml2LogoutDslTests {
-    @JvmField
-    val spring = SpringTestContext(this)
-
-    @Autowired
-    lateinit var mockMvc: MockMvc
-
-    @Test
-    fun `saml2Logout when no relying party registration repository then exception`() {
-        Assertions.assertThatThrownBy { this.spring.register(Saml2LogoutNoRelyingPartyRegistrationRepoConfig::class.java).autowire() }
-                .isInstanceOf(BeanCreationException::class.java)
-                .hasMessageContaining("relyingPartyRegistrationRepository cannot be null")
-
-    }
-
-    @Test
-    @Throws(Exception::class)
-    fun `saml2Logout when defaults and not saml login then default logout`() {
-        this.spring.register(Saml2LogoutDefaultsConfig::class.java).autowire()
-        val user = TestAuthentication.authenticatedUser()
-        val result: MvcResult = this.mockMvc.perform(
-            MockMvcRequestBuilders.post("/logout").with(SecurityMockMvcRequestPostProcessors.authentication(user))
-                .with(SecurityMockMvcRequestPostProcessors.csrf()))
-            .andExpect(MockMvcResultMatchers.status().isFound())
-            .andReturn()
-        val location = result.response.getHeader("Location")
-        Assertions.assertThat(location).isEqualTo("/login?logout")
-    }
-
-    @Test
-    @Throws(Exception::class)
-    fun saml2LogoutWhenDefaultsThenLogsOutAndSendsLogoutRequest() {
-        this.spring.register(Saml2LogoutDefaultsConfig::class.java).autowire()
-        val principal = DefaultSaml2AuthenticatedPrincipal("user", emptyMap())
-        principal.relyingPartyRegistrationId = "registration-id"
-        val user = Saml2Authentication(principal, "response", AuthorityUtils.createAuthorityList("ROLE_USER"))
-        val result: MvcResult = this.mockMvc.perform(MockMvcRequestBuilders.post("/logout")
-            .with(SecurityMockMvcRequestPostProcessors.authentication(user))
-            .with(SecurityMockMvcRequestPostProcessors.csrf()))
-            .andExpect(MockMvcResultMatchers.status().isFound())
-            .andReturn()
-        val location = result.response.getHeader("Location")
-        Assertions.assertThat(location).startsWith("https://ap.example.org/logout/saml2/request")
-    }
-
-    @Configuration
-    @EnableWebSecurity
-    open class Saml2LogoutNoRelyingPartyRegistrationRepoConfig {
-        @Bean
-        open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
-            http {
-                saml2Logout { }
-            }
-            return http.build()
-        }
-    }
-
-    @Configuration
-    @EnableWebSecurity
-    open class Saml2LogoutDefaultsConfig {
-
-        @Bean
-        open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
-            http {
-                saml2Logout { }
-            }
-            return http.build()
-        }
-
-        @Bean
-        open fun registrations(): RelyingPartyRegistrationRepository =
-            InMemoryRelyingPartyRegistrationRepository(TestRelyingPartyRegistrations.full().build())
-
-    }
-
-}

+ 0 - 282
config/src/test/kotlin/org/springframework/security/config/web/server/ServerSessionManagementDslTests.kt

@@ -1,282 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.config.web.server
-
-import org.junit.Test
-import org.junit.jupiter.api.extension.ExtendWith
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.context.ApplicationContext
-import org.springframework.context.annotation.Bean
-import org.springframework.context.annotation.Configuration
-import org.springframework.context.annotation.Import
-import org.springframework.http.MediaType
-import org.springframework.http.ResponseCookie
-import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity
-import org.springframework.security.config.test.SpringTestContext
-import org.springframework.security.config.test.SpringTestContextExtension
-import org.springframework.security.config.users.ReactiveAuthenticationTestConfiguration
-import org.springframework.security.core.session.InMemoryReactiveSessionRegistry
-import org.springframework.security.core.session.ReactiveSessionRegistry
-import org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers
-import org.springframework.security.web.server.SecurityWebFilterChain
-import org.springframework.security.web.server.authentication.InvalidateLeastUsedServerMaximumSessionsExceededHandler
-import org.springframework.security.web.server.authentication.PreventLoginServerMaximumSessionsExceededHandler
-import org.springframework.security.web.server.authentication.SessionLimit
-import org.springframework.test.web.reactive.server.WebTestClient
-import org.springframework.util.LinkedMultiValueMap
-import org.springframework.util.MultiValueMap
-import org.springframework.web.bind.annotation.GetMapping
-import org.springframework.web.bind.annotation.RestController
-import org.springframework.web.reactive.config.EnableWebFlux
-import org.springframework.web.reactive.function.BodyInserters
-import org.springframework.web.server.adapter.WebHttpHandlerBuilder
-import org.springframework.web.server.session.DefaultWebSessionManager
-
-/**
- * Tests for [ServerSessionManagementDsl]
- *
- * @author Marcus da Coregio
- */
-@ExtendWith(SpringTestContextExtension::class)
-class ServerSessionManagementDslTests {
-
-    @JvmField
-    val spring = SpringTestContext(this)
-
-    private lateinit var client: WebTestClient
-
-    @Autowired
-    fun setup(context: ApplicationContext) {
-        this.client = WebTestClient
-            .bindToApplicationContext(context)
-            .configureClient()
-            .build()
-    }
-
-    @Test
-    fun `login when max sessions prevent login then second login fails`() {
-        this.spring.register(ConcurrentSessionsMaxSessionPreventsLoginTrueConfig::class.java).autowire()
-
-        val data: MultiValueMap<String, String> = LinkedMultiValueMap()
-        data.add("username", "user")
-        data.add("password", "password")
-
-        val firstLoginSessionCookie = loginReturningCookie(data)
-
-        // second login should fail
-        this.client.mutateWith(SecurityMockServerConfigurers.csrf())
-            .post()
-            .uri("/login")
-            .contentType(MediaType.MULTIPART_FORM_DATA)
-            .body(BodyInserters.fromFormData(data))
-            .exchange()
-            .expectHeader()
-            .location("/login?error")
-
-        // first login should still be valid
-        this.client.mutateWith(SecurityMockServerConfigurers.csrf())
-            .get()
-            .uri("/")
-            .cookie(firstLoginSessionCookie!!.name, firstLoginSessionCookie.value)
-            .exchange()
-            .expectStatus()
-            .isOk()
-    }
-
-    @Test
-    fun `login when max sessions does not prevent login then seconds login succeeds and first session is invalidated`() {
-        ConcurrentSessionsMaxSessionPreventsLoginFalseConfig.maxSessions = 1
-        this.spring.register(SessionManagementSpecTests.ConcurrentSessionsMaxSessionPreventsLoginFalseConfig::class.java)
-            .autowire()
-
-        val data: MultiValueMap<String, String> = LinkedMultiValueMap()
-        data.add("username", "user")
-        data.add("password", "password")
-
-        val firstLoginSessionCookie = loginReturningCookie(data)
-        val secondLoginSessionCookie = loginReturningCookie(data)
-
-        // first login should not be valid
-        this.client.get()
-            .uri("/")
-            .cookie(firstLoginSessionCookie!!.name, firstLoginSessionCookie.value)
-            .exchange()
-            .expectStatus()
-            .isFound()
-            .expectHeader()
-            .location("/login")
-
-        // second login should be valid
-        this.client.get()
-            .uri("/")
-            .cookie(secondLoginSessionCookie!!.name, secondLoginSessionCookie.value)
-            .exchange()
-            .expectStatus()
-            .isOk()
-    }
-
-    @Test
-    fun `login when max sessions does not prevent login then least recently used session is invalidated`() {
-        ConcurrentSessionsMaxSessionPreventsLoginFalseConfig.maxSessions = 2
-        this.spring.register(ConcurrentSessionsMaxSessionPreventsLoginFalseConfig::class.java).autowire()
-        val data: MultiValueMap<String, String> = LinkedMultiValueMap()
-        data.add("username", "user")
-        data.add("password", "password")
-        val firstLoginSessionCookie = loginReturningCookie(data)
-        val secondLoginSessionCookie = loginReturningCookie(data)
-
-        // update last access time for first request
-        this.client.get()
-            .uri("/")
-            .cookie(firstLoginSessionCookie!!.name, firstLoginSessionCookie.value)
-            .exchange()
-            .expectStatus()
-            .isOk()
-        val thirdLoginSessionCookie = loginReturningCookie(data)
-
-        // second login should be invalid, it is the least recently used session
-        this.client.get()
-            .uri("/")
-            .cookie(secondLoginSessionCookie!!.name, secondLoginSessionCookie.value)
-            .exchange()
-            .expectStatus()
-            .isFound()
-            .expectHeader()
-            .location("/login")
-
-        // first login should be valid
-        this.client.get()
-            .uri("/")
-            .cookie(firstLoginSessionCookie.name, firstLoginSessionCookie.value)
-            .exchange()
-            .expectStatus()
-            .isOk()
-
-        // third login should be valid
-        this.client.get()
-            .uri("/")
-            .cookie(thirdLoginSessionCookie!!.name, thirdLoginSessionCookie.value)
-            .exchange()
-            .expectStatus()
-            .isOk()
-    }
-
-    private fun loginReturningCookie(data: MultiValueMap<String, String>): ResponseCookie? {
-        return login(data).expectCookie()
-            .exists("SESSION")
-            .returnResult(Void::class.java)
-            .responseCookies
-            .getFirst("SESSION")
-    }
-
-    private fun login(data: MultiValueMap<String, String>): WebTestClient.ResponseSpec {
-        return client.mutateWith(SecurityMockServerConfigurers.csrf())
-            .post()
-            .uri("/login")
-            .contentType(MediaType.MULTIPART_FORM_DATA)
-            .body(BodyInserters.fromFormData(data))
-            .exchange()
-            .expectStatus()
-            .is3xxRedirection()
-            .expectHeader()
-            .location("/")
-    }
-
-    @Configuration
-    @EnableWebFlux
-    @EnableWebFluxSecurity
-    @Import(Config::class)
-    open class ConcurrentSessionsMaxSessionPreventsLoginFalseConfig {
-
-        companion object {
-            var maxSessions = 1
-        }
-
-        @Bean
-        open fun springSecurity(http: ServerHttpSecurity, webSessionManager: DefaultWebSessionManager): SecurityWebFilterChain {
-            return http {
-                authorizeExchange {
-                    authorize(anyExchange, authenticated)
-                }
-                formLogin { }
-                sessionManagement {
-                    sessionConcurrency {
-                        maximumSessions = SessionLimit.of(maxSessions)
-                        maximumSessionsExceededHandler = InvalidateLeastUsedServerMaximumSessionsExceededHandler(webSessionManager.sessionStore)
-                    }
-                }
-            }
-        }
-
-    }
-
-    @Configuration
-    @EnableWebFlux
-    @EnableWebFluxSecurity
-    @Import(Config::class)
-    open class ConcurrentSessionsMaxSessionPreventsLoginTrueConfig {
-
-        @Bean
-        open fun springSecurity(http: ServerHttpSecurity): SecurityWebFilterChain {
-            return http {
-                authorizeExchange {
-                    authorize(anyExchange, authenticated)
-                }
-                formLogin { }
-                sessionManagement {
-                    sessionConcurrency {
-                        maximumSessions = SessionLimit.of(1)
-                        maximumSessionsExceededHandler =
-                            PreventLoginServerMaximumSessionsExceededHandler()
-                    }
-                }
-            }
-        }
-
-    }
-
-    @Configuration
-    @Import(
-        ReactiveAuthenticationTestConfiguration::class,
-        DefaultController::class
-    )
-    open class Config {
-
-        @Bean(WebHttpHandlerBuilder.WEB_SESSION_MANAGER_BEAN_NAME)
-        open fun webSessionManager(): DefaultWebSessionManager {
-            return DefaultWebSessionManager()
-        }
-
-        @Bean
-        open fun reactiveSessionRegistry(): ReactiveSessionRegistry {
-            return InMemoryReactiveSessionRegistry()
-        }
-
-    }
-
-    @RestController
-    open class DefaultController {
-
-        @GetMapping("/")
-        fun index(): String {
-            return "ok"
-        }
-
-    }
-
-
-}

+ 0 - 3
config/src/test/resources/org/springframework/security/config/http/OAuth2AuthorizedClientManagerRegistrarTests-clients.xml

@@ -53,7 +53,4 @@
 	<b:bean class="org.springframework.security.config.http.OAuth2AuthorizedClientManagerRegistrarTests"
 			factory-method="jwtBearerAccessTokenResponseClient"/>
 
-	<b:bean class="org.springframework.security.config.http.OAuth2AuthorizedClientManagerRegistrarTests"
-			factory-method="tokenExchangeAccessTokenResponseClient"/>
-
 </b:beans>

+ 5 - 8
config/src/test/resources/org/springframework/security/config/http/OAuth2AuthorizedClientManagerRegistrarTests-providers.xml

@@ -42,21 +42,18 @@
 			factory-method="authorizedClientManagerConsumer"/>
 
 	<b:bean class="org.springframework.security.config.http.OAuth2AuthorizedClientManagerRegistrarTests"
-			factory-method="authorizationCode"/>
+			factory-method="authorizationCodeAuthorizedClientProvider"/>
 
 	<b:bean class="org.springframework.security.config.http.OAuth2AuthorizedClientManagerRegistrarTests"
-			factory-method="refreshToken"/>
+			factory-method="refreshTokenAuthorizedClientProvider"/>
 
 	<b:bean class="org.springframework.security.config.http.OAuth2AuthorizedClientManagerRegistrarTests"
-			factory-method="clientCredentials"/>
+			factory-method="clientCredentialsAuthorizedClientProvider"/>
 
 	<b:bean class="org.springframework.security.config.http.OAuth2AuthorizedClientManagerRegistrarTests"
-			factory-method="password"/>
+			factory-method="passwordAuthorizedClientProvider"/>
 
 	<b:bean class="org.springframework.security.config.http.OAuth2AuthorizedClientManagerRegistrarTests"
-			factory-method="jwtBearer"/>
-
-	<b:bean class="org.springframework.security.config.http.OAuth2AuthorizedClientManagerRegistrarTests"
-			factory-method="tokenExchange"/>
+			factory-method="jwtBearerAuthorizedClientProvider"/>
 
 </b:beans>

+ 1 - 1
config/src/test/resources/org/springframework/security/config/method-security.xml

@@ -6,7 +6,7 @@
 	xmlns:tx="http://www.springframework.org/schema/tx"
 	xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 		http://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx.xsd
-		http://www.springframework.org/schema/security org/springframework/security/config/spring-security-6.3.xsd">
+		http://www.springframework.org/schema/security org/springframework/security/config/spring-security-6.2.xsd">
 
 	<tx:annotation-driven />
 

+ 5 - 5
config/src/test/resources/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests-MultiRegistration.xml

@@ -23,20 +23,20 @@
 			https://www.springframework.org/schema/security/spring-security.xsd
 			http://www.springframework.org/schema/beans
 			https://www.springframework.org/schema/beans/spring-beans.xsd">
-
-  <relying-party-registrations id="registrations">
+  
+  <relying-party-registrations>
     <relying-party-registration registration-id="one"
                                 entity-id="{baseUrl}/saml2/service-provider-metadata/{registrationId}"
                                 assertion-consumer-service-location="{baseUrl}/login/saml2/sso/{registrationId}"
                                 assertion-consumer-service-binding="REDIRECT"
                                 asserting-party-id="google"/>
-
+    
     <relying-party-registration registration-id="two"
                                 entity-id="{baseUrl}/saml2/service-provider-metadata/{registrationId}"
                                 assertion-consumer-service-location="{baseUrl}/login/saml2/sso/{registrationId}"
                                 assertion-consumer-service-binding="POST"
                                 asserting-party-id="simple-saml"/>
-
+    
     <asserting-party asserting-party-id="google" entity-id="https://accounts.google.com/o/saml2/idp/entity-id"
                      want-authn-requests-signed="true"
                      single-sign-on-service-location="https://accounts.google.com/o/saml2/idp/sso-url"
@@ -48,7 +48,7 @@
           certificate-location="classpath:org/springframework/security/config/saml2/idp-certificate.crt"
           private-key-location="classpath:org/springframework/security/config/saml2/rp-private.key"/>
     </asserting-party>
-
+    
     <asserting-party asserting-party-id="simple-saml"
                      entity-id="https://simplesaml-for-spring-saml.apps.pcfone.io/saml2/idp/metadata.php"
                      single-sign-on-service-location="https://simplesaml-for-spring-saml.apps.pcfone.io/saml2/idp/SSOService.php"

+ 0 - 58
config/src/test/resources/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests-RelayStateResolver.xml

@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Copyright 2002-2021 the original author or authors.
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      https://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<b:beans xmlns:b="http://www.springframework.org/schema/beans"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xmlns="http://www.springframework.org/schema/security"
-         xsi:schemaLocation="
-			http://www.springframework.org/schema/security
-			https://www.springframework.org/schema/security/spring-security.xsd
-			http://www.springframework.org/schema/beans
-			https://www.springframework.org/schema/beans/spring-beans.xsd">
-
-  <relying-party-registrations id="registrations">
-    <relying-party-registration registration-id="one"
-                                entity-id="{baseUrl}/saml2/service-provider-metadata/{registrationId}"
-                                assertion-consumer-service-location="{baseUrl}/login/saml2/sso/{registrationId}"
-                                assertion-consumer-service-binding="REDIRECT"
-                                asserting-party-id="google">
-      <signing-credential
-          certificate-location="classpath:org/springframework/security/config/saml2/rp-certificate.crt"
-          private-key-location="classpath:org/springframework/security/config/saml2/rp-private.key"/>
-	</relying-party-registration>
-    <asserting-party asserting-party-id="google" entity-id="https://accounts.google.com/o/saml2/idp/entity-id"
-                     want-authn-requests-signed="true"
-                     single-sign-on-service-location="https://accounts.google.com/o/saml2/idp/sso-url"
-                     single-sign-on-service-binding="POST">
-      <verification-credential
-          certificate-location="classpath:org/springframework/security/config/saml2/idp-certificate.crt"
-          private-key-location="classpath:org/springframework/security/config/saml2/rp-private.key"/>
-      <encryption-credential
-          certificate-location="classpath:org/springframework/security/config/saml2/idp-certificate.crt"
-          private-key-location="classpath:org/springframework/security/config/saml2/rp-private.key"/>
-    </asserting-party>
-  </relying-party-registrations>
-
-  <b:bean class="org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver">
-    <b:constructor-arg ref="registrations"/>
-    <b:property name="relayStateResolver" ref="relayStateResolver"/>
-  </b:bean>
-
-  <b:bean name="relayStateResolver" class="org.mockito.Mockito" factory-method="mock">
-    <b:constructor-arg value="org.springframework.core.convert.converter.Converter" type="java.lang.Class"/>
-  </b:bean>
-</b:beans>

+ 3 - 3
config/src/test/resources/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests-SingleRegistration.xml

@@ -23,14 +23,14 @@
 			https://www.springframework.org/schema/security/spring-security.xsd
 			http://www.springframework.org/schema/beans
 			https://www.springframework.org/schema/beans/spring-beans.xsd">
-
-  <relying-party-registrations id="registrations">
+  
+  <relying-party-registrations>
     <relying-party-registration registration-id="one"
                                 entity-id="{baseUrl}/saml2/service-provider-metadata/{registrationId}"
                                 assertion-consumer-service-location="{baseUrl}/login/saml2/sso/{registrationId}"
                                 assertion-consumer-service-binding="REDIRECT"
                                 asserting-party-id="google"/>
-
+    
     <asserting-party asserting-party-id="google" entity-id="https://accounts.google.com/o/saml2/idp/entity-id"
                      want-authn-requests-signed="true"
                      single-sign-on-service-location="https://accounts.google.com/o/saml2/idp/sso-url"

+ 1 - 1
core/src/main/java/org/springframework/security/access/expression/ExpressionUtils.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.

+ 3 - 3
core/src/main/java/org/springframework/security/access/expression/SecurityExpressionOperations.java

@@ -125,7 +125,7 @@ public interface SecurityExpressionOperations {
 	 * given the permission
 	 * @param target the target domain object to check permission on
 	 * @param permission the permission to check on the domain object (i.e. "read",
-	 * "write", etc.).
+	 * "write", etc).
 	 * @return true if permission is granted to the {@link #getAuthentication()}, else
 	 * false
 	 */
@@ -136,8 +136,8 @@ public interface SecurityExpressionOperations {
 	 * object with a given id, type, and permission.
 	 * @param targetId the identifier of the domain object to determine access
 	 * @param targetType the type (i.e. com.example.domain.Message)
-	 * @param permission the permission to check on the domain object (i.e. "read",
-	 * "write", etc.)
+	 * @param permission the perission to check on the domain object (i.e. "read",
+	 * "write", etc)
 	 * @return true if permission is granted to the {@link #getAuthentication()}, else
 	 * false
 	 */

+ 29 - 147
core/src/main/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyImpl.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2023 the original author or authors.
+ * Copyright 2002-2019 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,7 +20,6 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Set;
 
@@ -31,7 +30,6 @@ import org.springframework.core.log.LogMessage;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.authority.AuthorityUtils;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
-import org.springframework.util.Assert;
 
 /**
  * <p>
@@ -76,68 +74,30 @@ import org.springframework.util.Assert;
  * your intentions clearer.
  *
  * @author Michael Mayr
- * @author Josh Cummings
  */
 public class RoleHierarchyImpl implements RoleHierarchy {
 
 	private static final Log logger = LogFactory.getLog(RoleHierarchyImpl.class);
 
 	/**
-	 * {@code rolesReachableInOneOrMoreStepsMap} is a Map that under the key of a specific
-	 * role name contains a set of all roles reachable from this role in 1 or more steps
+	 * Raw hierarchy configuration where each line represents single or multiple level
+	 * role chain.
 	 */
-	private Map<String, Set<GrantedAuthority>> rolesReachableInOneOrMoreStepsMap = null;
+	private String roleHierarchyStringRepresentation = null;
 
 	/**
-	 * @deprecated Use {@link RoleHierarchyImpl#fromHierarchy} instead
+	 * {@code rolesReachableInOneStepMap} is a Map that under the key of a specific role
+	 * name contains a set of all roles reachable from this role in 1 step (i.e. parsed
+	 * {@link #roleHierarchyStringRepresentation} grouped by the higher role)
 	 */
-	@Deprecated
-	public RoleHierarchyImpl() {
-
-	}
-
-	private RoleHierarchyImpl(Map<String, Set<GrantedAuthority>> hierarchy) {
-		this.rolesReachableInOneOrMoreStepsMap = buildRolesReachableInOneOrMoreStepsMap(hierarchy);
-	}
-
-	/**
-	 * Create a role hierarchy instance with the given definition, similar to the
-	 * following:
-	 *
-	 * <pre>
-	 *     ROLE_A &gt; ROLE_B
-	 *     ROLE_B &gt; ROLE_AUTHENTICATED
-	 *     ROLE_AUTHENTICATED &gt; ROLE_UNAUTHENTICATED
-	 * </pre>
-	 * @param hierarchy the role hierarchy to use
-	 * @return a {@link RoleHierarchyImpl} that uses the given {@code hierarchy}
-	 */
-	public static RoleHierarchyImpl fromHierarchy(String hierarchy) {
-		return new RoleHierarchyImpl(buildRolesReachableInOneStepMap(hierarchy));
-	}
+	private Map<String, Set<GrantedAuthority>> rolesReachableInOneStepMap = null;
 
 	/**
-	 * Factory method that creates a {@link Builder} instance with the default role prefix
-	 * "ROLE_"
-	 * @return a {@link Builder} instance with the default role prefix "ROLE_"
-	 * @since 6.3
-	 */
-	public static Builder withDefaultRolePrefix() {
-		return withRolePrefix("ROLE_");
-	}
-
-	/**
-	 * Factory method that creates a {@link Builder} instance with the specified role
-	 * prefix.
-	 * @param rolePrefix the prefix to be used for the roles in the hierarchy.
-	 * @return a new {@link Builder} instance with the specified role prefix
-	 * @throws IllegalArgumentException if the provided role prefix is null
-	 * @since 6.3
+	 * {@code rolesReachableInOneOrMoreStepsMap} is a Map that under the key of a specific
+	 * role name contains a set of all roles reachable from this role in 1 or more steps
+	 * (i.e. fully resolved hierarchy from {@link #rolesReachableInOneStepMap})
 	 */
-	public static Builder withRolePrefix(String rolePrefix) {
-		Assert.notNull(rolePrefix, "rolePrefix must not be null");
-		return new Builder(rolePrefix);
-	}
+	private Map<String, Set<GrantedAuthority>> rolesReachableInOneOrMoreStepsMap = null;
 
 	/**
 	 * Set the role hierarchy and pre-calculate for every role the set of all reachable
@@ -146,15 +106,13 @@ public class RoleHierarchyImpl implements RoleHierarchy {
 	 * time). During pre-calculation, cycles in role hierarchy are detected and will cause
 	 * a <tt>CycleInRoleHierarchyException</tt> to be thrown.
 	 * @param roleHierarchyStringRepresentation - String definition of the role hierarchy.
-	 * @deprecated Use {@link RoleHierarchyImpl#fromHierarchy} instead
 	 */
-	@Deprecated
 	public void setHierarchy(String roleHierarchyStringRepresentation) {
+		this.roleHierarchyStringRepresentation = roleHierarchyStringRepresentation;
 		logger.debug(LogMessage.format("setHierarchy() - The following role hierarchy was set: %s",
 				roleHierarchyStringRepresentation));
-		Map<String, Set<GrantedAuthority>> hierarchy = buildRolesReachableInOneStepMap(
-				roleHierarchyStringRepresentation);
-		this.rolesReachableInOneOrMoreStepsMap = buildRolesReachableInOneOrMoreStepsMap(hierarchy);
+		buildRolesReachableInOneStepMap();
+		buildRolesReachableInOneOrMoreStepsMap();
 	}
 
 	@Override
@@ -198,21 +156,21 @@ public class RoleHierarchyImpl implements RoleHierarchy {
 	 * Parse input and build the map for the roles reachable in one step: the higher role
 	 * will become a key that references a set of the reachable lower roles.
 	 */
-	private static Map<String, Set<GrantedAuthority>> buildRolesReachableInOneStepMap(String hierarchy) {
-		Map<String, Set<GrantedAuthority>> rolesReachableInOneStepMap = new HashMap<>();
-		for (String line : hierarchy.split("\n")) {
+	private void buildRolesReachableInOneStepMap() {
+		this.rolesReachableInOneStepMap = new HashMap<>();
+		for (String line : this.roleHierarchyStringRepresentation.split("\n")) {
 			// Split on > and trim excessive whitespace
 			String[] roles = line.trim().split("\\s+>\\s+");
 			for (int i = 1; i < roles.length; i++) {
 				String higherRole = roles[i - 1];
 				GrantedAuthority lowerRole = new SimpleGrantedAuthority(roles[i]);
 				Set<GrantedAuthority> rolesReachableInOneStepSet;
-				if (!rolesReachableInOneStepMap.containsKey(higherRole)) {
+				if (!this.rolesReachableInOneStepMap.containsKey(higherRole)) {
 					rolesReachableInOneStepSet = new HashSet<>();
-					rolesReachableInOneStepMap.put(higherRole, rolesReachableInOneStepSet);
+					this.rolesReachableInOneStepMap.put(higherRole, rolesReachableInOneStepSet);
 				}
 				else {
-					rolesReachableInOneStepSet = rolesReachableInOneStepMap.get(higherRole);
+					rolesReachableInOneStepSet = this.rolesReachableInOneStepMap.get(higherRole);
 				}
 				rolesReachableInOneStepSet.add(lowerRole);
 				logger.debug(LogMessage.format(
@@ -220,7 +178,6 @@ public class RoleHierarchyImpl implements RoleHierarchy {
 						higherRole, lowerRole));
 			}
 		}
-		return rolesReachableInOneStepMap;
 	}
 
 	/**
@@ -229,105 +186,30 @@ public class RoleHierarchyImpl implements RoleHierarchy {
 	 * CycleInRoleHierarchyException if a cycle in the role hierarchy definition is
 	 * detected)
 	 */
-	private static Map<String, Set<GrantedAuthority>> buildRolesReachableInOneOrMoreStepsMap(
-			Map<String, Set<GrantedAuthority>> hierarchy) {
-		Map<String, Set<GrantedAuthority>> rolesReachableInOneOrMoreStepsMap = new HashMap<>();
+	private void buildRolesReachableInOneOrMoreStepsMap() {
+		this.rolesReachableInOneOrMoreStepsMap = new HashMap<>();
 		// iterate over all higher roles from rolesReachableInOneStepMap
-		for (String roleName : hierarchy.keySet()) {
-			Set<GrantedAuthority> rolesToVisitSet = new HashSet<>(hierarchy.get(roleName));
+		for (String roleName : this.rolesReachableInOneStepMap.keySet()) {
+			Set<GrantedAuthority> rolesToVisitSet = new HashSet<>(this.rolesReachableInOneStepMap.get(roleName));
 			Set<GrantedAuthority> visitedRolesSet = new HashSet<>();
 			while (!rolesToVisitSet.isEmpty()) {
 				// take a role from the rolesToVisit set
 				GrantedAuthority lowerRole = rolesToVisitSet.iterator().next();
 				rolesToVisitSet.remove(lowerRole);
-				if (!visitedRolesSet.add(lowerRole) || !hierarchy.containsKey(lowerRole.getAuthority())) {
+				if (!visitedRolesSet.add(lowerRole)
+						|| !this.rolesReachableInOneStepMap.containsKey(lowerRole.getAuthority())) {
 					continue; // Already visited role or role with missing hierarchy
 				}
 				else if (roleName.equals(lowerRole.getAuthority())) {
 					throw new CycleInRoleHierarchyException();
 				}
-				rolesToVisitSet.addAll(hierarchy.get(lowerRole.getAuthority()));
+				rolesToVisitSet.addAll(this.rolesReachableInOneStepMap.get(lowerRole.getAuthority()));
 			}
-			rolesReachableInOneOrMoreStepsMap.put(roleName, visitedRolesSet);
+			this.rolesReachableInOneOrMoreStepsMap.put(roleName, visitedRolesSet);
 			logger.debug(LogMessage.format(
 					"buildRolesReachableInOneOrMoreStepsMap() - From role %s one can reach %s in one or more steps.",
 					roleName, visitedRolesSet));
 		}
-		return rolesReachableInOneOrMoreStepsMap;
-	}
-
-	/**
-	 * Builder class for constructing a {@link RoleHierarchyImpl} based on a hierarchical
-	 * role structure.
-	 *
-	 * @author Federico Herrera
-	 * @since 6.3
-	 */
-	public static final class Builder {
-
-		private final String rolePrefix;
-
-		private final Map<String, Set<GrantedAuthority>> hierarchy;
-
-		private Builder(String rolePrefix) {
-			this.rolePrefix = rolePrefix;
-			this.hierarchy = new LinkedHashMap<>();
-		}
-
-		/**
-		 * Creates a new hierarchy branch to define a role and its child roles.
-		 * @param role the highest role in this branch
-		 * @return a {@link ImpliedRoles} to define the child roles for the
-		 * <code>role</code>
-		 */
-		public ImpliedRoles role(String role) {
-			Assert.hasText(role, "role must not be empty");
-			return new ImpliedRoles(role);
-		}
-
-		/**
-		 * Builds and returns a {@link RoleHierarchyImpl} describing the defined role
-		 * hierarchy.
-		 * @return a {@link RoleHierarchyImpl}
-		 */
-		public RoleHierarchyImpl build() {
-			return new RoleHierarchyImpl(this.hierarchy);
-		}
-
-		private Builder addHierarchy(String role, String... impliedRoles) {
-			Set<GrantedAuthority> withPrefix = new HashSet<>();
-			for (String impliedRole : impliedRoles) {
-				withPrefix.add(new SimpleGrantedAuthority(this.rolePrefix.concat(impliedRole)));
-			}
-			this.hierarchy.put(this.rolePrefix.concat(role), withPrefix);
-			return this;
-		}
-
-		/**
-		 * Builder class for constructing child roles within a role hierarchy branch.
-		 */
-		public final class ImpliedRoles {
-
-			private final String role;
-
-			private ImpliedRoles(String role) {
-				this.role = role;
-			}
-
-			/**
-			 * Specifies implied role(s) for the current role in the hierarchy.
-			 * @param impliedRoles role name(s) implied by the role.
-			 * @return the same {@link Builder} instance
-			 * @throws IllegalArgumentException if <code>impliedRoles</code> is null,
-			 * empty or contains any null element.
-			 */
-			public Builder implies(String... impliedRoles) {
-				Assert.notEmpty(impliedRoles, "at least one implied role must be provided");
-				Assert.noNullElements(impliedRoles, "implied role name(s) cannot be empty");
-				return Builder.this.addHierarchy(this.role, impliedRoles);
-			}
-
-		}
 
 	}
 

+ 1 - 1
core/src/main/java/org/springframework/security/access/prepost/PostAuthorize.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.

+ 1 - 1
core/src/main/java/org/springframework/security/access/prepost/PreAuthorize.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.