1
0
mirror of synced 2026-07-09 21:00:02 +00:00

Compare commits

...

75 Commits

Author SHA1 Message Date
github-actions[bot] e8aef09b4f Release 6.4.5 2025-04-21 15:58:58 +00:00
Josh Cummings f8d417dc03 Preserve Encrypted Elements
Closes gh-16367
2025-04-21 08:32:07 -06:00
dependabot[bot] 79bacf8204 Bump org.springframework:spring-framework-bom from 6.2.5 to 6.2.6
Bumps [org.springframework:spring-framework-bom](https://github.com/spring-projects/spring-framework) from 6.2.5 to 6.2.6.
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.5...v6.2.6)

---
updated-dependencies:
- dependency-name: org.springframework:spring-framework-bom
  dependency-version: 6.2.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-17 20:58:02 -07:00
dependabot[bot] 9bcfeab1d6 Bump org.springframework.ldap:spring-ldap-core from 3.2.11 to 3.2.12
Bumps [org.springframework.ldap:spring-ldap-core](https://github.com/spring-projects/spring-ldap) from 3.2.11 to 3.2.12.
- [Release notes](https://github.com/spring-projects/spring-ldap/releases)
- [Changelog](https://github.com/spring-projects/spring-ldap/blob/main/changelog.txt)
- [Commits](https://github.com/spring-projects/spring-ldap/compare/3.2.11...3.2.12)

---
updated-dependencies:
- dependency-name: org.springframework.ldap:spring-ldap-core
  dependency-version: 3.2.12
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-17 20:57:53 -07:00
github-actions[bot] 254c9c9b2d Merge branch '6.3.x' into 6.4.x 2025-04-18 03:50:03 +00:00
dependabot[bot] a5d963387b Bump org.springframework:spring-framework-bom from 6.1.18 to 6.1.19
Bumps [org.springframework:spring-framework-bom](https://github.com/spring-projects/spring-framework) from 6.1.18 to 6.1.19.
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.18...v6.1.19)

---
updated-dependencies:
- dependency-name: org.springframework:spring-framework-bom
  dependency-version: 6.1.19
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-17 20:49:18 -07:00
github-actions[bot] e5d9659b8f Merge branch '6.3.x' into 6.4.x 2025-04-18 03:37:29 +00:00
dependabot[bot] 99c4f58c34 Bump org.springframework.ldap:spring-ldap-core from 3.2.11 to 3.2.12
Bumps [org.springframework.ldap:spring-ldap-core](https://github.com/spring-projects/spring-ldap) from 3.2.11 to 3.2.12.
- [Release notes](https://github.com/spring-projects/spring-ldap/releases)
- [Changelog](https://github.com/spring-projects/spring-ldap/blob/main/changelog.txt)
- [Commits](https://github.com/spring-projects/spring-ldap/compare/3.2.11...3.2.12)

---
updated-dependencies:
- dependency-name: org.springframework.ldap:spring-ldap-core
  dependency-version: 3.2.12
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-17 20:36:42 -07:00
Joe Grandja cb60d8b3ed Merge branch '6.3.x' into 6.4.x
Closes gh-16951
2025-04-17 05:17:38 -04:00
Joe Grandja c1aa99fdd2 Enforce BCrypt password length for new passwords only
Closes gh-16802
2025-04-17 04:53:33 -04:00
dependabot[bot] f1a211ae0c Bump io.projectreactor:reactor-bom from 2023.0.16 to 2023.0.17
Bumps [io.projectreactor:reactor-bom](https://github.com/reactor/reactor) from 2023.0.16 to 2023.0.17.
- [Release notes](https://github.com/reactor/reactor/releases)
- [Commits](https://github.com/reactor/reactor/compare/2023.0.16...2023.0.17)

---
updated-dependencies:
- dependency-name: io.projectreactor:reactor-bom
  dependency-version: 2023.0.17
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-15 21:22:57 -07:00
github-actions[bot] a1481572ed Merge branch '6.3.x' into 6.4.x 2025-04-16 03:51:45 +00:00
dependabot[bot] eb01394427 Bump io.projectreactor:reactor-bom from 2023.0.16 to 2023.0.17
Bumps [io.projectreactor:reactor-bom](https://github.com/reactor/reactor) from 2023.0.16 to 2023.0.17.
- [Release notes](https://github.com/reactor/reactor/releases)
- [Commits](https://github.com/reactor/reactor/compare/2023.0.16...2023.0.17)

---
updated-dependencies:
- dependency-name: io.projectreactor:reactor-bom
  dependency-version: 2023.0.17
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-15 20:50:56 -07:00
dependabot[bot] 0ff3474e2d Bump io.micrometer:micrometer-observation from 1.14.5 to 1.14.6
Bumps [io.micrometer:micrometer-observation](https://github.com/micrometer-metrics/micrometer) from 1.14.5 to 1.14.6.
- [Release notes](https://github.com/micrometer-metrics/micrometer/releases)
- [Commits](https://github.com/micrometer-metrics/micrometer/compare/v1.14.5...v1.14.6)

---
updated-dependencies:
- dependency-name: io.micrometer:micrometer-observation
  dependency-version: 1.14.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 20:34:10 -07:00
dependabot[bot] 2ce4aecec7 Bump org-aspectj from 1.9.22.1 to 1.9.24
Bumps `org-aspectj` from 1.9.22.1 to 1.9.24.

Updates `org.aspectj:aspectjrt` from 1.9.22.1 to 1.9.24
- [Release notes](https://github.com/eclipse/org.aspectj/releases)
- [Commits](https://github.com/eclipse/org.aspectj/commits)

Updates `org.aspectj:aspectjweaver` from 1.9.22.1 to 1.9.24
- [Release notes](https://github.com/eclipse/org.aspectj/releases)
- [Commits](https://github.com/eclipse/org.aspectj/commits)

---
updated-dependencies:
- dependency-name: org.aspectj:aspectjrt
  dependency-version: 1.9.24
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.aspectj:aspectjweaver
  dependency-version: 1.9.24
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-13 20:30:04 -07:00
github-actions[bot] 7c90300912 Merge branch '6.3.x' into 6.4.x 2025-04-14 03:23:18 +00:00
dependabot[bot] 0d3d6f75f8 Bump org-aspectj from 1.9.22.1 to 1.9.24
Bumps `org-aspectj` from 1.9.22.1 to 1.9.24.

Updates `org.aspectj:aspectjrt` from 1.9.22.1 to 1.9.24
- [Release notes](https://github.com/eclipse/org.aspectj/releases)
- [Commits](https://github.com/eclipse/org.aspectj/commits)

Updates `org.aspectj:aspectjweaver` from 1.9.22.1 to 1.9.24
- [Release notes](https://github.com/eclipse/org.aspectj/releases)
- [Commits](https://github.com/eclipse/org.aspectj/commits)

---
updated-dependencies:
- dependency-name: org.aspectj:aspectjrt
  dependency-version: 1.9.24
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.aspectj:aspectjweaver
  dependency-version: 1.9.24
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-13 20:22:34 -07:00
dependabot[bot] a10a35c2ac Bump io.spring.gradle:spring-security-release-plugin from 1.0.3 to 1.0.4
Bumps [io.spring.gradle:spring-security-release-plugin](https://github.com/spring-io/spring-security-release-tools) from 1.0.3 to 1.0.4.
- [Release notes](https://github.com/spring-io/spring-security-release-tools/releases)
- [Commits](https://github.com/spring-io/spring-security-release-tools/compare/v1.0.3...v1.0.4)

---
updated-dependencies:
- dependency-name: io.spring.gradle:spring-security-release-plugin
  dependency-version: 1.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-09 21:12:41 -07:00
github-actions[bot] ee13d19503 Merge branch '6.3.x' into 6.4.x 2025-04-10 03:34:09 +00:00
dependabot[bot] eb83c35ded Bump io.spring.gradle:spring-security-release-plugin from 1.0.3 to 1.0.4
Bumps [io.spring.gradle:spring-security-release-plugin](https://github.com/spring-io/spring-security-release-tools) from 1.0.3 to 1.0.4.
- [Release notes](https://github.com/spring-io/spring-security-release-tools/releases)
- [Commits](https://github.com/spring-io/spring-security-release-tools/compare/v1.0.3...v1.0.4)

---
updated-dependencies:
- dependency-name: io.spring.gradle:spring-security-release-plugin
  dependency-version: 1.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-09 20:33:22 -07:00
Steve Riesenberg db34de59bc Merge branch '6.3.x' into 6.4.x
Closes gh-16901
2025-04-07 10:55:51 -05:00
Steve Riesenberg 3c0fef59b5 Polish gh-16039
Closes gh-16038
2025-04-07 10:54:09 -05:00
Jonah Klöckner da94fbe431 Evaluate URI query parameter only if enabled
Issue gh-16038
2025-04-07 10:54:07 -05:00
dependabot[bot] a081402383 Bump org.hibernate.orm:hibernate-core from 6.6.12.Final to 6.6.13.Final
Bumps [org.hibernate.orm:hibernate-core](https://github.com/hibernate/hibernate-orm) from 6.6.12.Final to 6.6.13.Final.
- [Release notes](https://github.com/hibernate/hibernate-orm/releases)
- [Changelog](https://github.com/hibernate/hibernate-orm/blob/6.6.13/changelog.txt)
- [Commits](https://github.com/hibernate/hibernate-orm/compare/6.6.12...6.6.13)

---
updated-dependencies:
- dependency-name: org.hibernate.orm:hibernate-core
  dependency-version: 6.6.13.Final
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-06 20:55:51 -07:00
dependabot[bot] f3c8262a00 Bump spring-io/spring-doc-actions from 0.0.19 to 0.0.20
Bumps [spring-io/spring-doc-actions](https://github.com/spring-io/spring-doc-actions) from 0.0.19 to 0.0.20.
- [Commits](https://github.com/spring-io/spring-doc-actions/compare/c2038265125ec6f305a4a041d892ee44c156a754...e28269199d1d27975cf7f65e16d6095c555b3cd0)

---
updated-dependencies:
- dependency-name: spring-io/spring-doc-actions
  dependency-version: 0.0.20
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-06 17:22:18 -07:00
Josh Cummings 0954638d57 Merge branch '6.3.x' into 6.4.x
Closes gh-16862
2025-04-01 12:02:25 -06:00
DingHao 857ef6fe08 WithHttpOnlyCookie defaults to false
Closes gh-16820

Signed-off-by: DingHao <dh.hiekn@gmail.com>
2025-04-01 11:59:51 -06:00
dependabot[bot] 55815103a5 Bump org.hibernate.orm:hibernate-core from 6.6.11.Final to 6.6.12.Final
Bumps [org.hibernate.orm:hibernate-core](https://github.com/hibernate/hibernate-orm) from 6.6.11.Final to 6.6.12.Final.
- [Release notes](https://github.com/hibernate/hibernate-orm/releases)
- [Changelog](https://github.com/hibernate/hibernate-orm/blob/6.6.12/changelog.txt)
- [Commits](https://github.com/hibernate/hibernate-orm/compare/6.6.11...6.6.12)

---
updated-dependencies:
- dependency-name: org.hibernate.orm:hibernate-core
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-30 21:00:22 -07:00
Steve Riesenberg 26c63aeb01 Merge branch '6.3.x' into 6.4.x
Closes gh-16844
2025-03-28 16:34:01 -05:00
Steve Riesenberg b7df86197c Apply request-handler-ref to CsrfAuthenticationStrategy
Closes gh-16801
2025-03-28 16:25:52 -05:00
Steve Riesenberg c84c438075 Apply request-handler-ref to CsrfAuthenticationStrategy
Closes gh-16801
2025-03-28 16:08:36 -05:00
Josh Cummings 1ad4323cec Merge branch '6.3.x' into 6.4.x 2025-03-27 16:43:43 -06:00
DingHao 1e7db094d1 Use correct message prompt
Signed-off-by: DingHao <dh.hiekn@gmail.com>
2025-03-27 16:42:52 -06:00
Josh Cummings 6c5b6d1c51 Merge branch '6.3.x' into 6.4.x
Closes gh-16837
2025-03-27 16:32:12 -06:00
Josh Cummings 456604ab45 Sort Default Advisors and Added Advisors
This commit ensures that the default advisors and added advisors
are sorted in the event that this component is not being published
as a Spring bean.

Issue gh-16819
2025-03-27 16:18:00 -06:00
Josh Cummings 15b9a50060 Add Test
Issue gh-16819
2025-03-27 16:18:00 -06:00
Tran Ngoc Nhan fcc1bd598d Sort Advisors AfterSingletonsInstantiated
In order to make so that authorization advisors are sorted
only one time and also as part of the configuration lifecycle,
AuthorizationAdvisorProxyFactory now implements
SmartInitializingBean.

Closes gh-16819

Signed-off-by: Tran Ngoc Nhan <ngocnhan.tran1996@gmail.com>
2025-03-27 16:18:00 -06:00
Rob Winch 1f3dd53bdf Fix WebAuthn saves Anonymous PublicKeyCredentialUserEntity
Closes gh-16606
2025-03-25 16:14:58 -05:00
Rob Winch a6b5c05da9 Additional WebAuthn4jRelyingPartyOperationTests
- verify that anonymous users not saved
- verify that when user found the CredentialRecord is allowed

Issue gh-16385
2025-03-25 16:14:25 -05:00
Rob Winch 9c054474a8 Use Test Name Conventions
Issue gh-16385
2025-03-25 16:14:25 -05:00
Rob Winch 593f7c4490 Use !isAuthenticated
It's more verbose to see if the user is not null and not anonymous

Issue gh-16385
2025-03-25 16:14:25 -05:00
Rob Winch 4e20d56d2d Fix format for WebAuthn4jRelyingPartyOperations
Issue gh-16385
2025-03-25 16:14:25 -05:00
Josh Cummings 26aa253633 Merge branch '6.3.x' into 6.4.x 2025-03-25 15:11:42 -06:00
github-actions[bot] af2668f7cb Bump Gradle Wrapper from 8.10.2 to 8.13.
Release notes of Gradle 8.13 can be found here:
https://docs.gradle.org/8.13/release-notes.html

Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-03-25 15:11:10 -06:00
Tomas Borghi 0a084135ec Delete import unused
Signed-off-by: Tomas Borghi <137845283+Borghii@users.noreply.github.com>
2025-03-24 16:50:39 -03:00
Tomas Borghi 5571ad1b27 Fix issues identified in PR review
Signed-off-by: Tomas Borghi <137845283+Borghii@users.noreply.github.com>
2025-03-24 13:18:23 -03:00
Borghi e3a715b8f5 Fix issues identified in PR review
Signed-off-by: Borghi <137845283+Borghii@users.noreply.github.com>
2025-03-24 13:00:27 -03:00
dependabot[bot] 2f04512e01 Bump spring-io/spring-doc-actions from 0.0.18 to 0.0.19
Bumps [spring-io/spring-doc-actions](https://github.com/spring-io/spring-doc-actions) from 0.0.18 to 0.0.19.
- [Commits](https://github.com/spring-io/spring-doc-actions/compare/852920ba3fb1f28b35a2f13201133bc00ef33677...c2038265125ec6f305a4a041d892ee44c156a754)

---
updated-dependencies:
- dependency-name: spring-io/spring-doc-actions
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-23 18:49:53 -07:00
github-actions[bot] 23444dd13f Merge branch '6.3.x' into 6.4.x 2025-03-24 01:41:22 +00:00
dependabot[bot] 883765b2de Bump @springio/asciidoctor-extensions in /docs
Bumps [@springio/asciidoctor-extensions](https://github.com/spring-io/asciidoctor-extensions) from 1.0.0-alpha.16 to 1.0.0-alpha.17.
- [Changelog](https://github.com/spring-io/asciidoctor-extensions/blob/main/CHANGELOG.adoc)
- [Commits](https://github.com/spring-io/asciidoctor-extensions/compare/v1.0.0-alpha.16...v1.0.0-alpha.17)

---
updated-dependencies:
- dependency-name: "@springio/asciidoctor-extensions"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-23 18:40:37 -07:00
Rob Winch c032b20178 Merge branch '6.3.x' into 6.4.x 2025-03-21 15:59:51 -05:00
Rob Winch 58e7ba4a4b https docs download 2025-03-21 15:59:39 -05:00
Josh Cummings db8b6322e2 Merge branch '6.3.x' into 6.4.x 2025-03-21 14:47:24 -06:00
Bragolgirith 72554f7f36 Update authorize-http-requests.adoc
Fix patterns in the Security Matchers documentation

Signed-off-by: Bragolgirith <6455473+Bragolgirith@users.noreply.github.com>
2025-03-21 14:46:53 -06:00
Rob Winch af8786150e Merge branch '6.3.x' into 6.4.x
Closes gh-16799
2025-03-21 15:11:18 -05:00
Rob Winch 65e83f8e7a Add link to docs zip
Closes gh-16798
2025-03-21 15:10:52 -05:00
Steve Riesenberg 96cfbd1e6c Merge branch '6.3.x' into 6.4.x
Closes gh-16782
Closes gh-16783
Closes gh-16784
Closes gh-16785
Closes gh-16786
2025-03-20 14:46:18 -05:00
Tran Ngoc Nhan ab6e9d2d1f Clarify WebInvocationPrivilegeEvaluator JavaDoc
Closes gh-16529

Signed-off-by: Tran Ngoc Nhan <ngocnhan.tran1996@gmail.com>
2025-03-20 14:38:10 -05:00
Tran Ngoc Nhan a53ca7c3d0 Update ServerOAuth2AuthorizedClientExchangeFilterFunction javadoc
Closes gh-16555

Signed-off-by: Tran Ngoc Nhan <ngocnhan.tran1996@gmail.com>
2025-03-20 14:38:09 -05:00
Tran Ngoc Nhan af40d7e35a Fix typo
Closes gh-16776

Signed-off-by: Tran Ngoc Nhan <ngocnhan.tran1996@gmail.com>
2025-03-20 14:38:09 -05:00
Tran Ngoc Nhan daf8cfe8d2 Fix Spring Framework reference link
Closes gh-16699

Signed-off-by: Tran Ngoc Nhan <ngocnhan.tran1996@gmail.com>
2025-03-20 14:38:08 -05:00
Tran Ngoc Nhan 75b537f99a Fix WebFlux authentication reference link
Closes gh-16702

Signed-off-by: Tran Ngoc Nhan <ngocnhan.tran1996@gmail.com>
2025-03-20 14:38:07 -05:00
Josh Cummings 55d61224e5 Merge branch '6.3.x' into 6.4.x 2025-03-20 13:25:04 -06:00
Josh Cummings d1b7f8a119 Update Gradle Wrapper Upgrade
Issue gh-16221
2025-03-20 13:23:49 -06:00
Josh Cummings 85c906290d Merge branch '6.3.x' into 6.4.x 2025-03-20 13:22:45 -06:00
dependabot[bot] 68f08c26d0 Bump org.springframework:spring-framework-bom from 6.2.4 to 6.2.5
Bumps [org.springframework:spring-framework-bom](https://github.com/spring-projects/spring-framework) from 6.2.4 to 6.2.5.
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.4...v6.2.5)

---
updated-dependencies:
- dependency-name: org.springframework:spring-framework-bom
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-19 21:08:40 -07:00
dependabot[bot] 5353d499b4 Bump ch.qos.logback:logback-classic from 1.5.17 to 1.5.18
Bumps [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback) from 1.5.17 to 1.5.18.
- [Release notes](https://github.com/qos-ch/logback/releases)
- [Commits](https://github.com/qos-ch/logback/compare/v_1.5.17...v_1.5.18)

---
updated-dependencies:
- dependency-name: ch.qos.logback:logback-classic
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-18 20:41:11 -07:00
dependabot[bot] 60df37b026 Bump ch.qos.logback:logback-classic from 1.5.17 to 1.5.18
Bumps [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback) from 1.5.17 to 1.5.18.
- [Release notes](https://github.com/qos-ch/logback/releases)
- [Commits](https://github.com/qos-ch/logback/compare/v_1.5.17...v_1.5.18)

---
updated-dependencies:
- dependency-name: ch.qos.logback:logback-classic
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-18 20:36:39 -07:00
AB d9a937f0c1 Correct Closing Tag
Closes gh-16600

Signed-off-by: AB <a.bierler@xdev-software.de>
2025-03-18 16:35:15 -06:00
dependabot[bot] 06893bc047 Bump org-eclipse-jetty from 11.0.24 to 11.0.25
Bumps `org-eclipse-jetty` from 11.0.24 to 11.0.25.

Updates `org.eclipse.jetty:jetty-server` from 11.0.24 to 11.0.25

Updates `org.eclipse.jetty:jetty-servlet` from 11.0.24 to 11.0.25

---
updated-dependencies:
- dependency-name: org.eclipse.jetty:jetty-server
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.eclipse.jetty:jetty-servlet
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-17 21:04:05 -07:00
dependabot[bot] 1d75b907f9 Bump org-eclipse-jetty from 11.0.24 to 11.0.25
Bumps `org-eclipse-jetty` from 11.0.24 to 11.0.25.

Updates `org.eclipse.jetty:jetty-server` from 11.0.24 to 11.0.25

Updates `org.eclipse.jetty:jetty-servlet` from 11.0.24 to 11.0.25

---
updated-dependencies:
- dependency-name: org.eclipse.jetty:jetty-server
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.eclipse.jetty:jetty-servlet
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-17 20:56:08 -07:00
github-actions[bot] 7dbd69fee1 Next development version 2025-03-17 21:31:02 +00:00
github-actions[bot] 816f3cd64d Next development version 2025-03-17 21:30:52 +00:00
github-actions[bot] 147081f771 Release 6.3.8 2025-03-17 20:59:34 +00:00
Borghi 0bc9313fdd Fix bug PublicKeyCredentialUserEntityRepository saves anonymousUser
Issue gh-16385

Signed-off-by: Borghi <137845283+Borghii@users.noreply.github.com>
2025-02-16 22:50:34 -03:00
53 changed files with 530 additions and 317 deletions
@@ -18,7 +18,7 @@ jobs:
matrix:
branch: [ '5.8.x', '6.2.x', '6.3.x', 'main' ]
steps:
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@852920ba3fb1f28b35a2f13201133bc00ef33677
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@e28269199d1d27975cf7f65e16d6095c555b3cd0
name: Update
with:
docs-branch: ${{ matrix.branch }}
@@ -28,7 +28,7 @@ jobs:
runs-on: ubuntu-latest
name: Update on docs-build
steps:
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@852920ba3fb1f28b35a2f13201133bc00ef33677
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@e28269199d1d27975cf7f65e16d6095c555b3cd0
name: Update
with:
docs-branch: 'docs-build'
+1 -1
View File
@@ -124,7 +124,7 @@ wrapperUpgrade {
gradle {
'spring-security' {
repo = 'spring-projects/spring-security'
baseBranch = '6.2.x' // runs only on 6.2.x and the update is merged forward to main
baseBranch = '6.3.x' // runs only on 6.3.x and the update is merged forward to main
}
}
}
@@ -183,6 +183,9 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
BeanDefinitionBuilder csrfAuthenticationStrategy = BeanDefinitionBuilder
.rootBeanDefinition(CsrfAuthenticationStrategy.class);
csrfAuthenticationStrategy.addConstructorArgReference(this.csrfRepositoryRef);
if (StringUtils.hasText(this.requestHandlerRef)) {
csrfAuthenticationStrategy.addPropertyReference("requestHandler", this.requestHandlerRef);
}
return csrfAuthenticationStrategy.getBeanDefinition();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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,6 +56,7 @@ 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.AnnotationAwareOrderComparator;
import org.springframework.core.annotation.AnnotationConfigurationException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.PermissionEvaluator;
@@ -1103,6 +1104,21 @@ public class PrePostMethodSecurityConfigurationTests {
verifyNoInteractions(handler);
}
// gh-16819
@Test
void autowireWhenDefaultsThenAdvisorAnnotationsAreSorted() {
this.spring.register(MethodSecurityServiceConfig.class).autowire();
AuthorizationAdvisorProxyFactory proxyFactory = this.spring.getContext()
.getBean(AuthorizationAdvisorProxyFactory.class);
AnnotationAwareOrderComparator comparator = AnnotationAwareOrderComparator.INSTANCE;
AuthorizationAdvisor previous = null;
for (AuthorizationAdvisor advisor : proxyFactory) {
boolean ordered = previous == null || comparator.compare(previous, advisor) < 0;
assertThat(ordered).isTrue();
previous = advisor;
}
}
private static Consumer<ConfigurableWebApplicationContext> disallowBeanOverriding() {
return (context) -> ((AnnotationConfigWebApplicationContext) context).setAllowBeanDefinitionOverriding(false);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2025 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.
@@ -1560,12 +1560,15 @@ public class OAuth2ResourceServerConfigurerTests {
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// @formatter:off
DefaultBearerTokenResolver defaultBearerTokenResolver = new DefaultBearerTokenResolver();
defaultBearerTokenResolver.setAllowUriQueryParameter(true);
http
.authorizeRequests()
.requestMatchers("/requires-read-scope").access("hasAuthority('SCOPE_message:read')")
.anyRequest().authenticated()
.and()
.oauth2ResourceServer()
.bearerTokenResolver(defaultBearerTokenResolver)
.jwt()
.jwkSetUri(this.jwkSetUri);
return http.build();
@@ -336,6 +336,43 @@ public class CsrfConfigTests {
// @formatter:on
}
@Test
public void postWhenUsingCsrfAndXorCsrfTokenRequestAttributeHandlerThenCsrfAuthenticationStrategyUses()
throws Exception {
this.spring.configLocations(this.xml("WithXorCsrfTokenRequestAttributeHandler"), this.xml("shared-controllers"))
.autowire();
// @formatter:off
MvcResult mvcResult1 = this.mvc.perform(get("/csrf"))
.andExpect(status().isOk())
.andReturn();
// @formatter:on
MockHttpServletRequest request1 = mvcResult1.getRequest();
MockHttpSession session = (MockHttpSession) request1.getSession();
CsrfTokenRepository repository = WebTestUtils.getCsrfTokenRepository(request1);
// @formatter:off
MockHttpServletRequestBuilder login = post("/login")
.param("username", "user")
.param("password", "password")
.session(session)
.with(csrf());
this.mvc.perform(login)
.andExpect(status().is3xxRedirection())
.andExpect(redirectedUrl("/"));
// @formatter:on
assertThat(repository.loadToken(request1)).isNull();
// @formatter:off
MvcResult mvcResult2 = this.mvc.perform(get("/csrf").session(session))
.andExpect(status().isOk())
.andReturn();
// @formatter:on
MockHttpServletRequest request2 = mvcResult2.getRequest();
CsrfToken csrfToken = repository.loadToken(request2);
CsrfToken csrfTokenAttribute = (CsrfToken) request2.getAttribute(CsrfToken.class.getName());
assertThat(csrfTokenAttribute).isNotNull();
assertThat(csrfTokenAttribute.getToken()).isNotBlank();
assertThat(csrfTokenAttribute.getToken()).isNotEqualTo(csrfToken.getToken());
}
@Test
public void postWhenHasCsrfTokenButSessionExpiresThenRequestIsCancelledAfterSuccessfulAuthentication()
throws Exception {
@@ -25,10 +25,15 @@
<c:property-placeholder local-override="true"/>
<b:bean id="bearerTokenResolver"
class="org.springframework.security.oauth2.server.resource.web.DefaultBearerTokenResolver">
<b:property name="allowUriQueryParameter" value="true"/>
</b:bean>
<http>
<intercept-url pattern="/**" access="authenticated"/>
<intercept-url pattern="/requires-read-scope" access="hasAuthority('SCOPE_message:read')"/>
<oauth2-resource-server>
<oauth2-resource-server bearer-token-resolver-ref="bearerTokenResolver">
<jwt jwk-set-uri="${jwk-set-uri:https://idp.example.org}"/>
</oauth2-resource-server>
</http>
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -47,6 +47,7 @@ import org.springframework.aop.Advisor;
import org.springframework.aop.Pointcut;
import org.springframework.aop.framework.AopInfrastructureBean;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.lang.NonNull;
import org.springframework.security.authorization.AuthorizationProxyFactory;
@@ -79,8 +80,8 @@ import org.springframework.util.ClassUtils;
* @author Josh Cummings
* @since 6.3
*/
public final class AuthorizationAdvisorProxyFactory
implements AuthorizationProxyFactory, Iterable<AuthorizationAdvisor>, AopInfrastructureBean {
public final class AuthorizationAdvisorProxyFactory implements AuthorizationProxyFactory,
Iterable<AuthorizationAdvisor>, AopInfrastructureBean, SmartInitializingSingleton {
private static final boolean isReactivePresent = ClassUtils.isPresent("reactor.core.publisher.Mono", null);
@@ -125,6 +126,7 @@ public final class AuthorizationAdvisorProxyFactory
advisors.add(new PostFilterAuthorizationMethodInterceptor());
AuthorizationAdvisorProxyFactory proxyFactory = new AuthorizationAdvisorProxyFactory(advisors);
proxyFactory.addAdvisor(new AuthorizeReturnObjectMethodInterceptor(proxyFactory));
AnnotationAwareOrderComparator.sort(proxyFactory.advisors);
return proxyFactory;
}
@@ -142,9 +144,15 @@ public final class AuthorizationAdvisorProxyFactory
advisors.add(new PostFilterAuthorizationReactiveMethodInterceptor());
AuthorizationAdvisorProxyFactory proxyFactory = new AuthorizationAdvisorProxyFactory(advisors);
proxyFactory.addAdvisor(new AuthorizeReturnObjectMethodInterceptor(proxyFactory));
AnnotationAwareOrderComparator.sort(proxyFactory.advisors);
return proxyFactory;
}
@Override
public void afterSingletonsInstantiated() {
AnnotationAwareOrderComparator.sort(this.advisors);
}
/**
* Proxy an object to enforce authorization advice.
*
@@ -165,7 +173,6 @@ public final class AuthorizationAdvisorProxyFactory
*/
@Override
public Object proxy(Object target) {
AnnotationAwareOrderComparator.sort(this.advisors);
if (target == null) {
return null;
}
@@ -178,9 +185,9 @@ public final class AuthorizationAdvisorProxyFactory
}
ProxyFactory factory = new ProxyFactory(target);
factory.addAdvisors(this.authorizationProxy);
for (Advisor advisor : this.advisors) {
factory.addAdvisors(advisor);
}
List<Advisor> advisors = new ArrayList<>(this.advisors);
AnnotationAwareOrderComparator.sort(advisors);
factory.addAdvisors(advisors);
factory.addInterface(AuthorizationProxy.class);
factory.setOpaque(true);
factory.setProxyTargetClass(!Modifier.isFinal(target.getClass().getModifiers()));
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -48,7 +48,7 @@ public final class AuthorizeReturnObjectMethodInterceptor implements Authorizati
private int order = AuthorizationInterceptorsOrder.SECURE_RESULT.getOrder();
public AuthorizeReturnObjectMethodInterceptor(AuthorizationProxyFactory authorizationProxyFactory) {
Assert.notNull(authorizationProxyFactory, "authorizationManager cannot be null");
Assert.notNull(authorizationProxyFactory, "authorizationProxyFactory cannot be null");
this.authorizationProxyFactory = authorizationProxyFactory;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -40,6 +40,7 @@ import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.Test;
import org.springframework.aop.Pointcut;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.TestAuthentication;
@@ -360,6 +361,32 @@ public class AuthorizationAdvisorProxyFactoryTests {
assertThat(target).isSameAs(this.flight);
}
// gh-16819
@Test
void advisorsWhenWithDefaultsThenAreSorted() {
AuthorizationAdvisorProxyFactory proxyFactory = AuthorizationAdvisorProxyFactory.withDefaults();
AnnotationAwareOrderComparator comparator = AnnotationAwareOrderComparator.INSTANCE;
AuthorizationAdvisor previous = null;
for (AuthorizationAdvisor advisor : proxyFactory) {
boolean ordered = previous == null || comparator.compare(previous, advisor) < 0;
assertThat(ordered).isTrue();
previous = advisor;
}
}
// gh-16819
@Test
void advisorsWhenWithReactiveDefaultsThenAreSorted() {
AuthorizationAdvisorProxyFactory proxyFactory = AuthorizationAdvisorProxyFactory.withReactiveDefaults();
AnnotationAwareOrderComparator comparator = AnnotationAwareOrderComparator.INSTANCE;
AuthorizationAdvisor previous = null;
for (AuthorizationAdvisor advisor : proxyFactory) {
boolean ordered = previous == null || comparator.compare(previous, advisor) < 0;
assertThat(ordered).isTrue();
previous = advisor;
}
}
private Authentication authenticated(String user, String... authorities) {
return TestAuthentication.authenticated(TestAuthentication.withUsername(user).authorities(authorities).build());
}
@@ -611,7 +611,8 @@ public class BCrypt {
int rounds, off;
StringBuilder rs = new StringBuilder();
if (passwordb.length > 72) {
// Enforce max length for new passwords only
if (!for_check && passwordb.length > 72) {
throw new IllegalArgumentException("password cannot be more than 72 bytes");
}
if (salt == null) {
@@ -223,13 +223,34 @@ public class BCryptPasswordEncoderTests {
}
@Test
public void enforcePasswordLength() {
public void encodeWhenPasswordOverMaxLengthThenThrowIllegalArgumentException() {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
String password72chars = "123456789012345678901234567890123456789012345678901234567890123456789012";
assertThat(encoder.matches(password72chars, encoder.encode(password72chars))).isTrue();
String password73chars = password72chars.concat("a");
assertThatIllegalArgumentException()
.isThrownBy(() -> encoder.matches(password73chars, encoder.encode(password73chars)));
encoder.encode(password72chars);
String password73chars = password72chars + "3";
assertThatIllegalArgumentException().isThrownBy(() -> encoder.encode(password73chars));
}
@Test
public void matchesWhenPasswordOverMaxLengthThenAllowToMatch() {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
String password71chars = "12345678901234567890123456789012345678901234567890123456789012345678901";
String encodedPassword71chars = "$2a$10$jx3x2FaF.iX5QZ9i3O424Os2Ou5P5JrnedmWYHuDyX8JKA4Unp4xq";
assertThat(encoder.matches(password71chars, encodedPassword71chars)).isTrue();
String password72chars = password71chars + "2";
String encodedPassword72chars = "$2a$10$oXYO6/UvbsH5rQEraBkl6uheccBqdB3n.RaWbrimog9hS2GX4lo/O";
assertThat(encoder.matches(password72chars, encodedPassword72chars)).isTrue();
// Max length is 72 bytes, however, we need to ensure backwards compatibility
// for previously encoded passwords that are greater than 72 bytes and allow the
// match to be performed.
String password73chars = password72chars + "3";
String encodedPassword73chars = "$2a$10$1l9.kvQTsqNLiCYFqmKtQOHkp.BrgIrwsnTzWo9jdbQRbuBYQ/AVK";
assertThat(encoder.matches(password73chars, encodedPassword73chars)).isTrue();
}
}
+1 -1
View File
@@ -132,7 +132,7 @@
*** xref:servlet/appendix/faq.adoc[FAQ]
* xref:reactive/index.adoc[Reactive Applications]
** xref:reactive/getting-started.adoc[Getting Started]
** Authentication
** xref:reactive/authentication/index.adoc[Authentication]
*** xref:reactive/authentication/x509.adoc[X.509 Authentication]
*** xref:reactive/authentication/logout.adoc[Logout]
*** Session Management
@@ -8,4 +8,4 @@ Once authentication is performed we know the identity and can perform authorizat
Spring Security provides built-in support for authenticating users.
This section is dedicated to generic authentication support that applies in both Servlet and WebFlux environments.
Refer to the sections on authentication for xref:servlet/authentication/index.adoc#servlet-authentication[Servlet] and xref:servlet/authentication/index.adoc[WebFlux] for details on what is supported for each stack.
Refer to the sections on authentication for xref:servlet/authentication/index.adoc[Servlet] and xref:reactive/authentication/index.adoc[WebFlux] for details on what is supported for each stack.
+5
View File
@@ -1,5 +1,10 @@
= Spring Security
[NOTE]
====
Spring Security's documentation can be https://docs.spring.io/spring-security/reference/spring-security-docs.zip[downloaded] as a zip file.
====
Spring Security is a framework that provides xref:features/authentication/index.adoc[authentication], xref:features/authorization/index.adoc[authorization], and xref:features/exploits/index.adoc[protection against common attacks].
With first class support for securing both xref:servlet/index.adoc[imperative] and xref:reactive/index.adoc[reactive] applications, it is the de-facto standard for securing Spring-based applications.
@@ -0,0 +1,3 @@
[[webflux-authentication]]
= Authentication
:page-section-summary-toc: 1
@@ -34,7 +34,7 @@ The attributes on the `<http>` element control some of the properties on the cor
Use AuthorizationManager API instead of SecurityMetadataSource (defaults to true)
[[nsa-http-authorization-manager-ref]]
* **access-decision-manager-ref**
* **use-authorization-manager**
Use this AuthorizationManager instead of deriving one from <intercept-url> elements
[[nsa-http-access-decision-manager-ref]]
@@ -1048,8 +1048,8 @@ public class SecurityConfig {
http
.securityMatcher("/api/**") <1>
.authorizeHttpRequests(authorize -> authorize
.requestMatchers("/user/**").hasRole("USER") <2>
.requestMatchers("/admin/**").hasRole("ADMIN") <3>
.requestMatchers("/api/user/**").hasRole("USER") <2>
.requestMatchers("/api/admin/**").hasRole("ADMIN") <3>
.anyRequest().authenticated() <4>
)
.formLogin(withDefaults());
@@ -1071,8 +1071,8 @@ open class SecurityConfig {
http {
securityMatcher("/api/**") <1>
authorizeHttpRequests {
authorize("/user/**", hasRole("USER")) <2>
authorize("/admin/**", hasRole("ADMIN")) <3>
authorize("/api/user/**", hasRole("USER")) <2>
authorize("/api/admin/**", hasRole("ADMIN")) <3>
authorize(anyRequest, authenticated) <4>
}
}
@@ -1084,8 +1084,8 @@ open class SecurityConfig {
======
<1> Configure `HttpSecurity` to only be applied to URLs that start with `/api/`
<2> Allow access to URLs that start with `/user/` to users with the `USER` role
<3> Allow access to URLs that start with `/admin/` to users with the `ADMIN` role
<2> Allow access to URLs that start with `/api/user/` to users with the `USER` role
<3> Allow access to URLs that start with `/api/admin/` to users with the `ADMIN` role
<4> Any other request that doesn't match the rules above, will require authentication
The `securityMatcher(s)` and `requestMatcher(s)` methods will decide which `RequestMatcher` implementation fits best for your application: If {spring-framework-reference-url}web.html#spring-web[Spring MVC] is in the classpath, then javadoc:org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher[] will be used, otherwise, javadoc:org.springframework.security.web.util.matcher.AntPathRequestMatcher[] will be used.
@@ -1111,8 +1111,8 @@ public class SecurityConfig {
http
.securityMatcher(antMatcher("/api/**")) <2>
.authorizeHttpRequests(authorize -> authorize
.requestMatchers(antMatcher("/user/**")).hasRole("USER") <3>
.requestMatchers(regexMatcher("/admin/.*")).hasRole("ADMIN") <4>
.requestMatchers(antMatcher("/api/user/**")).hasRole("USER") <3>
.requestMatchers(regexMatcher("/api/admin/.*")).hasRole("ADMIN") <4>
.requestMatchers(new MyCustomRequestMatcher()).hasRole("SUPERVISOR") <5>
.anyRequest().authenticated()
)
@@ -1146,8 +1146,8 @@ open class SecurityConfig {
http {
securityMatcher(antMatcher("/api/**")) <2>
authorizeHttpRequests {
authorize(antMatcher("/user/**"), hasRole("USER")) <3>
authorize(regexMatcher("/admin/**"), hasRole("ADMIN")) <4>
authorize(antMatcher("/api/user/**"), hasRole("USER")) <3>
authorize(regexMatcher("/api/admin/**"), hasRole("ADMIN")) <4>
authorize(MyCustomRequestMatcher(), hasRole("SUPERVISOR")) <5>
authorize(anyRequest, authenticated)
}
@@ -1161,8 +1161,8 @@ open class SecurityConfig {
<1> Import the static factory methods from `AntPathRequestMatcher` and `RegexRequestMatcher` to create `RequestMatcher` instances.
<2> Configure `HttpSecurity` to only be applied to URLs that start with `/api/`, using `AntPathRequestMatcher`
<3> Allow access to URLs that start with `/user/` to users with the `USER` role, using `AntPathRequestMatcher`
<4> Allow access to URLs that start with `/admin/` to users with the `ADMIN` role, using `RegexRequestMatcher`
<3> Allow access to URLs that start with `/api/user/` to users with the `USER` role, using `AntPathRequestMatcher`
<4> Allow access to URLs that start with `/api/admin/` to users with the `ADMIN` role, using `RegexRequestMatcher`
<5> Allow access to URLs that match the `MyCustomRequestMatcher` to users with the `SUPERVISOR` role, using a custom `RequestMatcher`
== Further Reading
@@ -2,4 +2,4 @@
= Spring MVC Test Integration
:page-section-summary-toc: 1
Spring Security provides comprehensive integration with https://docs.spring.io/spring/docs/current/spring-framework-reference/html/testing.html#spring-mvc-test-framework[Spring MVC Test]
Spring Security provides comprehensive integration with {spring-framework-reference-url}testing/mockmvc.html[Spring MVC Test]
+1 -1
View File
@@ -14,7 +14,7 @@
# limitations under the License.
#
springBootVersion=3.3.3
version=6.4.4
version=6.4.5
samplesBranch=main
org.gradle.jvmargs=-Xmx3g -XX:+HeapDumpOnOutOfMemoryError
org.gradle.parallel=true
+9 -9
View File
@@ -6,18 +6,18 @@ io-spring-nohttp = "0.0.11"
jakarta-websocket = "2.2.0"
org-apache-directory-server = "1.5.5"
org-apache-maven-resolver = "1.9.22"
org-aspectj = "1.9.22.1"
org-aspectj = "1.9.24"
org-bouncycastle = "1.79"
org-eclipse-jetty = "11.0.24"
org-eclipse-jetty = "11.0.25"
org-jetbrains-kotlin = "1.9.25"
org-jetbrains-kotlinx = "1.9.0"
org-mockito = "5.14.2"
org-opensaml = "4.3.2"
org-opensaml5 = "5.1.2"
org-springframework = "6.2.4"
org-springframework = "6.2.6"
[libraries]
ch-qos-logback-logback-classic = "ch.qos.logback:logback-classic:1.5.17"
ch-qos-logback-logback-classic = "ch.qos.logback:logback-classic:1.5.18"
com-fasterxml-jackson-jackson-bom = "com.fasterxml.jackson:jackson-bom:2.18.3"
com-google-inject-guice = "com.google.inject:guice:3.0"
com-netflix-nebula-nebula-project-plugin = "com.netflix.nebula:nebula-project-plugin:8.2.0"
@@ -28,15 +28,15 @@ com-squareup-okhttp3-okhttp = { module = "com.squareup.okhttp3:okhttp", version.
com-unboundid-unboundid-ldapsdk = "com.unboundid:unboundid-ldapsdk:6.0.11"
com-unboundid-unboundid-ldapsdk7 = "com.unboundid:unboundid-ldapsdk:7.0.1"
commons-collections = "commons-collections:commons-collections:3.2.2"
io-micrometer-micrometer-observation = "io.micrometer:micrometer-observation:1.14.5"
io-micrometer-micrometer-observation = "io.micrometer:micrometer-observation:1.14.6"
io-mockk = "io.mockk:mockk:1.13.17"
io-projectreactor-reactor-bom = "io.projectreactor:reactor-bom:2023.0.16"
io-projectreactor-reactor-bom = "io.projectreactor:reactor-bom:2023.0.17"
io-rsocket-rsocket-bom = { module = "io.rsocket:rsocket-bom", version.ref = "io-rsocket" }
io-spring-javaformat-spring-javaformat-checkstyle = { module = "io.spring.javaformat:spring-javaformat-checkstyle", version.ref = "io-spring-javaformat" }
io-spring-javaformat-spring-javaformat-gradle-plugin = { module = "io.spring.javaformat:spring-javaformat-gradle-plugin", version.ref = "io-spring-javaformat" }
io-spring-nohttp-nohttp-checkstyle = { module = "io.spring.nohttp:nohttp-checkstyle", version.ref = "io-spring-nohttp" }
io-spring-nohttp-nohttp-gradle = { module = "io.spring.nohttp:nohttp-gradle", version.ref = "io-spring-nohttp" }
io-spring-security-release-plugin = "io.spring.gradle:spring-security-release-plugin:1.0.3"
io-spring-security-release-plugin = "io.spring.gradle:spring-security-release-plugin:1.0.4"
jakarta-annotation-jakarta-annotation-api = "jakarta.annotation:jakarta.annotation-api:2.1.1"
jakarta-inject-jakarta-inject-api = "jakarta.inject:jakarta.inject-api:2.0.1"
jakarta-persistence-jakarta-persistence-api = "jakarta.persistence:jakarta.persistence-api:3.1.0"
@@ -70,7 +70,7 @@ org-bouncycastle-bcprov-jdk15on = { module = "org.bouncycastle:bcprov-jdk18on",
org-eclipse-jetty-jetty-server = { module = "org.eclipse.jetty:jetty-server", version.ref = "org-eclipse-jetty" }
org-eclipse-jetty-jetty-servlet = { module = "org.eclipse.jetty:jetty-servlet", version.ref = "org-eclipse-jetty" }
org-hamcrest = "org.hamcrest:hamcrest:2.2"
org-hibernate-orm-hibernate-core = "org.hibernate.orm:hibernate-core:6.6.11.Final"
org-hibernate-orm-hibernate-core = "org.hibernate.orm:hibernate-core:6.6.13.Final"
org-hsqldb = "org.hsqldb:hsqldb:2.7.4"
org-jetbrains-kotlin-kotlin-bom = { module = "org.jetbrains.kotlin:kotlin-bom", version.ref = "org-jetbrains-kotlin" }
org-jetbrains-kotlin-kotlin-gradle-plugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.25"
@@ -89,7 +89,7 @@ org-skyscreamer-jsonassert = "org.skyscreamer:jsonassert:1.5.3"
org-slf4j-log4j-over-slf4j = "org.slf4j:log4j-over-slf4j:1.7.36"
org-slf4j-slf4j-api = "org.slf4j:slf4j-api:2.0.17"
org-springframework-data-spring-data-bom = "org.springframework.data:spring-data-bom:2024.1.4"
org-springframework-ldap-spring-ldap-core = "org.springframework.ldap:spring-ldap-core:3.2.11"
org-springframework-ldap-spring-ldap-core = "org.springframework.ldap:spring-ldap-core:3.2.12"
org-springframework-spring-framework-bom = { module = "org.springframework:spring-framework-bom", version.ref = "org-springframework" }
org-synchronoss-cloud-nio-multipart-parser = "org.synchronoss.cloud:nio-multipart-parser:1.1.0"
Binary file not shown.
+2 -2
View File
@@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=8d97a97984f6cbd2b85fe4c60a743440a347544bf18818048e611f5288d46c94
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
distributionSha256Sum=20f1b1176237254a6fc204d8434196fa11a4cfb387567519c61556e8710aed78
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Vendored
+2 -3
View File
@@ -86,8 +86,7 @@ done
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -206,7 +205,7 @@ fi
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -245,7 +245,7 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements
* be used to create an Authentication for saving.</li>
* </ul>
* @param authorizedClient the {@link OAuth2AuthorizedClient} to use.
* @return the {@link Consumer} to populate the
* @return the {@link Consumer} to populate the attributes
*/
public static Consumer<Map<String, Object>> oauth2AuthorizedClient(OAuth2AuthorizedClient authorizedClient) {
return (attributes) -> attributes.put(OAUTH2_AUTHORIZED_CLIENT_ATTR_NAME, authorizedClient);
@@ -52,26 +52,77 @@ public final class DefaultBearerTokenResolver implements BearerTokenResolver {
@Override
public String resolve(final HttpServletRequest request) {
final String authorizationHeaderToken = resolveFromAuthorizationHeader(request);
final String parameterToken = isParameterTokenSupportedForRequest(request)
? resolveFromRequestParameters(request) : null;
if (authorizationHeaderToken != null) {
if (parameterToken != null) {
// @formatter:off
return resolveToken(
resolveFromAuthorizationHeader(request),
resolveAccessTokenFromQueryString(request),
resolveAccessTokenFromBody(request)
);
// @formatter:on
}
private static String resolveToken(String... accessTokens) {
if (accessTokens == null || accessTokens.length == 0) {
return null;
}
String accessToken = null;
for (String token : accessTokens) {
if (accessToken == null) {
accessToken = token;
}
else if (token != null) {
BearerTokenError error = BearerTokenErrors
.invalidRequest("Found multiple bearer tokens in the request");
throw new OAuth2AuthenticationException(error);
}
return authorizationHeaderToken;
}
if (parameterToken != null && isParameterTokenEnabledForRequest(request)) {
if (!StringUtils.hasText(parameterToken)) {
BearerTokenError error = BearerTokenErrors
.invalidRequest("The requested token parameter is an empty string");
throw new OAuth2AuthenticationException(error);
}
return parameterToken;
if (accessToken != null && accessToken.isBlank()) {
BearerTokenError error = BearerTokenErrors
.invalidRequest("The requested token parameter is an empty string");
throw new OAuth2AuthenticationException(error);
}
return null;
return accessToken;
}
private String resolveFromAuthorizationHeader(HttpServletRequest request) {
String authorization = request.getHeader(this.bearerTokenHeaderName);
if (!StringUtils.startsWithIgnoreCase(authorization, "bearer")) {
return null;
}
Matcher matcher = authorizationPattern.matcher(authorization);
if (!matcher.matches()) {
BearerTokenError error = BearerTokenErrors.invalidToken("Bearer token is malformed");
throw new OAuth2AuthenticationException(error);
}
return matcher.group("token");
}
private String resolveAccessTokenFromQueryString(HttpServletRequest request) {
if (!this.allowUriQueryParameter || !HttpMethod.GET.name().equals(request.getMethod())) {
return null;
}
return resolveToken(request.getParameterValues(ACCESS_TOKEN_PARAMETER_NAME));
}
private String resolveAccessTokenFromBody(HttpServletRequest request) {
if (!this.allowFormEncodedBodyParameter
|| !MediaType.APPLICATION_FORM_URLENCODED_VALUE.equals(request.getContentType())
|| HttpMethod.GET.name().equals(request.getMethod())) {
return null;
}
String queryString = request.getQueryString();
if (queryString != null && queryString.contains(ACCESS_TOKEN_PARAMETER_NAME)) {
return null;
}
return resolveToken(request.getParameterValues(ACCESS_TOKEN_PARAMETER_NAME));
}
/**
@@ -109,50 +160,4 @@ public final class DefaultBearerTokenResolver implements BearerTokenResolver {
this.bearerTokenHeaderName = bearerTokenHeaderName;
}
private String resolveFromAuthorizationHeader(HttpServletRequest request) {
String authorization = request.getHeader(this.bearerTokenHeaderName);
if (!StringUtils.startsWithIgnoreCase(authorization, "bearer")) {
return null;
}
Matcher matcher = authorizationPattern.matcher(authorization);
if (!matcher.matches()) {
BearerTokenError error = BearerTokenErrors.invalidToken("Bearer token is malformed");
throw new OAuth2AuthenticationException(error);
}
return matcher.group("token");
}
private static String resolveFromRequestParameters(HttpServletRequest request) {
String[] values = request.getParameterValues(ACCESS_TOKEN_PARAMETER_NAME);
if (values == null || values.length == 0) {
return null;
}
if (values.length == 1) {
return values[0];
}
BearerTokenError error = BearerTokenErrors.invalidRequest("Found multiple bearer tokens in the request");
throw new OAuth2AuthenticationException(error);
}
private boolean isParameterTokenSupportedForRequest(final HttpServletRequest request) {
return isFormEncodedRequest(request) || isGetRequest(request);
}
private static boolean isGetRequest(HttpServletRequest request) {
return HttpMethod.GET.name().equals(request.getMethod());
}
private static boolean isFormEncodedRequest(HttpServletRequest request) {
return MediaType.APPLICATION_FORM_URLENCODED_VALUE.equals(request.getContentType());
}
private static boolean hasAccessTokenInQueryString(HttpServletRequest request) {
return (request.getQueryString() != null) && request.getQueryString().contains(ACCESS_TOKEN_PARAMETER_NAME);
}
private boolean isParameterTokenEnabledForRequest(HttpServletRequest request) {
return ((this.allowFormEncodedBodyParameter && isFormEncodedRequest(request) && !isGetRequest(request)
&& !hasAccessTokenInQueryString(request)) || (this.allowUriQueryParameter && isGetRequest(request)));
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -77,18 +77,18 @@ public class ServerBearerTokenAuthenticationConverter implements ServerAuthentic
}
return authorizationHeaderToken;
}
if (parameterToken != null && isParameterTokenSupportedForRequest(request)) {
if (!StringUtils.hasText(parameterToken)) {
BearerTokenError error = BearerTokenErrors
.invalidRequest("The requested token parameter is an empty string");
throw new OAuth2AuthenticationException(error);
}
return parameterToken;
if (parameterToken != null && !StringUtils.hasText(parameterToken)) {
BearerTokenError error = BearerTokenErrors
.invalidRequest("The requested token parameter is an empty string");
throw new OAuth2AuthenticationException(error);
}
return null;
return parameterToken;
}
private static String resolveAccessTokenFromRequest(ServerHttpRequest request) {
private String resolveAccessTokenFromRequest(ServerHttpRequest request) {
if (!isParameterTokenSupportedForRequest(request)) {
return null;
}
List<String> parameterTokens = request.getQueryParams().get("access_token");
if (CollectionUtils.isEmpty(parameterTokens)) {
return null;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -110,6 +110,7 @@ public class DefaultBearerTokenResolverTests {
@Test
public void resolveWhenValidHeaderIsPresentTogetherWithFormParameterThenAuthenticationExceptionIsThrown() {
this.resolver.setAllowFormEncodedBodyParameter(true);
MockHttpServletRequest request = new MockHttpServletRequest();
request.addHeader("Authorization", "Bearer " + TEST_TOKEN);
request.setMethod("POST");
@@ -121,6 +122,7 @@ public class DefaultBearerTokenResolverTests {
@Test
public void resolveWhenValidHeaderIsPresentTogetherWithQueryParameterThenAuthenticationExceptionIsThrown() {
this.resolver.setAllowUriQueryParameter(true);
MockHttpServletRequest request = new MockHttpServletRequest();
request.addHeader("Authorization", "Bearer " + TEST_TOKEN);
request.setMethod("GET");
@@ -133,6 +135,7 @@ public class DefaultBearerTokenResolverTests {
// gh-10326
@Test
public void resolveWhenRequestContainsTwoAccessTokenQueryParametersThenAuthenticationExceptionIsThrown() {
this.resolver.setAllowUriQueryParameter(true);
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("GET");
request.addParameter("access_token", "token1", "token2");
@@ -143,6 +146,7 @@ public class DefaultBearerTokenResolverTests {
// gh-10326
@Test
public void resolveWhenRequestContainsTwoAccessTokenFormParametersThenAuthenticationExceptionIsThrown() {
this.resolver.setAllowFormEncodedBodyParameter(true);
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.setContentType("application/x-www-form-urlencoded");
@@ -233,6 +237,19 @@ public class DefaultBearerTokenResolverTests {
assertThat(this.resolver.resolve(request)).isNull();
}
@Test
public void resolveWhenPostAndQueryParameterIsSupportedAndFormParameterIsPresentThenTokenIsNotResolved() {
this.resolver.setAllowUriQueryParameter(true);
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.setContentType("application/x-www-form-urlencoded");
request.setQueryString("access_token=" + TEST_TOKEN);
request.addParameter("access_token", TEST_TOKEN);
assertThat(this.resolver.resolve(request)).isNull();
}
@Test
public void resolveWhenFormParameterIsPresentAndNotSupportedThenTokenIsNotResolved() {
MockHttpServletRequest request = new MockHttpServletRequest();
@@ -261,6 +278,25 @@ public class DefaultBearerTokenResolverTests {
assertThat(this.resolver.resolve(request)).isNull();
}
// gh-16038
@Test
public void resolveWhenRequestContainsTwoAccessTokenFormParametersAndSupportIsDisabledThenTokenIsNotResolved() {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.setContentType("application/x-www-form-urlencoded");
request.addParameter("access_token", "token1", "token2");
assertThat(this.resolver.resolve(request)).isNull();
}
// gh-16038
@Test
public void resolveWhenRequestContainsTwoAccessTokenQueryParametersAndSupportIsDisabledThenTokenIsNotResolved() {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("GET");
request.addParameter("access_token", "token1", "token2");
assertThat(this.resolver.resolve(request)).isNull();
}
@Test
public void resolveWhenQueryParameterIsPresentAndEmptyStringThenTokenIsNotResolved() {
this.resolver.setAllowUriQueryParameter(true);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -157,6 +157,7 @@ public class ServerBearerTokenAuthenticationConverterTests {
@Test
public void resolveWhenValidHeaderIsPresentTogetherWithQueryParameterThenAuthenticationExceptionIsThrown() {
// @formatter:off
this.converter.setAllowUriQueryParameter(true);
MockServerHttpRequest.BaseBuilder<?> request = MockServerHttpRequest.get("/")
.queryParam("access_token", TEST_TOKEN)
.header(HttpHeaders.AUTHORIZATION, "Bearer " + TEST_TOKEN);
@@ -205,6 +206,7 @@ public class ServerBearerTokenAuthenticationConverterTests {
@Test
void resolveWhenQueryParameterHasMultipleAccessTokensThenOAuth2AuthenticationException() {
this.converter.setAllowUriQueryParameter(true);
MockServerHttpRequest.BaseBuilder<?> request = MockServerHttpRequest.get("/")
.queryParam("access_token", TEST_TOKEN, TEST_TOKEN);
assertThatExceptionOfType(OAuth2AuthenticationException.class).isThrownBy(() -> convertToToken(request))
@@ -217,6 +219,14 @@ public class ServerBearerTokenAuthenticationConverterTests {
}
// gh-16038
@Test
void resolveWhenRequestContainsTwoAccessTokenQueryParametersAndSupportIsDisabledThenTokenIsNotResolved() {
MockServerHttpRequest.BaseBuilder<?> request = MockServerHttpRequest.get("/")
.queryParam("access_token", TEST_TOKEN, TEST_TOKEN);
assertThat(convertToToken(request)).isNull();
}
private BearerTokenAuthenticationToken convertToToken(MockServerHttpRequest.BaseBuilder<?> request) {
return convertToToken(request.build());
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
private void decryptResponse(Response response) {
Collection<Assertion> decrypteds = new ArrayList<>();
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
int count = 0;
int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
try {
Assertion decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
count++;
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
}
}
response.getEncryptedAssertions().removeAll(encrypteds);
response.getAssertions().addAll(decrypteds);
// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
if (decrypted != null) {
d.setNameID(decrypted);
d.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
private void decryptAttributes(AttributeStatement statement) {
Collection<Attribute> decrypteds = new ArrayList<>();
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
try {
Attribute decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
}
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
throw new Saml2Exception(ex);
}
}
statement.getEncryptedAttributes().removeAll(encrypteds);
statement.getAttributes().addAll(decrypteds);
}
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
if (decrypted != null) {
subject.setNameID(decrypted);
subject.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
if (decrypted != null) {
sc.setNameID(decrypted);
sc.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
if (decrypted != null) {
request.setNameID(decrypted);
request.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
private void decryptResponse(Response response) {
Collection<Assertion> decrypteds = new ArrayList<>();
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
int count = 0;
int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
try {
Assertion decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
count++;
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
}
}
response.getEncryptedAssertions().removeAll(encrypteds);
response.getAssertions().addAll(decrypteds);
// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
if (decrypted != null) {
d.setNameID(decrypted);
d.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
private void decryptAttributes(AttributeStatement statement) {
Collection<Attribute> decrypteds = new ArrayList<>();
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
try {
Attribute decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
}
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
throw new Saml2Exception(ex);
}
}
statement.getEncryptedAttributes().removeAll(encrypteds);
statement.getAttributes().addAll(decrypteds);
}
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
if (decrypted != null) {
subject.setNameID(decrypted);
subject.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
if (decrypted != null) {
sc.setNameID(decrypted);
sc.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
if (decrypted != null) {
request.setNameID(decrypted);
request.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
private void decryptResponse(Response response) {
Collection<Assertion> decrypteds = new ArrayList<>();
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
int count = 0;
int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
try {
Assertion decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
count++;
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
}
}
response.getEncryptedAssertions().removeAll(encrypteds);
response.getAssertions().addAll(decrypteds);
// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
if (decrypted != null) {
d.setNameID(decrypted);
d.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
private void decryptAttributes(AttributeStatement statement) {
Collection<Attribute> decrypteds = new ArrayList<>();
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
try {
Attribute decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
}
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
throw new Saml2Exception(ex);
}
}
statement.getEncryptedAttributes().removeAll(encrypteds);
statement.getAttributes().addAll(decrypteds);
}
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
if (decrypted != null) {
subject.setNameID(decrypted);
subject.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
if (decrypted != null) {
sc.setNameID(decrypted);
sc.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
if (decrypted != null) {
request.setNameID(decrypted);
request.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
private void decryptResponse(Response response) {
Collection<Assertion> decrypteds = new ArrayList<>();
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
int count = 0;
int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
try {
Assertion decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
count++;
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
}
}
response.getEncryptedAssertions().removeAll(encrypteds);
response.getAssertions().addAll(decrypteds);
// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
if (decrypted != null) {
d.setNameID(decrypted);
d.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
private void decryptAttributes(AttributeStatement statement) {
Collection<Attribute> decrypteds = new ArrayList<>();
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
try {
Attribute decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
}
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
throw new Saml2Exception(ex);
}
}
statement.getEncryptedAttributes().removeAll(encrypteds);
statement.getAttributes().addAll(decrypteds);
}
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
if (decrypted != null) {
subject.setNameID(decrypted);
subject.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
if (decrypted != null) {
sc.setNameID(decrypted);
sc.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
if (decrypted != null) {
request.setNameID(decrypted);
request.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
private void decryptResponse(Response response) {
Collection<Assertion> decrypteds = new ArrayList<>();
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
int count = 0;
int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
try {
Assertion decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
count++;
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
}
}
response.getEncryptedAssertions().removeAll(encrypteds);
response.getAssertions().addAll(decrypteds);
// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
if (decrypted != null) {
d.setNameID(decrypted);
d.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
private void decryptAttributes(AttributeStatement statement) {
Collection<Attribute> decrypteds = new ArrayList<>();
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
try {
Attribute decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
}
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
throw new Saml2Exception(ex);
}
}
statement.getEncryptedAttributes().removeAll(encrypteds);
statement.getAttributes().addAll(decrypteds);
}
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
if (decrypted != null) {
subject.setNameID(decrypted);
subject.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
if (decrypted != null) {
sc.setNameID(decrypted);
sc.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
if (decrypted != null) {
request.setNameID(decrypted);
request.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
private void decryptResponse(Response response) {
Collection<Assertion> decrypteds = new ArrayList<>();
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
int count = 0;
int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
try {
Assertion decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
count++;
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
}
}
response.getEncryptedAssertions().removeAll(encrypteds);
response.getAssertions().addAll(decrypteds);
// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
if (decrypted != null) {
d.setNameID(decrypted);
d.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
private void decryptAttributes(AttributeStatement statement) {
Collection<Attribute> decrypteds = new ArrayList<>();
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
try {
Attribute decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
}
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
throw new Saml2Exception(ex);
}
}
statement.getEncryptedAttributes().removeAll(encrypteds);
statement.getAttributes().addAll(decrypteds);
}
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
if (decrypted != null) {
subject.setNameID(decrypted);
subject.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
if (decrypted != null) {
sc.setNameID(decrypted);
sc.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
if (decrypted != null) {
request.setNameID(decrypted);
request.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
private void decryptResponse(Response response) {
Collection<Assertion> decrypteds = new ArrayList<>();
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
int count = 0;
int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
try {
Assertion decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
count++;
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
}
}
response.getEncryptedAssertions().removeAll(encrypteds);
response.getAssertions().addAll(decrypteds);
// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
if (decrypted != null) {
d.setNameID(decrypted);
d.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
private void decryptAttributes(AttributeStatement statement) {
Collection<Attribute> decrypteds = new ArrayList<>();
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
try {
Attribute decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
}
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
throw new Saml2Exception(ex);
}
}
statement.getEncryptedAttributes().removeAll(encrypteds);
statement.getAttributes().addAll(decrypteds);
}
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
if (decrypted != null) {
subject.setNameID(decrypted);
subject.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
if (decrypted != null) {
sc.setNameID(decrypted);
sc.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
if (decrypted != null) {
request.setNameID(decrypted);
request.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
private void decryptResponse(Response response) {
Collection<Assertion> decrypteds = new ArrayList<>();
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
int count = 0;
int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
try {
Assertion decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
count++;
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
}
}
response.getEncryptedAssertions().removeAll(encrypteds);
response.getAssertions().addAll(decrypteds);
// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
if (decrypted != null) {
d.setNameID(decrypted);
d.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
private void decryptAttributes(AttributeStatement statement) {
Collection<Attribute> decrypteds = new ArrayList<>();
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
try {
Attribute decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
}
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
throw new Saml2Exception(ex);
}
}
statement.getEncryptedAttributes().removeAll(encrypteds);
statement.getAttributes().addAll(decrypteds);
}
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
if (decrypted != null) {
subject.setNameID(decrypted);
subject.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
if (decrypted != null) {
sc.setNameID(decrypted);
sc.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
if (decrypted != null) {
request.setNameID(decrypted);
request.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -386,6 +386,24 @@ public class OpenSaml4AuthenticationProviderTests {
this.provider.authenticate(token);
}
// gh-16367
@Test
public void authenticateWhenEncryptedAssertionWithSignatureThenEncryptedAssertionStillAvailable() {
Response response = response();
Assertion assertion = TestOpenSamlObjects.signed(assertion(),
TestSaml2X509Credentials.assertingPartySigningCredential(), RELYING_PARTY_ENTITY_ID);
EncryptedAssertion encryptedAssertion = TestOpenSamlObjects.encrypted(assertion,
TestSaml2X509Credentials.assertingPartyEncryptingCredential());
response.getEncryptedAssertions().add(encryptedAssertion);
Saml2AuthenticationToken token = token(signed(response), decrypting(verifying(registration())));
OpenSaml4AuthenticationProvider provider = new OpenSaml4AuthenticationProvider();
provider.setResponseValidator((t) -> {
assertThat(t.getResponse().getEncryptedAssertions()).isNotEmpty();
return Saml2ResponseValidatorResult.success();
});
provider.authenticate(token);
}
@Test
public void authenticateWhenEncryptedAssertionWithResponseSignatureThenItSucceeds() {
Response response = response();
@@ -410,6 +428,26 @@ public class OpenSaml4AuthenticationProviderTests {
this.provider.authenticate(token);
}
// gh-16367
@Test
public void authenticateWhenEncryptedNameIdWithSignatureThenEncryptedNameIdStillAvailable() {
Response response = response();
Assertion assertion = assertion();
NameID nameId = assertion.getSubject().getNameID();
EncryptedID encryptedID = TestOpenSamlObjects.encrypted(nameId,
TestSaml2X509Credentials.assertingPartyEncryptingCredential());
assertion.getSubject().setNameID(null);
assertion.getSubject().setEncryptedID(encryptedID);
response.getAssertions().add(signed(assertion));
Saml2AuthenticationToken token = token(response, decrypting(verifying(registration())));
OpenSaml4AuthenticationProvider provider = new OpenSaml4AuthenticationProvider();
provider.setAssertionValidator((t) -> {
assertThat(t.getAssertion().getSubject().getEncryptedID()).isNotNull();
return Saml2ResponseValidatorResult.success();
});
provider.authenticate(token);
}
@Test
public void authenticateWhenEncryptedAttributeThenDecrypts() {
Response response = response();
@@ -426,6 +464,26 @@ public class OpenSaml4AuthenticationProviderTests {
assertThat(principal.getAttribute("name")).containsExactly("value");
}
// gh-16367
@Test
public void authenticateWhenEncryptedAttributeThenEncryptedAttributesStillAvailable() {
Response response = response();
Assertion assertion = assertion();
EncryptedAttribute attribute = TestOpenSamlObjects.encrypted("name", "value",
TestSaml2X509Credentials.assertingPartyEncryptingCredential());
AttributeStatement statement = build(AttributeStatement.DEFAULT_ELEMENT_NAME);
statement.getEncryptedAttributes().add(attribute);
assertion.getAttributeStatements().add(statement);
response.getAssertions().add(assertion);
Saml2AuthenticationToken token = token(signed(response), decrypting(verifying(registration())));
OpenSaml4AuthenticationProvider provider = new OpenSaml4AuthenticationProvider();
provider.setAssertionValidator((t) -> {
assertThat(t.getAssertion().getAttributeStatements().get(0).getEncryptedAttributes()).isNotEmpty();
return Saml2ResponseValidatorResult.success();
});
provider.authenticate(token);
}
@Test
public void authenticateWhenDecryptionKeysAreMissingThenThrowAuthenticationException() {
Response response = response();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
private void decryptResponse(Response response) {
Collection<Assertion> decrypteds = new ArrayList<>();
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
int count = 0;
int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
try {
Assertion decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
count++;
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
}
}
response.getEncryptedAssertions().removeAll(encrypteds);
response.getAssertions().addAll(decrypteds);
// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
if (decrypted != null) {
d.setNameID(decrypted);
d.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
private void decryptAttributes(AttributeStatement statement) {
Collection<Attribute> decrypteds = new ArrayList<>();
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
try {
Attribute decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
}
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
throw new Saml2Exception(ex);
}
}
statement.getEncryptedAttributes().removeAll(encrypteds);
statement.getAttributes().addAll(decrypteds);
}
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
if (decrypted != null) {
subject.setNameID(decrypted);
subject.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
if (decrypted != null) {
sc.setNameID(decrypted);
sc.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
if (decrypted != null) {
request.setNameID(decrypted);
request.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
private void decryptResponse(Response response) {
Collection<Assertion> decrypteds = new ArrayList<>();
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
int count = 0;
int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
try {
Assertion decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
count++;
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
}
}
response.getEncryptedAssertions().removeAll(encrypteds);
response.getAssertions().addAll(decrypteds);
// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
if (decrypted != null) {
d.setNameID(decrypted);
d.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
private void decryptAttributes(AttributeStatement statement) {
Collection<Attribute> decrypteds = new ArrayList<>();
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
try {
Attribute decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
}
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
throw new Saml2Exception(ex);
}
}
statement.getEncryptedAttributes().removeAll(encrypteds);
statement.getAttributes().addAll(decrypteds);
}
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
if (decrypted != null) {
subject.setNameID(decrypted);
subject.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
if (decrypted != null) {
sc.setNameID(decrypted);
sc.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
if (decrypted != null) {
request.setNameID(decrypted);
request.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
private void decryptResponse(Response response) {
Collection<Assertion> decrypteds = new ArrayList<>();
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
int count = 0;
int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
try {
Assertion decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
count++;
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
}
}
response.getEncryptedAssertions().removeAll(encrypteds);
response.getAssertions().addAll(decrypteds);
// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
if (decrypted != null) {
d.setNameID(decrypted);
d.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
private void decryptAttributes(AttributeStatement statement) {
Collection<Attribute> decrypteds = new ArrayList<>();
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
try {
Attribute decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
}
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
throw new Saml2Exception(ex);
}
}
statement.getEncryptedAttributes().removeAll(encrypteds);
statement.getAttributes().addAll(decrypteds);
}
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
if (decrypted != null) {
subject.setNameID(decrypted);
subject.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
if (decrypted != null) {
sc.setNameID(decrypted);
sc.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
if (decrypted != null) {
request.setNameID(decrypted);
request.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
private void decryptResponse(Response response) {
Collection<Assertion> decrypteds = new ArrayList<>();
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
int count = 0;
int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
try {
Assertion decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
count++;
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
}
}
response.getEncryptedAssertions().removeAll(encrypteds);
response.getAssertions().addAll(decrypteds);
// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
if (decrypted != null) {
d.setNameID(decrypted);
d.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
private void decryptAttributes(AttributeStatement statement) {
Collection<Attribute> decrypteds = new ArrayList<>();
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
try {
Attribute decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
}
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
throw new Saml2Exception(ex);
}
}
statement.getEncryptedAttributes().removeAll(encrypteds);
statement.getAttributes().addAll(decrypteds);
}
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
if (decrypted != null) {
subject.setNameID(decrypted);
subject.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
if (decrypted != null) {
sc.setNameID(decrypted);
sc.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
if (decrypted != null) {
request.setNameID(decrypted);
request.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
private void decryptResponse(Response response) {
Collection<Assertion> decrypteds = new ArrayList<>();
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
int count = 0;
int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
try {
Assertion decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
count++;
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
}
}
response.getEncryptedAssertions().removeAll(encrypteds);
response.getAssertions().addAll(decrypteds);
// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
if (decrypted != null) {
d.setNameID(decrypted);
d.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
private void decryptAttributes(AttributeStatement statement) {
Collection<Attribute> decrypteds = new ArrayList<>();
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
try {
Attribute decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
}
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
throw new Saml2Exception(ex);
}
}
statement.getEncryptedAttributes().removeAll(encrypteds);
statement.getAttributes().addAll(decrypteds);
}
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
if (decrypted != null) {
subject.setNameID(decrypted);
subject.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
if (decrypted != null) {
sc.setNameID(decrypted);
sc.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
if (decrypted != null) {
request.setNameID(decrypted);
request.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
private void decryptResponse(Response response) {
Collection<Assertion> decrypteds = new ArrayList<>();
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
int count = 0;
int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
try {
Assertion decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
count++;
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
}
}
response.getEncryptedAssertions().removeAll(encrypteds);
response.getAssertions().addAll(decrypteds);
// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
if (decrypted != null) {
d.setNameID(decrypted);
d.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
private void decryptAttributes(AttributeStatement statement) {
Collection<Attribute> decrypteds = new ArrayList<>();
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
try {
Attribute decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
}
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
throw new Saml2Exception(ex);
}
}
statement.getEncryptedAttributes().removeAll(encrypteds);
statement.getAttributes().addAll(decrypteds);
}
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
if (decrypted != null) {
subject.setNameID(decrypted);
subject.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
if (decrypted != null) {
sc.setNameID(decrypted);
sc.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
if (decrypted != null) {
request.setNameID(decrypted);
request.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
private void decryptResponse(Response response) {
Collection<Assertion> decrypteds = new ArrayList<>();
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
int count = 0;
int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
try {
Assertion decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
count++;
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
}
}
response.getEncryptedAssertions().removeAll(encrypteds);
response.getAssertions().addAll(decrypteds);
// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
if (decrypted != null) {
d.setNameID(decrypted);
d.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
private void decryptAttributes(AttributeStatement statement) {
Collection<Attribute> decrypteds = new ArrayList<>();
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
try {
Attribute decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
}
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
throw new Saml2Exception(ex);
}
}
statement.getEncryptedAttributes().removeAll(encrypteds);
statement.getAttributes().addAll(decrypteds);
}
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
if (decrypted != null) {
subject.setNameID(decrypted);
subject.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
if (decrypted != null) {
sc.setNameID(decrypted);
sc.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
if (decrypted != null) {
request.setNameID(decrypted);
request.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
private void decryptResponse(Response response) {
Collection<Assertion> decrypteds = new ArrayList<>();
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
int count = 0;
int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
try {
Assertion decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
count++;
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
}
}
response.getEncryptedAssertions().removeAll(encrypteds);
response.getAssertions().addAll(decrypteds);
// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
if (decrypted != null) {
d.setNameID(decrypted);
d.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
private void decryptAttributes(AttributeStatement statement) {
Collection<Attribute> decrypteds = new ArrayList<>();
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
try {
Attribute decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
}
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
throw new Saml2Exception(ex);
}
}
statement.getEncryptedAttributes().removeAll(encrypteds);
statement.getAttributes().addAll(decrypteds);
}
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
if (decrypted != null) {
subject.setNameID(decrypted);
subject.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
if (decrypted != null) {
sc.setNameID(decrypted);
sc.setEncryptedID(null);
}
}
catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
if (decrypted != null) {
request.setNameID(decrypted);
request.setEncryptedID(null);
}
}
catch (DecryptionException ex) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -386,6 +386,24 @@ public class OpenSaml5AuthenticationProviderTests {
this.provider.authenticate(token);
}
// gh-16367
@Test
public void authenticateWhenEncryptedAssertionWithSignatureThenEncryptedAssertionStillAvailable() {
Response response = response();
Assertion assertion = TestOpenSamlObjects.signed(assertion(),
TestSaml2X509Credentials.assertingPartySigningCredential(), RELYING_PARTY_ENTITY_ID);
EncryptedAssertion encryptedAssertion = TestOpenSamlObjects.encrypted(assertion,
TestSaml2X509Credentials.assertingPartyEncryptingCredential());
response.getEncryptedAssertions().add(encryptedAssertion);
Saml2AuthenticationToken token = token(signed(response), decrypting(verifying(registration())));
OpenSaml5AuthenticationProvider provider = new OpenSaml5AuthenticationProvider();
provider.setResponseValidator((t) -> {
assertThat(t.getResponse().getEncryptedAssertions()).isNotEmpty();
return Saml2ResponseValidatorResult.success();
});
provider.authenticate(token);
}
@Test
public void authenticateWhenEncryptedAssertionWithResponseSignatureThenItSucceeds() {
Response response = response();
@@ -410,6 +428,26 @@ public class OpenSaml5AuthenticationProviderTests {
this.provider.authenticate(token);
}
// gh-16367
@Test
public void authenticateWhenEncryptedNameIdWithSignatureThenEncryptedNameIdStillAvailable() {
Response response = response();
Assertion assertion = assertion();
NameID nameId = assertion.getSubject().getNameID();
EncryptedID encryptedID = TestOpenSamlObjects.encrypted(nameId,
TestSaml2X509Credentials.assertingPartyEncryptingCredential());
assertion.getSubject().setNameID(null);
assertion.getSubject().setEncryptedID(encryptedID);
response.getAssertions().add(signed(assertion));
Saml2AuthenticationToken token = token(response, decrypting(verifying(registration())));
OpenSaml5AuthenticationProvider provider = new OpenSaml5AuthenticationProvider();
provider.setAssertionValidator((t) -> {
assertThat(t.getAssertion().getSubject().getEncryptedID()).isNotNull();
return Saml2ResponseValidatorResult.success();
});
provider.authenticate(token);
}
@Test
public void authenticateWhenEncryptedAttributeThenDecrypts() {
Response response = response();
@@ -426,6 +464,26 @@ public class OpenSaml5AuthenticationProviderTests {
assertThat(principal.getAttribute("name")).containsExactly("value");
}
// gh-16367
@Test
public void authenticateWhenEncryptedAttributeThenEncryptedAttributesStillAvailable() {
Response response = response();
Assertion assertion = assertion();
EncryptedAttribute attribute = TestOpenSamlObjects.encrypted("name", "value",
TestSaml2X509Credentials.assertingPartyEncryptingCredential());
AttributeStatement statement = build(AttributeStatement.DEFAULT_ELEMENT_NAME);
statement.getEncryptedAttributes().add(attribute);
assertion.getAttributeStatements().add(statement);
response.getAssertions().add(assertion);
Saml2AuthenticationToken token = token(signed(response), decrypting(verifying(registration())));
OpenSaml5AuthenticationProvider provider = new OpenSaml5AuthenticationProvider();
provider.setAssertionValidator((t) -> {
assertThat(t.getAssertion().getAttributeStatements().get(0).getEncryptedAttributes()).isNotEmpty();
return Saml2ResponseValidatorResult.success();
});
provider.authenticate(token);
}
@Test
public void authenticateWhenDecryptionKeysAreMissingThenThrowAuthenticationException() {
Response response = response();
@@ -29,6 +29,9 @@ public interface WebInvocationPrivilegeEvaluator {
/**
* Determines whether the user represented by the supplied <tt>Authentication</tt>
* object is allowed to invoke the supplied URI.
* <p>
* Note this will only match authorization rules that don't require a certain
* {@code HttpMethod}.
* @param uri the URI excluding the context path (a default context path setting will
* be used)
*/
@@ -36,13 +39,18 @@ public interface WebInvocationPrivilegeEvaluator {
/**
* Determines whether the user represented by the supplied <tt>Authentication</tt>
* object is allowed to invoke the supplied URI, with the given .
* object is allowed to invoke the supplied URI, with the given parameters.
* <p>
* Note the default implementation of <tt>FilterInvocationSecurityMetadataSource</tt>
* Note:
* <ul>
* <li>The default implementation of <tt>FilterInvocationSecurityMetadataSource</tt>
* disregards the <code>contextPath</code> when evaluating which secure object
* metadata applies to a given request URI, so generally the <code>contextPath</code>
* is unimportant unless you are using a custom
* <code>FilterInvocationSecurityMetadataSource</code>.
* <code>FilterInvocationSecurityMetadataSource</code>.</li>
* <li>this will only match authorization rules that don't require a certain
* {@code HttpMethod}.</li>
* </ul>
* @param uri the URI excluding the context path
* @param contextPath the context path (may be null).
* @param method the HTTP method (or null, for any method)
@@ -452,7 +452,7 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
<div class="login-form">
<h2>Login with Passkeys</h2>
<button id="passkey-signin" type="submit" class="primary">Sign in with a passkey</button>
</form>
</div>
""";
private static final String LOGIN_PAGE_TEMPLATE = """
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2025 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.
@@ -84,7 +84,7 @@ public final class CookieServerCsrfTokenRepository implements ServerCsrfTokenRep
*/
public static CookieServerCsrfTokenRepository withHttpOnlyFalse() {
CookieServerCsrfTokenRepository result = new CookieServerCsrfTokenRepository();
result.setCookieCustomizer((cookie) -> cookie.httpOnly(false));
result.cookieHttpOnly = false;
return result;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -333,9 +333,7 @@ public class Webauthn4JRelyingPartyOperations implements WebAuthnRelyingPartyOpe
public PublicKeyCredentialRequestOptions createCredentialRequestOptions(
PublicKeyCredentialRequestOptionsRequest request) {
Authentication authentication = request.getAuthentication();
// FIXME: do not load credentialRecords if anonymous
PublicKeyCredentialUserEntity userEntity = findUserEntityOrCreateAndSave(authentication.getName());
List<CredentialRecord> credentialRecords = this.userCredentials.findByUserId(userEntity.getId());
List<CredentialRecord> credentialRecords = findCredentialRecords(authentication);
return PublicKeyCredentialRequestOptions.builder()
.allowCredentials(credentialDescriptors(credentialRecords))
.challenge(Bytes.random())
@@ -346,6 +344,17 @@ public class Webauthn4JRelyingPartyOperations implements WebAuthnRelyingPartyOpe
.build();
}
private List<CredentialRecord> findCredentialRecords(Authentication authentication) {
if (!this.trustResolver.isAuthenticated(authentication)) {
return Collections.emptyList();
}
PublicKeyCredentialUserEntity userEntity = this.userEntities.findByUsername(authentication.getName());
if (userEntity == null) {
return Collections.emptyList();
}
return this.userCredentials.findByUserId(userEntity.getId());
}
@Override
public PublicKeyCredentialUserEntity authenticate(RelyingPartyAuthenticationRequest request) {
PublicKeyCredentialRequestOptions requestOptions = request.getRequestOptions();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2025 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.
@@ -290,6 +290,21 @@ class CookieServerCsrfTokenRepositoryTests {
loadAndAssertExpectedValues();
}
// gh-16820
@Test
void withHttpOnlyFalseWhenCookieCustomizerThenStillDefaultsToFalse() {
CookieServerCsrfTokenRepository repository = CookieServerCsrfTokenRepository.withHttpOnlyFalse();
repository.setCookieCustomizer((customizer) -> customizer.maxAge(1000));
MockServerHttpRequest.BaseBuilder<?> request = MockServerHttpRequest.get("/dummy");
MockServerWebExchange exchange = MockServerWebExchange.from(request);
CsrfToken csrfToken = repository.generateToken(exchange).block();
repository.saveToken(exchange, csrfToken).block();
ResponseCookie cookie = exchange.getResponse().getCookies().getFirst("XSRF-TOKEN");
assertThat(cookie).isNotNull();
assertThat(cookie.getMaxAge().getSeconds()).isEqualTo(1000);
assertThat(cookie.isHttpOnly()).isEqualTo(Boolean.FALSE);
}
private void setExpectedHeaderName(String expectedHeaderName) {
this.csrfTokenRepository.setHeaderName(expectedHeaderName);
this.expectedHeaderName = expectedHeaderName;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -42,6 +42,8 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.PasswordEncodedUser;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.webauthn.api.AuthenticatorAttestationResponse;
import org.springframework.security.web.webauthn.api.AuthenticatorAttestationResponse.AuthenticatorAttestationResponseBuilder;
import org.springframework.security.web.webauthn.api.AuthenticatorSelectionCriteria;
@@ -66,6 +68,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatRuntimeException;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.verifyNoInteractions;
@ExtendWith(MockitoExtension.class)
class Webauthn4jRelyingPartyOperationsTests {
@@ -536,6 +539,50 @@ class Webauthn4jRelyingPartyOperationsTests {
.isEqualTo(creationOptions.getAuthenticatorSelection().getUserVerification());
}
@Test
void createCredentialRequestOptionsWhenAnonymousAuthentication() {
AnonymousAuthenticationToken authentication = new AnonymousAuthenticationToken("key", "anonymousUser",
Set.of(() -> "ROLE_ANONYMOUS"));
PublicKeyCredentialRequestOptionsRequest createRequest = new ImmutablePublicKeyCredentialRequestOptionsRequest(
authentication);
PublicKeyCredentialRequestOptions credentialRequestOptions = this.rpOperations
.createCredentialRequestOptions(createRequest);
assertThat(credentialRequestOptions.getAllowCredentials()).isEmpty();
// verify anonymous user not saved
verifyNoInteractions(this.userEntities);
}
@Test
void createCredentialRequestOptionsWhenNullAuthentication() {
PublicKeyCredentialRequestOptionsRequest createRequest = new ImmutablePublicKeyCredentialRequestOptionsRequest(
null);
PublicKeyCredentialRequestOptions credentialRequestOptions = this.rpOperations
.createCredentialRequestOptions(createRequest);
assertThat(credentialRequestOptions.getAllowCredentials()).isEmpty();
// verify anonymous user not saved
verifyNoInteractions(this.userEntities);
}
@Test
void createCredentialRequestOptionsWhenAuthenticated() {
UserDetails user = PasswordEncodedUser.user();
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user, null,
user.getAuthorities());
PublicKeyCredentialUserEntity userEntity = TestPublicKeyCredentialUserEntity.userEntity().build();
CredentialRecord credentialRecord = TestCredentialRecord.userCredential().build();
given(this.userEntities.findByUsername(user.getUsername())).willReturn(userEntity);
given(this.userCredentials.findByUserId(userEntity.getId())).willReturn(Arrays.asList(credentialRecord));
PublicKeyCredentialRequestOptionsRequest createRequest = new ImmutablePublicKeyCredentialRequestOptionsRequest(
auth);
PublicKeyCredentialRequestOptions credentialRequestOptions = this.rpOperations
.createCredentialRequestOptions(createRequest);
assertThat(credentialRequestOptions.getAllowCredentials()).extracting(PublicKeyCredentialDescriptor::getId)
.containsExactly(credentialRecord.getCredentialId());
}
private static AuthenticatorAttestationResponse setFlag(byte... flags) throws Exception {
AuthenticatorAttestationResponseBuilder authAttResponseBldr = TestAuthenticatorAttestationResponse
.createAuthenticatorAttestationResponse();