1
0
mirror of synced 2026-08-05 17:57:15 +00:00

Compare commits

..

124 Commits

Author SHA1 Message Date
dependabot[bot] 824c029f2e Bump actions/checkout from 6.0.3 to 7.0.1
Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.3 to 7.0.1.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/df4cb1c069e1874edd31b4311f1884172cec0e10...3d3c42e5aac5ba805825da76410c181273ba90b1)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-24 00:33:24 +00:00
github-actions[bot] 8f69721f24 Next development version 2026-06-09 16:02:59 +00:00
github-actions[bot] 73b077790f Release 6.5.11 2026-06-09 15:25:02 +00:00
Joe Grandja fd5dae5e4d Sync branch '6.5.x' 2026-06-09 09:57:02 -04:00
dependabot[bot] 700a4533aa Bump ch.qos.logback:logback-classic from 1.5.32 to 1.5.34
Bumps [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback) from 1.5.32 to 1.5.34.
- [Release notes](https://github.com/qos-ch/logback/releases)
- [Commits](https://github.com/qos-ch/logback/compare/v_1.5.32...v_1.5.34)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-09 08:27:37 -04:00
Joe Grandja 3a394c633f Update micrometer-bom to 1.15.12
Closes gh-19302
2026-06-09 08:18:31 -04:00
Joe Grandja 79f9bec818 Update to reactor-bom 2024.0.18
Closes gh-19301
2026-06-09 08:18:30 -04:00
dependabot[bot] 5b019365b7 Bump org.hibernate.orm:hibernate-core from 6.6.51.Final to 6.6.53.Final
Bumps [org.hibernate.orm:hibernate-core](https://github.com/hibernate/hibernate-orm) from 6.6.51.Final to 6.6.53.Final.
- [Release notes](https://github.com/hibernate/hibernate-orm/releases)
- [Changelog](https://github.com/hibernate/hibernate-orm/blob/6.6.53/changelog.txt)
- [Commits](https://github.com/hibernate/hibernate-orm/compare/6.6.51...6.6.53)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-09 07:37:50 -04:00
dependabot[bot] f9b4afdfc5 Bump com.fasterxml.jackson:jackson-bom from 2.18.7 to 2.18.8
Bumps [com.fasterxml.jackson:jackson-bom](https://github.com/FasterXML/jackson-bom) from 2.18.7 to 2.18.8.
- [Commits](https://github.com/FasterXML/jackson-bom/compare/jackson-bom-2.18.7...jackson-bom-2.18.8)

---
updated-dependencies:
- dependency-name: com.fasterxml.jackson:jackson-bom
  dependency-version: 2.18.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-09 07:36:02 -04:00
dependabot[bot] f325ddbdaa Bump org.springframework:spring-framework-bom from 6.2.18 to 6.2.19
Bumps [org.springframework:spring-framework-bom](https://github.com/spring-projects/spring-framework) from 6.2.18 to 6.2.19.
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.18...v6.2.19)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-09 07:32:45 -04:00
dependabot[bot] 4adfdf66b9 Bump org.apache.maven:maven-resolver-provider from 3.9.15 to 3.9.16
Bumps org.apache.maven:maven-resolver-provider from 3.9.15 to 3.9.16.

---
updated-dependencies:
- dependency-name: org.apache.maven:maven-resolver-provider
  dependency-version: 3.9.16
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-09 05:50:28 -04:00
dependabot[bot] e91b81a5aa Bump org-bouncycastle from 1.80 to 1.80.2
Bumps `org-bouncycastle` from 1.80 to 1.80.2.

Updates `org.bouncycastle:bcpkix-jdk18on` from 1.80 to 1.80.2
- [Changelog](https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html)
- [Commits](https://github.com/bcgit/bc-java/commits)

Updates `org.bouncycastle:bcprov-jdk18on` from 1.80 to 1.80.2
- [Changelog](https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html)
- [Commits](https://github.com/bcgit/bc-java/commits)

---
updated-dependencies:
- dependency-name: org.bouncycastle:bcpkix-jdk18on
  dependency-version: 1.80.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.bouncycastle:bcprov-jdk18on
  dependency-version: 1.80.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-09 05:49:36 -04:00
dependabot[bot] 0949d3b3ea Bump org.slf4j:slf4j-api from 2.0.17 to 2.0.18
Bumps org.slf4j:slf4j-api from 2.0.17 to 2.0.18.

---
updated-dependencies:
- dependency-name: org.slf4j:slf4j-api
  dependency-version: 2.0.18
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-09 05:33:00 -04:00
dependabot[bot] d44efc899d Bump org.hibernate.orm:hibernate-core from 6.6.50.Final to 6.6.51.Final
Bumps [org.hibernate.orm:hibernate-core](https://github.com/hibernate/hibernate-orm) from 6.6.50.Final to 6.6.51.Final.
- [Release notes](https://github.com/hibernate/hibernate-orm/releases)
- [Changelog](https://github.com/hibernate/hibernate-orm/blob/6.6.51/changelog.txt)
- [Commits](https://github.com/hibernate/hibernate-orm/compare/6.6.50...6.6.51)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-09 05:29:40 -04:00
dependabot[bot] c5870a746a Bump @springio/antora-extensions from 1.14.11 to 1.14.12 in /docs
Bumps [@springio/antora-extensions](https://github.com/spring-io/antora-extensions) from 1.14.11 to 1.14.12.
- [Changelog](https://github.com/spring-io/antora-extensions/blob/main/CHANGELOG.adoc)
- [Commits](https://github.com/spring-io/antora-extensions/compare/v1.14.11...v1.14.12)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-09 05:28:18 -04:00
dependabot[bot] 5eb41b8a06 Bump actions/checkout from 6.0.2 to 6.0.3
Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.2 to 6.0.3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/de0fac2e4500dabe0009e67214ff5f5447ce83dd...df4cb1c069e1874edd31b4311f1884172cec0e10)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-09 05:21:32 -04:00
Josh Cummings e3ad551ab3 Backport SubjectX500PrincipalExtractor
This commit backports SubjectX500PrincipalExtractor so as to provide
folks moving from 6.x to 7.x a migration path from
SubjectDnX509PrincipalExtractor.

Issue gh-16980

Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-06-01 14:30:33 -06:00
Josh Cummings cf06871200 Rework Logout Validation Logic
This commit simplifies the code, favoring the construction
of a list of error codes over composing a set of consumers.
This will simplify future analysis by making the code more
readable.

Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-05-29 14:45:44 -06:00
Josh Cummings e50c2a6a74 Rework Login Validation Logic
This commit simplifies the validation code, favoring the
construction of a list of error codes over using an
accumulating Saml2ResponseValidationResult. This will
simplify future analysis by making the code more readable.

Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-05-29 14:45:36 -06:00
Josh Cummings 356131b1ea Use FormPostRedirectStrategy
Closes gh-16673

Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-05-29 11:56:50 -06:00
Josh Cummings a14c9d66b1 Favor Relative URIs in CookieRequestCache
Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-05-28 06:54:59 -04:00
Josh Cummings 9d4d9065b4 Cap Deflate Size
Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-05-28 06:39:29 -04:00
Josh Cummings fe2e52f646 Add Micrometer Version Override
Closes gh-19187

Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-05-26 15:18:01 -06:00
Josh Cummings 0ea87ca3bf Upgrade Micrometer to 1.15.11
Closes gh-19224

Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-05-26 15:17:57 -06:00
Josh Cummings 85514a9b34 Update NodeJS to 24.15
This commit declares a NodeJS value whereas previously,
Antora would use the latest LTS version. When it updated to
Node 24.16, site production stopped, possibly due to
https://github.com/nodejs/node/commit/e95570c054.

Either way, it is helpful to have a pinned version in order
to stabilize builds, allowing us to update it in an orderly
fashion like other dependencies.

Issue gh-19206

Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-05-22 22:27:00 -06:00
dependabot[bot] 86e0f1341e Bump com.fasterxml.jackson:jackson-bom from 2.18.6 to 2.18.7
Bumps [com.fasterxml.jackson:jackson-bom](https://github.com/FasterXML/jackson-bom) from 2.18.6 to 2.18.7.
- [Commits](https://github.com/FasterXML/jackson-bom/compare/jackson-bom-2.18.6...jackson-bom-2.18.7)

---
updated-dependencies:
- dependency-name: com.fasterxml.jackson:jackson-bom
  dependency-version: 2.18.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-21 12:38:00 -06:00
dependabot[bot] cea6618265 Bump org.hibernate.orm:hibernate-core from 6.6.49.Final to 6.6.50.Final
Bumps [org.hibernate.orm:hibernate-core](https://github.com/hibernate/hibernate-orm) from 6.6.49.Final to 6.6.50.Final.
- [Release notes](https://github.com/hibernate/hibernate-orm/releases)
- [Changelog](https://github.com/hibernate/hibernate-orm/blob/6.6.50/changelog.txt)
- [Commits](https://github.com/hibernate/hibernate-orm/compare/6.6.49...6.6.50)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-21 12:36:57 -06:00
dependabot[bot] 5bf8f641f1 Bump spring-io/spring-gradle-build-action from 2.0.5 to 2.0.6
Bumps [spring-io/spring-gradle-build-action](https://github.com/spring-io/spring-gradle-build-action) from 2.0.5 to 2.0.6.
- [Release notes](https://github.com/spring-io/spring-gradle-build-action/releases)
- [Commits](https://github.com/spring-io/spring-gradle-build-action/compare/efc55f07f4dfa22f2afd97f9ea1be4212eeed737...c8668747d7c264864c8c7f7026d0d277d14a78dc)

---
updated-dependencies:
- dependency-name: spring-io/spring-gradle-build-action
  dependency-version: 2.0.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-21 12:36:52 -06:00
dependabot[bot] 8b9f556d8f Bump gradle-wrapper from 8.14.4 to 8.14.5
Bumps [gradle-wrapper](https://github.com/gradle/gradle) from 8.14.4 to 8.14.5.
- [Release notes](https://github.com/gradle/gradle/releases)
- [Commits](https://github.com/gradle/gradle/compare/v8.14.4...v8.14.5)

---
updated-dependencies:
- dependency-name: gradle-wrapper
  dependency-version: 8.14.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-21 12:36:46 -06:00
dependabot[bot] d9b8a8ec54 Bump spring-io/spring-release-actions from 0.0.4 to 0.0.5
Bumps [spring-io/spring-release-actions](https://github.com/spring-io/spring-release-actions) from 0.0.4 to 0.0.5.
- [Release notes](https://github.com/spring-io/spring-release-actions/releases)
- [Commits](https://github.com/spring-io/spring-release-actions/compare/2420148725bebe44bd59a575a9b1961ca4459b0b...a1f321783a0769dd2aea4fad6c2ae2f95a52b885)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-21 12:36:42 -06:00
dependabot[bot] 4e04c266be Bump antora from 3.2.0-alpha.11 to 3.2.0-alpha.12 in /docs
---
updated-dependencies:
- dependency-name: antora
  dependency-version: 3.2.0-alpha.12
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-21 12:36:37 -06:00
Josh Cummings 9b14465243 Align Assertions in Builder with Deprecated Constructor
The deprecated (introspectionUri, clientId, clientSecret) constructors
that the builders replaced explicitly asserted non-null clientId and
clientSecret. Bring the builder's build() in line with that contract by
asserting at the API boundary rather than relying on downstream classes
to enforce it.

Closes gh-19201

Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-05-21 10:36:10 -06:00
Josh Cummings b075f0df02 Decode percent-encoded values
Closes gh-19136

Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-04-29 08:57:16 -06:00
github-actions[bot] 6343002b32 Next development version 2026-04-20 18:55:26 +00:00
github-actions[bot] 0a9d4dc8fc Release 6.5.10 2026-04-20 17:54:21 +00:00
Josh Cummings 3d4e20597a Merge remote-tracking branch 'oss/6.5.x' into 6.5.x 2026-04-20 11:49:17 -06:00
dependabot[bot] 81bd52ae48 Bump org.hibernate.orm:hibernate-core from 6.6.48.Final to 6.6.49.Final
Bumps [org.hibernate.orm:hibernate-core](https://github.com/hibernate/hibernate-orm) from 6.6.48.Final to 6.6.49.Final.
- [Release notes](https://github.com/hibernate/hibernate-orm/releases)
- [Changelog](https://github.com/hibernate/hibernate-orm/blob/6.6.49/changelog.txt)
- [Commits](https://github.com/hibernate/hibernate-orm/compare/6.6.48...6.6.49)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-20 11:27:51 -06:00
dependabot[bot] 25b6af2738 Bump org.springframework:spring-framework-bom from 6.2.17 to 6.2.18
Bumps [org.springframework:spring-framework-bom](https://github.com/spring-projects/spring-framework) from 6.2.17 to 6.2.18.
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.17...v6.2.18)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-20 11:27:29 -06:00
dependabot[bot] 95987bffc1 Bump org.apache.maven:maven-resolver-provider from 3.9.14 to 3.9.15
Bumps org.apache.maven:maven-resolver-provider from 3.9.14 to 3.9.15.

---
updated-dependencies:
- dependency-name: org.apache.maven:maven-resolver-provider
  dependency-version: 3.9.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-20 11:27:07 -06:00
Josh Cummings 6e5f8f2a1d Merge remote-tracking branch 'origin/6.5.x' into 6.5.x 2026-04-20 09:51:26 -06:00
Seol-JY 4187af38b2 Verify token deletion in JdbcOneTimeTokenService 2026-04-18 12:30:30 -04:00
Josh Cummings 5b638a54a4 Use SHA Hashes
This commit updates workflows that were using tags to instead
use SHA hashes to reference actions and workflows

Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-04-17 14:15:50 -06:00
dependabot[bot] 51eef2b980 Bump io.projectreactor:reactor-bom from 2024.0.16 to 2024.0.17
Bumps [io.projectreactor:reactor-bom](https://github.com/reactor/reactor) from 2024.0.16 to 2024.0.17.
- [Release notes](https://github.com/reactor/reactor/releases)
- [Commits](https://github.com/reactor/reactor/compare/2024.0.16...2024.0.17)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-17 11:57:33 -06:00
dependabot[bot] 302cfb116e Bump @springio/antora-extensions from 1.14.10 to 1.14.11 in /docs
Bumps [@springio/antora-extensions](https://github.com/spring-io/antora-extensions) from 1.14.10 to 1.14.11.
- [Changelog](https://github.com/spring-io/antora-extensions/blob/main/CHANGELOG.adoc)
- [Commits](https://github.com/spring-io/antora-extensions/compare/v1.14.10...v1.14.11)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-17 11:08:19 -06:00
dependabot[bot] 695ea1717f Bump org.hibernate.orm:hibernate-core from 6.6.47.Final to 6.6.48.Final
Bumps [org.hibernate.orm:hibernate-core](https://github.com/hibernate/hibernate-orm) from 6.6.47.Final to 6.6.48.Final.
- [Release notes](https://github.com/hibernate/hibernate-orm/releases)
- [Changelog](https://github.com/hibernate/hibernate-orm/blob/6.6.48/changelog.txt)
- [Commits](https://github.com/hibernate/hibernate-orm/compare/6.6.47...6.6.48)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-17 11:07:58 -06:00
dependabot[bot] 1206c2b141 Bump actions/upload-artifact from 7.0.0 to 7.0.1
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 7.0.0 to 7.0.1.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/bbbca2ddaa5d8feaa63e36b76fdaad77386f024f...043fb46d1a93c77aae656e7c1c64a875d1fc6a0a)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-17 11:07:36 -06:00
dependabot[bot] 3539f06146 Bump spring-io/spring-release-actions from 0.0.3 to 0.0.4
Bumps [spring-io/spring-release-actions](https://github.com/spring-io/spring-release-actions) from 0.0.3 to 0.0.4.
- [Release notes](https://github.com/spring-io/spring-release-actions/releases)
- [Commits](https://github.com/spring-io/spring-release-actions/compare/0.0.3...0.0.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-17 11:07:08 -06:00
Josh Cummings a317a3d866 Add Support for Always Running Additional Authentication Checks
Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-04-15 21:07:39 -06:00
Josh Cummings 68b820ed09 Check Issuer with Issuer Provided
Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-04-15 18:23:22 -06:00
dependabot[bot] 44d32815b1 Bump @springio/antora-extensions from 1.14.9 to 1.14.10 in /docs
Bumps [@springio/antora-extensions](https://github.com/spring-io/antora-extensions) from 1.14.9 to 1.14.10.
- [Changelog](https://github.com/spring-io/antora-extensions/blob/main/CHANGELOG.adoc)
- [Commits](https://github.com/spring-io/antora-extensions/compare/v1.14.9...v1.14.10)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-07 10:29:49 -06:00
dependabot[bot] 87c3335e01 Bump org.hibernate.orm:hibernate-core from 6.6.45.Final to 6.6.47.Final
Bumps [org.hibernate.orm:hibernate-core](https://github.com/hibernate/hibernate-orm) from 6.6.45.Final to 6.6.47.Final.
- [Release notes](https://github.com/hibernate/hibernate-orm/releases)
- [Changelog](https://github.com/hibernate/hibernate-orm/blob/6.6.47/changelog.txt)
- [Commits](https://github.com/hibernate/hibernate-orm/compare/6.6.45...6.6.47)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-07 10:07:57 -06:00
Joe Grandja eefbb4da64 Fix DefaultOidcUser.equals()
Closes gh-18622
2026-04-02 10:41:32 -04:00
Rob Winch a2793f31b4 Merge Add XML Based shouldWriteHeadersEagerly tests
Add XML Based shouldWriteHeadersEagerly tests
2026-04-01 12:53:29 -04:00
Robert Winch 679a47a51d Add XML Based shouldWriteHeadersEagerly tests 2026-04-01 11:37:39 -05:00
Josh Cummings 08fca57d12 Add Missing Serialization Support
Closed gh-19012

Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-03-31 13:58:35 -06:00
Josh Cummings acabacb971 Update Test to find SuppressWarnings
Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-03-31 13:47:52 -06:00
johnycho 1a130fca3c Improve serialVersionUID check in tests
Signed-off-by: johnycho <shunnn215@gmail.com>
2026-03-31 13:47:50 -06:00
Rob Winch 5a4ada04ac Merge pull request #19004 from rwinch/CredentialRecordOwnerAuthorizationManager
Add CredentialRecordOwnerAuthorizationManager
2026-03-29 23:46:03 -04:00
Robert Winch a856baa6a8 Add CredentialRecordOwnerAuthorizationManager
Add CredentialRecordOwnerAuthorizationManager that verifies the
credential being deleted is owned by the currently authenticated user.
Also add an AuthorizationManager<Bytes> to WebAuthnRegistrationFilter
for the delete credential operation, defaulting to deny all, and wire it
up in WebAuthnConfigurer.

Per the WebAuthn specification [1], credential ids contain at least 16
bytes with at least 100 bits of entropy, making them practically
unguessable. The specification also advises that credential ids should
be kept private, as exposing them can leak personally identifying
information [2]. The CredentialRecordOwnerAuthorizationManager serves as
defense in depth: even if a credential id were somehow exposed, an
unauthorized user could not delete another user's credential.

[1] https://www.w3.org/TR/webauthn-3/#credential-id
[2] https://www.w3.org/TR/webauthn-3/#sctn-credential-id-privacy-leak
2026-03-29 21:54:27 -05:00
Josh Cummings ac63cf4fa5 Polish CustomAuthorizationManager Docs
Issue gh-13967

Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-03-27 16:45:25 -06:00
as1605 f6bb55effb Fix documentation for Custom Authorization Manager
Closes gh-13967

Signed-off-by: as1605 <1605.aditya.singh@gmail.com>
2026-03-27 16:45:25 -06:00
Tran Ngoc Nhan 85b756cb74 Update FilterChainProxy#getFilters(String) javadoc
Closes gh-18157

Signed-off-by: Tran Ngoc Nhan <ngocnhan.tran1996@gmail.com>
2026-03-27 16:09:50 -06:00
dependabot[bot] 7441ce7f16 Bump spring-io/spring-security-release-tools/.github/workflows/perform-release.yml
Bumps [spring-io/spring-security-release-tools/.github/workflows/perform-release.yml](https://github.com/spring-io/spring-security-release-tools) from 1.0.14 to 1.0.15.
- [Release notes](https://github.com/spring-io/spring-security-release-tools/releases)
- [Changelog](https://github.com/spring-io/spring-security-release-tools/blob/main/RELEASE.adoc)
- [Commits](https://github.com/spring-io/spring-security-release-tools/compare/729fed56d42122f88583aff1be35c0800b7d77e9...b92832ecbc7cbe969201e6beafbde0ee400cf095)

---
updated-dependencies:
- dependency-name: spring-io/spring-security-release-tools/.github/workflows/perform-release.yml
  dependency-version: 1.0.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-27 13:25:46 -06:00
dependabot[bot] 9dbcd8cf00 Bump spring-io/spring-security-release-tools/.github/workflows/update-scheduled-release-version.yml
Bumps [spring-io/spring-security-release-tools/.github/workflows/update-scheduled-release-version.yml](https://github.com/spring-io/spring-security-release-tools) from 1.0.14 to 1.0.15.
- [Release notes](https://github.com/spring-io/spring-security-release-tools/releases)
- [Changelog](https://github.com/spring-io/spring-security-release-tools/blob/main/RELEASE.adoc)
- [Commits](https://github.com/spring-io/spring-security-release-tools/compare/729fed56d42122f88583aff1be35c0800b7d77e9...b92832ecbc7cbe969201e6beafbde0ee400cf095)

---
updated-dependencies:
- dependency-name: spring-io/spring-security-release-tools/.github/workflows/update-scheduled-release-version.yml
  dependency-version: 1.0.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-27 13:25:35 -06:00
Josh Cummings 835d6c1fbd Add Issuer Validation to withIssuerLocation Snippets
Closes gh-19000

Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-03-27 13:22:24 -06:00
Josh Cummings 95b2cdf7f4 Clarify JavaDoc
Removed note about DelegatingJwtGrantedAuthoritiesConverter from
ExpressionJwtGrantedAuthoritiesConverter and further explained in
DelegatingJwtGrantedAuthoritiesConverter where it comes in handy.

Issue gh-18300

Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-03-27 11:48:56 -06:00
Rob Winch 3ecf84855e Merge pull request #18989 from rwinch/gh-18970-null-oncommitted
Merge Handle null value in OnCommittedResponseWrapper header methods
2026-03-26 17:29:33 -04:00
Robert Winch 0039bc0cf0 Handle null value in OnCommittedResponseWrapper header methods
Closes gh-18970
2026-03-26 14:50:44 -05:00
Josh Cummings 057e5181ea Adjust Formatting
Issue gh-18805

Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-03-25 15:19:29 -06:00
Tran Ngoc Nhan 178ca56aaf Fallback defaultTargetUrl if refererHeader is empty
Closes gh-18805

Signed-off-by: Tran Ngoc Nhan <ngocnhan.tran1996@gmail.com>
2026-03-25 15:19:29 -06:00
dependabot[bot] 61ccf14953 Bump org.hibernate.orm:hibernate-core from 6.6.44.Final to 6.6.45.Final
Bumps [org.hibernate.orm:hibernate-core](https://github.com/hibernate/hibernate-orm) from 6.6.44.Final to 6.6.45.Final.
- [Release notes](https://github.com/hibernate/hibernate-orm/releases)
- [Changelog](https://github.com/hibernate/hibernate-orm/blob/6.6.45/changelog.txt)
- [Commits](https://github.com/hibernate/hibernate-orm/compare/6.6.44...6.6.45)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-25 15:11:27 -06:00
Joe Grandja 6e683f2286 Fix ID Token auth_time validation
Closes gh-18839
2026-03-25 11:33:55 -04:00
Josh Cummings b6e24db68c Return Mono.empty on Empty POST
Closes gh-18973

Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-03-23 18:12:21 -06:00
Daniel Garnier-Moiroux aeb5fc1fb0 Fix HttpSessionRequestCache#getMatchingRequest query string parsing
- URL parsing changed in framework 6.2, and fails when path contains a % sign.
- The HttpSessionRequestCache only needs to inspect the query string, not the full URL.

Fixes gh-16656

Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
2026-03-23 17:52:17 -06:00
Tran Ngoc Nhan 62f33d3fcf Add equals and hashCode to HttpMethodRequestMatcher
Closes gh-18911

Signed-off-by: Tran Ngoc Nhan <ngocnhan.tran1996@gmail.com>
2026-03-20 21:22:20 -06:00
Rob Winch 9fed1ac8c3 New line per sentence
Signed-off-by: Rob Winch <362503+rwinch@users.noreply.github.com>
2026-03-20 15:28:21 -06:00
Josh Cummings 9dbe3bdcc0 Polish Session Management Persistence Docs
Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-03-20 15:28:21 -06:00
sankranti d547ae0181 Fix defaults description in Session Management doc
Corrected that starting from Spring Security 6
security context is not automatically saved by default.

Signed-off-by: sankranti <sankranty@gmail.com>
2026-03-20 15:28:21 -06:00
dependabot[bot] b8b1278e1f Bump @springio/antora-extensions from 1.14.7 to 1.14.9 in /docs
Bumps [@springio/antora-extensions](https://github.com/spring-io/antora-extensions) from 1.14.7 to 1.14.9.
- [Changelog](https://github.com/spring-io/antora-extensions/blob/main/CHANGELOG.adoc)
- [Commits](https://github.com/spring-io/antora-extensions/compare/v1.14.7...v1.14.9)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-20 15:22:06 -06:00
dependabot[bot] 381047e386 Bump spring-io/spring-security-release-tools from 1.0.14 to 1.0.15
Bumps [spring-io/spring-security-release-tools](https://github.com/spring-io/spring-security-release-tools) from 1.0.14 to 1.0.15.
- [Release notes](https://github.com/spring-io/spring-security-release-tools/releases)
- [Changelog](https://github.com/spring-io/spring-security-release-tools/blob/main/RELEASE.adoc)
- [Commits](https://github.com/spring-io/spring-security-release-tools/compare/729fed56d42122f88583aff1be35c0800b7d77e9...b92832ecbc7cbe969201e6beafbde0ee400cf095)

---
updated-dependencies:
- dependency-name: spring-io/spring-security-release-tools
  dependency-version: 1.0.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-20 15:21:53 -06:00
dependabot[bot] 376b40a735 Bump io.spring.gradle:spring-security-release-plugin
Bumps [io.spring.gradle:spring-security-release-plugin](https://github.com/spring-io/spring-security-release-tools) from 1.0.14 to 1.0.15.
- [Release notes](https://github.com/spring-io/spring-security-release-tools/releases)
- [Changelog](https://github.com/spring-io/spring-security-release-tools/blob/main/RELEASE.adoc)
- [Commits](https://github.com/spring-io/spring-security-release-tools/compare/v1.0.14...v1.0.15)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-20 14:58:20 -06:00
dependabot[bot] 89fa1cbdd2 Bump spring-io/spring-security-release-tools/.github/workflows/build.yml
Bumps [spring-io/spring-security-release-tools/.github/workflows/build.yml](https://github.com/spring-io/spring-security-release-tools) from 1.0.14 to 1.0.15.
- [Release notes](https://github.com/spring-io/spring-security-release-tools/releases)
- [Changelog](https://github.com/spring-io/spring-security-release-tools/blob/main/RELEASE.adoc)
- [Commits](https://github.com/spring-io/spring-security-release-tools/compare/729fed56d42122f88583aff1be35c0800b7d77e9...b92832ecbc7cbe969201e6beafbde0ee400cf095)

---
updated-dependencies:
- dependency-name: spring-io/spring-security-release-tools/.github/workflows/build.yml
  dependency-version: 1.0.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-20 14:57:09 -06:00
dependabot[bot] 0d75e6d10c Bump @springio/asciidoctor-extensions in /docs
Bumps [@springio/asciidoctor-extensions](https://github.com/spring-io/asciidoctor-extensions) from 1.0.0-alpha.17 to 1.0.0-alpha.18.
- [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.17...v1.0.0-alpha.18)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-20 14:56:46 -06:00
dependabot[bot] 01758c4c59 Bump spring-io/spring-security-release-tools/.github/workflows/deploy-artifacts.yml
Bumps [spring-io/spring-security-release-tools/.github/workflows/deploy-artifacts.yml](https://github.com/spring-io/spring-security-release-tools) from 1.0.14 to 1.0.15.
- [Release notes](https://github.com/spring-io/spring-security-release-tools/releases)
- [Changelog](https://github.com/spring-io/spring-security-release-tools/blob/main/RELEASE.adoc)
- [Commits](https://github.com/spring-io/spring-security-release-tools/compare/729fed56d42122f88583aff1be35c0800b7d77e9...b92832ecbc7cbe969201e6beafbde0ee400cf095)

---
updated-dependencies:
- dependency-name: spring-io/spring-security-release-tools/.github/workflows/deploy-artifacts.yml
  dependency-version: 1.0.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-20 14:56:10 -06:00
dependabot[bot] f37833a59c Bump spring-io/spring-security-release-tools/.github/workflows/test.yml
Bumps [spring-io/spring-security-release-tools/.github/workflows/test.yml](https://github.com/spring-io/spring-security-release-tools) from 1.0.14 to 1.0.15.
- [Release notes](https://github.com/spring-io/spring-security-release-tools/releases)
- [Changelog](https://github.com/spring-io/spring-security-release-tools/blob/main/RELEASE.adoc)
- [Commits](https://github.com/spring-io/spring-security-release-tools/compare/729fed56d42122f88583aff1be35c0800b7d77e9...b92832ecbc7cbe969201e6beafbde0ee400cf095)

---
updated-dependencies:
- dependency-name: spring-io/spring-security-release-tools/.github/workflows/test.yml
  dependency-version: 1.0.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-20 14:55:52 -06:00
dependabot[bot] 52e6c4c4be Bump spring-io/spring-security-release-tools/.github/workflows/deploy-schema.yml
Bumps [spring-io/spring-security-release-tools/.github/workflows/deploy-schema.yml](https://github.com/spring-io/spring-security-release-tools) from 1.0.14 to 1.0.15.
- [Release notes](https://github.com/spring-io/spring-security-release-tools/releases)
- [Changelog](https://github.com/spring-io/spring-security-release-tools/blob/main/RELEASE.adoc)
- [Commits](https://github.com/spring-io/spring-security-release-tools/compare/729fed56d42122f88583aff1be35c0800b7d77e9...b92832ecbc7cbe969201e6beafbde0ee400cf095)

---
updated-dependencies:
- dependency-name: spring-io/spring-security-release-tools/.github/workflows/deploy-schema.yml
  dependency-version: 1.0.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-20 14:55:38 -06:00
github-actions[bot] 96ceb535f4 Next development version 2026-03-16 18:13:58 +00:00
github-actions[bot] 0c54a55ae8 Release 6.5.9 2026-03-16 17:40:54 +00:00
Josh Cummings 01ff3b086a Add Workflow for Deferring Issues
Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-03-16 10:49:07 -06:00
Rob Winch 33e6f4bd3f Merge Fix Jackson Deserializer for AuthenticationExtensionsClientOutputs 2026-03-16 11:57:07 -04:00
Robert Winch cdd4b36d37 Update Antora UI Spring to v0.4.26 2026-03-16 08:26:19 -05:00
Robert Winch 7672f76fde Bump io.projectreactor:reactor-bom from 2024.0.15 to 2024.0.16 2026-03-16 08:26:12 -05:00
Robert Winch 3db4999da4 Bump org.apache.maven:maven-resolver-provider from 3.9.13 to 3.9.14 2026-03-16 08:26:04 -05:00
dependabot[bot] a708d2f61b Bump org.springframework:spring-framework-bom from 6.2.16 to 6.2.17
Bumps [org.springframework:spring-framework-bom](https://github.com/spring-projects/spring-framework) from 6.2.16 to 6.2.17.
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.16...v6.2.17)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-16 03:07:46 +00:00
Ziqin Wang e726c05e76 Fix Jackson 2 deserializer for AuthenticationExtensionsClientOutputs
The deserializer is updated to properly ignore unknown extensions.

Closes gh-18643

Signed-off-by: Ziqin Wang <ziqin@wangziqin.net>
2026-03-15 15:04:14 +08:00
Ziqin Wang a7039fb3e6 Test Jackson 2 deserializer with unknown primitive WebAuthn ext
Signed-off-by: Ziqin Wang <ziqin@wangziqin.net>
2026-03-15 15:03:28 +08:00
Ziqin Wang 88ea668f47 Test Jackson 2 deserializer with unknown obj/arr WebAuthn ext
Signed-off-by: Ziqin Wang <ziqin@wangziqin.net>
2026-03-15 15:03:17 +08:00
github-actions[bot] 03a5de1955 Update Antora Spring UI to v0.4.26 2026-03-13 17:45:05 +00:00
dependabot[bot] 06cbea383e Bump org.apache.maven:maven-resolver-provider from 3.9.13 to 3.9.14
Bumps org.apache.maven:maven-resolver-provider from 3.9.13 to 3.9.14.

---
updated-dependencies:
- dependency-name: org.apache.maven:maven-resolver-provider
  dependency-version: 3.9.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-13 03:07:50 +00:00
Andrey Litvitski e250236279 Read relayState from authenticationRequest
Closes gh-18243

Signed-off-by: Andrey Litvitski <andrey1010102008@gmail.com>
2026-03-12 10:30:11 -06:00
Josh Cummings ef76ba040d Require non-null authenticationRequest
Closes gh-18880

Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-03-11 16:45:23 -06:00
dependabot[bot] d69af716c8 Bump io.projectreactor:reactor-bom from 2024.0.15 to 2024.0.16
Bumps [io.projectreactor:reactor-bom](https://github.com/reactor/reactor) from 2024.0.15 to 2024.0.16.
- [Release notes](https://github.com/reactor/reactor/releases)
- [Commits](https://github.com/reactor/reactor/compare/2024.0.15...2024.0.16)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-11 03:06:57 +00:00
Rob Winch 7e37aa2b75 Merge Fix CookieRequestCache parameters 2026-03-09 15:25:05 -04:00
Vishnutheep B 07bfe371b4 Fix CookieRequestCache parameters
Previously the parameters were not restored.

This commit ensures the parameters are restored.

Closes gh-18204

Signed-off-by: Vishnutheep B <vishnutheep@gmail.com>
2026-03-09 14:10:30 -05:00
Robert Winch e12edf43f2 Bump @antora/collector-extension from 1.0.2 to 1.0.3 in /docs 2026-03-09 09:58:04 -05:00
dependabot[bot] a499e56b9b Bump org.apache.maven:maven-resolver-provider from 3.9.12 to 3.9.13
Bumps org.apache.maven:maven-resolver-provider from 3.9.12 to 3.9.13.

---
updated-dependencies:
- dependency-name: org.apache.maven:maven-resolver-provider
  dependency-version: 3.9.13
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-09 03:09:41 +00:00
dependabot[bot] 8c3f6ea0d4 Bump @antora/collector-extension from 1.0.2 to 1.0.3 in /docs
---
updated-dependencies:
- dependency-name: "@antora/collector-extension"
  dependency-version: 1.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-06 00:37:07 +00:00
Josh Cummings e17d85e460 Add IDE Setup Documentation
Issue gh-17833

Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-03-03 18:51:32 -07:00
dependabot[bot] f12036db05 Bump actions/upload-artifact from 6.0.0 to 7.0.0
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6.0.0 to 7.0.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/b7c566a772e6b6bfb58ed0dc250532a479d7789f...bbbca2ddaa5d8feaa63e36b76fdaad77386f024f)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-03 18:16:39 -07:00
dependabot[bot] 7b5c502a97 Bump org.hibernate.orm:hibernate-core from 6.6.43.Final to 6.6.44.Final
Bumps [org.hibernate.orm:hibernate-core](https://github.com/hibernate/hibernate-orm) from 6.6.43.Final to 6.6.44.Final.
- [Release notes](https://github.com/hibernate/hibernate-orm/releases)
- [Changelog](https://github.com/hibernate/hibernate-orm/blob/6.6.44/changelog.txt)
- [Commits](https://github.com/hibernate/hibernate-orm/compare/6.6.43...6.6.44)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-03 17:47:07 -07:00
HaiYan 706b059ea8 Update logout.adoc
Directives should be Directive

Signed-off-by: HaiYan <haiyan_qi@hotmail.com>
2026-03-03 16:43:18 -07:00
Rob Winch ea3b112bea Fix Flaky Crypto Tests 2026-03-03 15:58:17 -06:00
Robert Winch 1261c229a3 Fix Flaky Crypto Tests
Previously the RsaSecretEncryptorTests were flaky because the assumed that a BadPaddigException would be thrown
when using things like different salt. However, given that the tests had random inputs (e.g. keys) there is the
possibility that, despite the fact that it can never be properly decrypted, the final bytes look like a valid
encrypted value.

This updates the tests to ensure that decrypt either throws an Exception or is not equal to the original
plaintext.
2026-03-03 14:52:28 -06:00
Josh Cummings 4501ae7d1c Update Reactive Resource Server startup exceptations
Issue gh-16708

Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-02-26 16:56:22 -07:00
Josh Cummings 48112d3d74 Polish Resource Server startup expectations
Issue gh-16708

Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-02-26 16:56:22 -07:00
[CLOUD4] 한현 b8735abb63 Clarify Resource Server startup expectations
Clarify that Spring Boot defers OIDC discovery by default.

Closes gh-16708

Signed-off-by: [CLOUD4] 한현 <gusgus1467@naver.com>
2026-02-26 16:56:22 -07:00
Guillaume Husta 68a02ff176 Update Link to CRSF Docs in FAQ
Signed-off-by: Guillaume Husta <guillaume.husta@gmail.com>
2026-02-26 14:47:21 -07:00
dependabot[bot] f37a706d62 Bump org-apache-maven-resolver from 1.9.26 to 1.9.27
Bumps `org-apache-maven-resolver` from 1.9.26 to 1.9.27.

Updates `org.apache.maven.resolver:maven-resolver-connector-basic` from 1.9.26 to 1.9.27
- [Release notes](https://github.com/apache/maven-resolver/releases)
- [Commits](https://github.com/apache/maven-resolver/compare/maven-resolver-1.9.26...maven-resolver-1.9.27)

Updates `org.apache.maven.resolver:maven-resolver-impl` from 1.9.26 to 1.9.27
- [Release notes](https://github.com/apache/maven-resolver/releases)
- [Commits](https://github.com/apache/maven-resolver/compare/maven-resolver-1.9.26...maven-resolver-1.9.27)

Updates `org.apache.maven.resolver:maven-resolver-transport-http` from 1.9.26 to 1.9.27

---
updated-dependencies:
- dependency-name: org.apache.maven.resolver:maven-resolver-connector-basic
  dependency-version: 1.9.27
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.apache.maven.resolver:maven-resolver-impl
  dependency-version: 1.9.27
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.apache.maven.resolver:maven-resolver-transport-http
  dependency-version: 1.9.27
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-26 14:38:30 -07:00
Rob Winch 522c48b3b5 Merge Add Missing OnCommitedResponseWrapper Header Overrides
Add Missing OnCommitedResponseWrapper Header Overrides
2026-02-24 20:16:24 -06:00
Robert Winch 1dae9aa459 Add Missing OnCommitedResponseWrapper Header Overrides
Spring Security's `OnCommitedResponseWrapper` does not override the `setHeader`, `setIntHeader`, `addIntHeader`
methods. This means that if the `Content-Length` response header is specified using any of those methods then
the response body length is not tracked and can be committed before the response headers are written.

Spring Security should override the missing methods and track `Content-Length` as is already done for `addHeader`.

This issue is the underlying problem for spring-projects/spring-framework#36381

Closes gh-18797
2026-02-24 19:46:29 -06:00
Josh Cummings bec25edeb0 Merge pull request #18566 from Hann244/docs/gh-16530-jsp-method-attribute
Clarify need for method attribute in JSP authorize tag
2026-02-24 17:08:14 -07:00
Josh Cummings 4d43edfb20 Polish Documentation
- Combined explanation of method attribute with usage recommendations
- Used one sentence per line format

Issue gh-16530

Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
2026-02-24 14:24:11 -07:00
onhann 9f9699f8a5 Clarify need for method attribute in JSP authorize tag
Closes gh-16530

This aligns the JSP documentation with the changes made in gh-16529.
Added a NOTE to clarify that the method attribute is required when the underlying RequestMatcher is method-specific.

Signed-off-by: onhann <gusgus1467@naver.com>
2026-02-24 14:24:11 -07:00
Rob Winch d29c984881 Merge pull request #18544 from Khyojae/gh-18543
Fix GrantedAuthority.authority null in AuthoritiesAuthorizationManager
2026-02-23 11:16:42 -06:00
3644 changed files with 56843 additions and 158804 deletions
+52 -118
View File
@@ -1,12 +1,11 @@
version: 2
registries:
shibboleth:
spring-milestones:
type: maven-repository
url: https://build.shibboleth.net/maven/releases
url: https://repo.spring.io/milestone
updates:
# 6.5.x
- package-ecosystem: gradle
target-branch: 6.5.x
target-branch: 6.4.x
directory: /
schedule:
interval: daily
@@ -15,7 +14,7 @@ updates:
labels:
- 'type: dependency-upgrade'
registries:
- shibboleth
- spring-milestones
ignore:
- dependency-name: com.nimbusds:nimbus-jose-jwt
- dependency-name: org.python:jython
@@ -31,28 +30,8 @@ updates:
update-types:
- version-update:semver-major
- version-update:semver-minor
- package-ecosystem: npm
target-branch: 6.5.x
directory: /docs
schedule:
interval: weekly
labels:
- 'type: task'
- 'type: dependency-upgrade'
- 'in: build'
- package-ecosystem: github-actions
target-branch: 6.5.x
directory: /
schedule:
interval: weekly
labels:
- 'type: task'
- 'type: dependency-upgrade'
- 'in: build'
# 7.0.x
- package-ecosystem: gradle
target-branch: 7.0.x
target-branch: 6.3.x
directory: /
schedule:
interval: daily
@@ -61,7 +40,33 @@ updates:
labels:
- 'type: dependency-upgrade'
registries:
- shibboleth
- spring-milestones
ignore:
- dependency-name: com.nimbusds:nimbus-jose-jwt
- dependency-name: org.python:jython
- dependency-name: org.apache.directory.server:*
- dependency-name: org.apache.directory.shared:*
- dependency-name: org.junit:junit-bom
update-types:
- version-update:semver-major
- dependency-name: org.mockito:mockito-bom
update-types:
- version-update:semver-major
- dependency-name: '*'
update-types:
- version-update:semver-major
- version-update:semver-minor
- package-ecosystem: gradle
target-branch: main
directory: /
schedule:
interval: daily
time: '03:00'
timezone: Etc/UTC
labels:
- 'type: dependency-upgrade'
registries:
- spring-milestones
ignore:
- dependency-name: com.nimbusds:nimbus-jose-jwt
- dependency-name: org.python:jython
@@ -81,55 +86,35 @@ updates:
update-types:
- version-update:semver-major
- version-update:semver-minor
- package-ecosystem: npm
target-branch: 7.0.x
directory: /docs
schedule:
interval: weekly
labels:
- 'type: task'
- 'type: dependency-upgrade'
- 'in: build'
- package-ecosystem: github-actions
target-branch: 7.0.x
target-branch: 6.3.x
directory: /
schedule:
interval: weekly
labels:
- 'type: task'
- 'in: build'
ignore:
- dependency-name: sjohnr/*
- package-ecosystem: github-actions
target-branch: docs-build
directory: /
schedule:
interval: weekly
labels:
- 'type: task'
- 'type: dependency-upgrade'
- 'in: build'
# main
- package-ecosystem: gradle
target-branch: main
- package-ecosystem: npm
target-branch: docs-build
directory: /
schedule:
interval: daily
time: '03:00'
timezone: Etc/UTC
interval: weekly
labels:
- 'type: dependency-upgrade'
registries:
- shibboleth
ignore:
- dependency-name: com.nimbusds:nimbus-jose-jwt
- dependency-name: org.python:jython
- dependency-name: org.apache.directory.server:*
- dependency-name: org.apache.directory.shared:*
- dependency-name: org.junit:junit-bom
update-types:
- version-update:semver-major
- dependency-name: org.mockito:mockito-bom
update-types:
- version-update:semver-major
- dependency-name: com.gradle.enterprise
update-types:
- version-update:semver-major
- version-update:semver-minor
- dependency-name: '*'
update-types:
- version-update:semver-major
- 'type: task'
- 'in: build'
- package-ecosystem: npm
target-branch: main
directory: /docs
@@ -137,63 +122,12 @@ updates:
interval: weekly
labels:
- 'type: task'
- 'type: dependency-upgrade'
- 'in: build'
- package-ecosystem: github-actions
target-branch: main
directory: /
schedule:
interval: weekly
labels:
- 'type: task'
- 'type: dependency-upgrade'
- 'in: build'
# docs-build
- package-ecosystem: gradle
target-branch: docs-build
directory: /
schedule:
interval: daily
time: '03:00'
timezone: Etc/UTC
labels:
- 'type: dependency-upgrade'
registries:
- shibboleth
ignore:
- dependency-name: com.nimbusds:nimbus-jose-jwt
- dependency-name: org.python:jython
- dependency-name: org.apache.directory.server:*
- dependency-name: org.apache.directory.shared:*
- dependency-name: org.junit:junit-bom
update-types:
- version-update:semver-major
- dependency-name: org.mockito:mockito-bom
update-types:
- version-update:semver-major
- dependency-name: com.gradle.enterprise
update-types:
- version-update:semver-major
- version-update:semver-minor
- dependency-name: '*'
update-types:
- version-update:semver-major
- package-ecosystem: npm
target-branch: docs-build
directory: /
target-branch: 6.3.x
directory: /docs
schedule:
interval: weekly
labels:
- 'type: task'
- 'type: dependency-upgrade'
- 'in: build'
- package-ecosystem: github-actions
target-branch: docs-build
directory: /
schedule:
interval: weekly
labels:
- 'type: task'
- 'type: dependency-upgrade'
- 'in: build'
@@ -1,16 +0,0 @@
name: Merge Dependabot PR
on:
pull_request:
branches:
- main
- '*.x'
run-name: Merge Dependabot PR ${{ github.ref_name }}
jobs:
merge-dependabot-pr:
permissions: write-all
uses: spring-io/spring-github-workflows/.github/workflows/spring-merge-dependabot-pr.yml@v7
with:
mergeArguments: --auto --rebase
-36
View File
@@ -1,36 +0,0 @@
name: CI
on:
schedule:
- cron: '0 10 * * *' # Once per day at 10am UTC
workflow_dispatch: # Manual trigger
env:
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
permissions:
contents: read
jobs:
snapshot-test:
name: Test Against Snapshots
uses: spring-io/spring-security-release-tools/.github/workflows/test.yml@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
strategy:
matrix:
include:
- java-version: 25
toolchain: 25
with:
java-version: ${{ matrix.java-version }}
test-args: --refresh-dependencies -PforceMavenRepositories=snapshot,https://oss.sonatype.org/content/repositories/snapshots -PisOverrideVersionCatalog -PtestToolchain=${{ matrix.toolchain }} -PspringFrameworkVersion=7.+ -PreactorVersion=2025.+ -PspringDataVersion=2025.+ --stacktrace
secrets: inherit
send-notification:
name: Send Notification
needs: [ snapshot-test ]
if: ${{ !success() }}
runs-on: ubuntu-latest
steps:
- name: Send Notification
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
with:
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
+1 -1
View File
@@ -14,4 +14,4 @@ jobs:
actions: read
contents: read
security-events: write
uses: spring-io/github-actions/.github/workflows/codeql-analysis.yml@1
uses: spring-io/github-actions/.github/workflows/codeql-analysis.yml@e415dadd0910c901e7a7fabd67bbb355b2324500 # 1
@@ -17,45 +17,78 @@ permissions:
jobs:
build:
name: Build
uses: spring-io/spring-security-release-tools/.github/workflows/build.yml@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
uses: spring-io/spring-security-release-tools/.github/workflows/build.yml@b92832ecbc7cbe969201e6beafbde0ee400cf095 # v1.0.15
strategy:
matrix:
os: [ ubuntu-latest, windows-latest ]
jdk: [ 25 ]
jdk: [ 17 ]
with:
runs-on: ${{ matrix.os }}
java-version: ${{ matrix.jdk }}
distribution: temurin
secrets: inherit
test:
name: Test Against Snapshots
uses: spring-io/spring-security-release-tools/.github/workflows/test.yml@b92832ecbc7cbe969201e6beafbde0ee400cf095 # v1.0.15
strategy:
matrix:
include:
- java-version: 21-ea
toolchain: 21
- java-version: 17
toolchain: 17
with:
java-version: ${{ matrix.java-version }}
test-args: --refresh-dependencies -PforceMavenRepositories=snapshot -PisOverrideVersionCatalog -PtestToolchain=${{ matrix.toolchain }} -PspringFrameworkVersion=6.2.+ -PreactorVersion=2023.0.+ -PspringDataVersion=2024.0.+ -PmicrometerVersion=1.15.+ --stacktrace
secrets: inherit
check-samples:
name: Check Samples
runs-on: ubuntu-latest
if: ${{ github.repository_owner == 'spring-projects' }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up gradle
uses: spring-io/spring-gradle-build-action@c8668747d7c264864c8c7f7026d0d277d14a78dc # v2.0.6
with:
java-version: 17
distribution: temurin
- name: Check samples project
env:
LOCAL_REPOSITORY_PATH: ${{ github.workspace }}/build/publications/repos
SAMPLES_DIR: ../spring-security-samples
run: |
# Extract version from gradle.properties
version=$(cat gradle.properties | grep "version=" | awk -F'=' '{print $2}')
# Extract samplesBranch from gradle.properties
samples_branch=$(cat gradle.properties | grep "samplesBranch=" | awk -F'=' '{print $2}')
./gradlew publishMavenJavaPublicationToLocalRepository
./gradlew cloneRepository -PrepositoryName="spring-projects/spring-security-samples" -Pref="$samples_branch" -PcloneOutputDirectory="$SAMPLES_DIR"
./gradlew --refresh-dependencies --project-dir "$SAMPLES_DIR" --init-script spring-security-ci.gradle -PlocalRepositoryPath="$LOCAL_REPOSITORY_PATH" -PspringSecurityVersion="$version" test integrationTest
deploy-artifacts:
name: Deploy Artifacts
needs: [ build]
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-artifacts.yml@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
needs: [ build, test, check-samples ]
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-artifacts.yml@b92832ecbc7cbe969201e6beafbde0ee400cf095 # v1.0.15
with:
should-deploy-artifacts: ${{ needs.build.outputs.should-deploy-artifacts }}
default-publish-milestones-central: true
java-version: 25
secrets: inherit
deploy-schema:
name: Deploy Schema
needs: [ build ]
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-schema.yml@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
needs: [ build, test, check-samples ]
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-schema.yml@b92832ecbc7cbe969201e6beafbde0ee400cf095 # v1.0.15
with:
should-deploy-schema: ${{ needs.build.outputs.should-deploy-artifacts }}
java-version: 25
secrets: inherit
perform-release:
name: Perform Release
needs: [ deploy-artifacts, deploy-schema ]
uses: spring-io/spring-security-release-tools/.github/workflows/perform-release.yml@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
uses: spring-io/spring-security-release-tools/.github/workflows/perform-release.yml@b92832ecbc7cbe969201e6beafbde0ee400cf095 # v1.0.15
with:
should-perform-release: ${{ needs.deploy-artifacts.outputs.artifacts-deployed }}
project-version: ${{ needs.deploy-artifacts.outputs.project-version }}
milestone-repo-url: https://repo1.maven.org/maven2
milestone-repo-url: https://repo.spring.io/artifactory/milestone
release-repo-url: https://repo1.maven.org/maven2
artifact-path: org/springframework/security/spring-security-core
slack-announcing-id: spring-security-announcing
java-version: 25
secrets: inherit
send-notification:
name: Send Notification
@@ -64,6 +97,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Send Notification
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@b92832ecbc7cbe969201e6beafbde0ee400cf095 # v1.0.15
with:
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
+76
View File
@@ -0,0 +1,76 @@
name: Defer Issues
on:
workflow_dispatch:
permissions:
contents: read
jobs:
defer-issues:
name: Defer Issues
runs-on: ubuntu-latest
if: github.repository_owner == 'spring-projects'
permissions:
issues: write
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Compute Version
id: compute-version
uses: spring-io/spring-release-actions/compute-version@a1f321783a0769dd2aea4fad6c2ae2f95a52b885 # 0.0.5
- name: Get Today's Release Version
id: todays-release
uses: spring-io/spring-release-actions/get-todays-release-version@a1f321783a0769dd2aea4fad6c2ae2f95a52b885 # 0.0.5
with:
snapshot-version: ${{ steps.compute-version.outputs.version }}
milestone-repository: ${{ github.repository }}
milestone-token: ${{ secrets.GITHUB_TOKEN }}
- name: Compute Next Version
id: next-version
uses: spring-io/spring-release-actions/compute-next-version@a1f321783a0769dd2aea4fad6c2ae2f95a52b885 # 0.0.5
with:
version: ${{ steps.todays-release.outputs.release-version }}
- name: Schedule Next Milestone
uses: spring-io/spring-release-actions/schedule-milestone@a1f321783a0769dd2aea4fad6c2ae2f95a52b885 # 0.0.5
with:
version: ${{ steps.next-version.outputs.version }}
version-date: ${{ steps.next-version.outputs.version-date }}
repository: ${{ github.repository }}
token: ${{ secrets.GITHUB_TOKEN }}
- name: Move Open Issues to Next Milestone
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CURRENT_MILESTONE: ${{ steps.todays-release.outputs.release-version }}
NEXT_MILESTONE: ${{ steps.next-version.outputs.version }}
run: |
current_milestone_number=$(gh api repos/${{ github.repository }}/milestones \
--jq ".[] | select(.title == \"$CURRENT_MILESTONE\") | .number")
if [ -z "$current_milestone_number" ]; then
echo "No milestone found for $CURRENT_MILESTONE"
exit 0
fi
next_milestone_number=$(gh api repos/${{ github.repository }}/milestones \
--jq ".[] | select(.title == \"$NEXT_MILESTONE\") | .number")
if [ -z "$next_milestone_number" ]; then
echo "No milestone found for $NEXT_MILESTONE"
exit 1
fi
echo "Moving open issues from milestone '$CURRENT_MILESTONE' (#$current_milestone_number) to '$NEXT_MILESTONE' (#$next_milestone_number)"
page=1
while true; do
issues=$(gh api "repos/${{ github.repository }}/issues?milestone=$current_milestone_number&state=open&per_page=100&page=$page" \
--jq '.[].number')
if [ -z "$issues" ]; then
break
fi
for issue in $issues; do
echo "Moving issue/PR #$issue to milestone $NEXT_MILESTONE"
gh api repos/${{ github.repository }}/issues/$issue \
--method PATCH \
--field milestone=$next_milestone_number \
--silent
done
page=$((page + 1))
done
echo "Done."
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
if: github.repository_owner == 'spring-projects'
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: docs-build
fetch-depth: 1
-27
View File
@@ -1,27 +0,0 @@
name: Finalize Release
on:
workflow_dispatch: # Manual trigger
inputs:
version:
description: The Spring Security release to finalize (e.g. 7.0.0-RC2)
required: true
env:
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
permissions:
contents: read
jobs:
perform-release:
name: Perform Release
uses: spring-io/spring-security-release-tools/.github/workflows/perform-release.yml@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
with:
should-perform-release: true
project-version: ${{ inputs.version }}
milestone-repo-url: https://repo1.maven.org/maven2
release-repo-url: https://repo1.maven.org/maven2
artifact-path: org/springframework/security/spring-security-core
slack-announcing-id: spring-security-announcing
secrets: inherit
@@ -9,7 +9,6 @@ permissions:
jobs:
upgrade_wrapper:
name: Execution
if: ${{ github.repository == 'spring-projects/spring-security' }}
runs-on: ubuntu-latest
steps:
- name: Set up Git configuration
@@ -20,11 +19,11 @@ jobs:
git config --global user.name 'github-actions[bot]'
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up JDK 25
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up JDK 17
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
java-version: '25'
java-version: '17'
distribution: 'temurin'
- name: Set up Gradle
uses: gradle/setup-gradle@f29f5a9d7b09a7c6b29859002d29d24e1674c884 # v5.0.1
@@ -30,6 +30,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Send Notification
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@b92832ecbc7cbe969201e6beafbde0ee400cf095 # v1.0.15
with:
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
+8 -8
View File
@@ -11,11 +11,11 @@ jobs:
runs-on: ubuntu-latest
if: ${{ github.repository == 'spring-projects/spring-security' }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up gradle
uses: spring-io/spring-gradle-build-action@efc55f07f4dfa22f2afd97f9ea1be4212eeed737 # v2.0.5
uses: spring-io/spring-gradle-build-action@c8668747d7c264864c8c7f7026d0d277d14a78dc # v2.0.6
with:
java-version: '25'
java-version: '17'
distribution: 'temurin'
- name: Build with Gradle
run: ./gradlew clean build -PskipCheckExpectedBranchVersion --continue --scan
@@ -24,17 +24,17 @@ jobs:
runs-on: ubuntu-latest
if: ${{ github.repository == 'spring-projects/spring-security' }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up gradle
uses: spring-io/spring-gradle-build-action@efc55f07f4dfa22f2afd97f9ea1be4212eeed737 # v2.0.5
uses: spring-io/spring-gradle-build-action@c8668747d7c264864c8c7f7026d0d277d14a78dc # v2.0.6
with:
java-version: '25'
java-version: '17'
distribution: 'temurin'
- name: Run Antora
run: ./gradlew -PbuildSrc.skipTests=true :spring-security-docs:antora
- name: Upload Docs
id: upload
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: docs
path: docs/build/site
@@ -46,6 +46,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Send Notification
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@b92832ecbc7cbe969201e6beafbde0ee400cf095 # v1.0.15
with:
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
+2 -2
View File
@@ -11,11 +11,11 @@ jobs:
strategy:
matrix:
# List of active maintenance branches.
branch: [ main, 7.0.x, 6.5.x, 6.4.x, 6.3.x ]
branch: [ main, 6.4.x, 6.3.x ]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1
- name: Dispatch
@@ -12,25 +12,23 @@ permissions:
jobs:
update-antora-ui-spring:
name: Update on Supported Branches
if: ${{ github.repository == 'spring-projects/spring-security' }}
runs-on: ubuntu-latest
name: Update on Supported Branches
strategy:
matrix:
branch: [ '6.5.x', '7.0.x', 'main' ]
branch: [ '5.8.x', '6.2.x', '6.3.x', 'main' ]
steps:
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@415e2b11a766ba64799fffb5c97a4f7e17f677cf
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@415e2b11a766ba64799fffb5c97a4f7e17f677cf # v0.0.22
name: Update
with:
docs-branch: ${{ matrix.branch }}
token: ${{ secrets.GITHUB_TOKEN }}
antora-file-path: 'docs/antora-playbook.yml'
update-antora-ui-spring-docs-build:
name: Update on docs-build
if: ${{ github.repository == 'spring-projects/spring-security' }}
runs-on: ubuntu-latest
name: Update on docs-build
steps:
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@415e2b11a766ba64799fffb5c97a4f7e17f677cf
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@415e2b11a766ba64799fffb5c97a4f7e17f677cf # v0.0.22
name: Update
with:
docs-branch: 'docs-build'
@@ -9,7 +9,7 @@ permissions:
jobs:
update-scheduled-release-version:
name: Update Scheduled Release Version
uses: spring-io/spring-security-release-tools/.github/workflows/update-scheduled-release-version.yml@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
uses: spring-io/spring-security-release-tools/.github/workflows/update-scheduled-release-version.yml@b92832ecbc7cbe969201e6beafbde0ee400cf095 # v1.0.15
secrets: inherit
send-notification:
name: Send Notification
@@ -18,6 +18,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Send Notification
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@b92832ecbc7cbe969201e6beafbde0ee400cf095 # v1.0.15
with:
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
-1
View File
@@ -25,7 +25,6 @@ atlassian-ide-plugin.xml
s101plugin.state
.attach_pid*
.~lock.*#
.kotlin/
!.idea/checkstyle-idea.xml
!.idea/externalDependencies.xml
+1 -1
View File
@@ -3,4 +3,4 @@
# See https://sdkman.io/usage#config
# A summary is to add the following to ~/.sdkman/etc/config
# sdkman_auto_env=true
java=25-librca
java=17.0.3-tem
+1 -1
View File
@@ -1,3 +1,3 @@
{
"java.gradle.buildServer.enabled": "off"
"java.import.gradle.enabled": false
}
+2 -5
View File
@@ -31,7 +31,7 @@ If you have a question, check Stack Overflow using
https://stackoverflow.com/questions/tagged/spring-security+or+spring-ldap+or+spring-authorization-server+or+spring-session?tab=Newest[this list of tags].
Find an existing discussion, or start a new one if necessary.
If you believe there is an issue, search through https://github.com/spring-projects/spring-security/issues[existing issues] trying a few different ways to find discussions, past or current, that are related to the issue.
If you believe there is an issue, search through https://github.com/spring-projects/spring-security/issues[existing issues] trying a few different ways to find discussions, past or current, that are related to the issue.
Reading those discussions helps you to learn about the issue, and helps us to make a decision.
[[find-an-issue]]
@@ -79,9 +79,6 @@ See https://github.com/spring-projects/spring-security/tree/main#building-from-s
The wiki pages https://github.com/spring-projects/spring-framework/wiki/Code-Style[Code Style] and https://github.com/spring-projects/spring-framework/wiki/IntelliJ-IDEA-Editor-Settings[IntelliJ IDEA Editor Settings] define the source file coding standards we use along with some IDEA editor settings we customize.
Additionally, since Streams are https://github.com/spring-projects/spring-security/issues/7154[much slower] than `for` loops, please use them judiciously.
The team may ask you to change to a `for` loop if the given code is along a hot path.
To format the code as well as check the style, run `./gradlew format && ./gradlew check`.
[[submit-a-pull-request]]
@@ -94,7 +91,7 @@ Don't worry if you don't get them all correct the first time, we will help you.
1. [[sign-cla]] All commits must include a __Signed-off-by__ trailer at the end of each commit message to indicate that the contributor agrees to the Developer Certificate of Origin.
For additional details, please refer to the blog post https://spring.io/blog/2025/01/06/hello-dco-goodbye-cla-simplifying-contributions-to-spring[Hello DCO, Goodbye CLA: Simplifying Contributions to Spring].
2. [[create-an-issue-list]] Must you https://github.com/spring-projects/spring-security/issues/new/choose[create an issue] first? No, but it is recommended for features and larger bug fixes. It's easier to discuss with the team first to determine the right fix or enhancement.
2. [[create-an-issue-list]] Must you https://github.com/spring-projects/spring-security/issues/new/choose[create an issue] first? No, but it is recommended for features and larger bug fixes. It's easier discuss with the team first to determine the right fix or enhancement.
For typos and straightforward bug fixes, starting with a pull request is encouraged.
Please include a description for context and motivation.
Note that the team may close your pull request if it's not a fit for the project.
+21
View File
@@ -68,6 +68,27 @@ The https://github.com/spring-projects/spring-security/tree/docs-build[playbook
Discover more commands with `./gradlew tasks`.
=== IDE setup (IntelliJ)
No special steps are needed to open Spring Security in IntelliJ.
=== IDE setup (Eclipse and VS Code)
To work in Eclipse or VS Code, first generate Eclipse metadata so you can import the project into Eclipse or VS Code:
[indent=0]
----
./gradlew cleanEclipse eclipse
----
If you have not built the project yet, run `./gradlew publishToMavenLocal` first so dependencies are resolved.
*VS Code:* Open the repository root as a folder. The repository includes `.vscode/settings.json` which disables automatic Gradle import so that the generated Eclipse metadata (`.classpath`, `.project`) is used. Do not use the Gradle for Java extension to import the project.
*Eclipse:* File → Import → General → Existing Projects into Workspace, then select the repository root.
The build uses a custom Eclipse plugin to work around Gradle dependency cycles that confuse IDE metadata generation. You may see Eclipse warnings about `xml-apis` from some test dependencies; those are excluded in the build and can be ignored.
== Getting Support
Check out the https://stackoverflow.com/questions/tagged/spring-security[Spring Security tags on Stack Overflow].
https://spring.io/support[Commercial support] is available too.
-54
View File
@@ -1,54 +0,0 @@
plugins {
id 'compile-warnings-error'
id 'javadoc-warnings-error'
}
apply plugin: 'io.spring.convention.spring-module'
dependencies {
management platform(project(":spring-security-dependencies"))
api project(':spring-security-crypto')
api project(':spring-security-core')
api 'org.springframework:spring-aop'
api 'org.springframework:spring-beans'
api 'org.springframework:spring-context'
api 'org.springframework:spring-core'
api 'org.springframework:spring-expression'
api 'io.micrometer:micrometer-observation'
optional project(':spring-security-acl')
optional project(':spring-security-messaging')
optional project(':spring-security-web')
optional 'org.springframework:spring-websocket'
optional 'com.fasterxml.jackson.core:jackson-databind'
optional 'io.micrometer:context-propagation'
optional 'io.projectreactor:reactor-core'
optional 'jakarta.annotation:jakarta.annotation-api'
optional 'org.aspectj:aspectjrt'
optional 'org.springframework:spring-jdbc'
optional 'org.springframework:spring-tx'
optional 'org.jetbrains.kotlinx:kotlinx-coroutines-reactor'
provided 'jakarta.servlet:jakarta.servlet-api'
testImplementation project(path : ':spring-security-web', configuration : 'tests')
testImplementation 'commons-collections:commons-collections'
testImplementation 'io.projectreactor:reactor-test'
testImplementation "org.assertj:assertj-core"
testImplementation "org.junit.jupiter:junit-jupiter-api"
testImplementation "org.junit.jupiter:junit-jupiter-params"
testImplementation "org.junit.jupiter:junit-jupiter-engine"
testImplementation "org.mockito:mockito-core"
testImplementation "org.mockito:mockito-junit-jupiter"
testImplementation "org.springframework:spring-core-test"
testImplementation "org.springframework:spring-test"
testImplementation 'org.skyscreamer:jsonassert'
testImplementation 'org.springframework:spring-test'
testImplementation 'org.jetbrains.kotlin:kotlin-reflect'
testImplementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
testImplementation 'io.mockk:mockk'
testRuntimeOnly 'org.hsqldb:hsqldb'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
@@ -1,36 +0,0 @@
/*
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.access;
/**
* Represents the interface of a secured object.
*
* @author Ben Alex
*/
public interface ITargetObject {
Integer computeHashCode(String input);
int countLength(String input);
String makeLowerCase(String input);
String makeUpperCase(String input);
String publicMakeLowerCase(String input);
}
@@ -1,53 +0,0 @@
/*
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.access;
/**
* Simply extends {@link TargetObject} so we have a different object to put configuration
* attributes against.
* <P>
* There is no different behaviour. We have to define each method so that
* <code>Class.getMethod(methodName, args)</code> returns a <code>Method</code>
* referencing this class rather than the parent class.
* </p>
* <P>
* We need to implement <code>ITargetObject</code> again because the
* <code>MethodDefinitionAttributes</code> only locates attributes on interfaces
* explicitly defined by the intercepted class (not the interfaces defined by its parent
* class or classes).
* </p>
*
* @author Ben Alex
*/
public class OtherTargetObject extends TargetObject implements ITargetObject {
@Override
public String makeLowerCase(String input) {
return super.makeLowerCase(input);
}
@Override
public String makeUpperCase(String input) {
return super.makeUpperCase(input);
}
@Override
public String publicMakeLowerCase(String input) {
return super.publicMakeLowerCase(input);
}
}
@@ -1,81 +0,0 @@
/*
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.access;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
/**
* Represents a secured object.
*
* @author Ben Alex
*/
public class TargetObject implements ITargetObject {
@Override
public Integer computeHashCode(String input) {
return input.hashCode();
}
@Override
public int countLength(String input) {
return input.length();
}
/**
* Returns the lowercase string, followed by security environment information.
* @param input the message to make lowercase
* @return the lowercase message, a space, the <code>Authentication</code> class that
* was on the <code>SecurityContext</code> at the time of method invocation, and a
* boolean indicating if the <code>Authentication</code> object is authenticated or
* not
*/
@Override
public String makeLowerCase(String input) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth == null) {
return input.toLowerCase() + " Authentication empty";
}
else {
return input.toLowerCase() + " " + auth.getClass().getName() + " " + auth.isAuthenticated();
}
}
/**
* Returns the uppercase string, followed by security environment information.
* @param input the message to make uppercase
* @return the uppercase message, a space, the <code>Authentication</code> class that
* was on the <code>SecurityContext</code> at the time of method invocation, and a
* boolean indicating if the <code>Authentication</code> object is authenticated or
* not
*/
@Override
public String makeUpperCase(String input) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
return input.toUpperCase() + " " + auth.getClass().getName() + " " + auth.isAuthenticated();
}
/**
* Delegates through to the {@link #makeLowerCase(String)} method.
* @param input the message to be made lower-case
*/
@Override
public String publicMakeLowerCase(String input) {
return this.makeLowerCase(input);
}
}
-6
View File
@@ -1,9 +1,3 @@
plugins {
id 'compile-warnings-error'
id 'javadoc-warnings-error'
id 'security-nullability'
}
apply plugin: 'io.spring.convention.spring-module'
dependencies {
@@ -71,7 +71,7 @@ import org.springframework.util.StringUtils;
* <tt>AclEntryVoter</tt>:
* <ul>
* <li>Process domain object class <code>BankAccount</code>, configuration attribute
* <code>VOTE_ACL_BANK_ACCOUNT_READ</code>, require permission
* <code>VOTE_ACL_BANK_ACCONT_READ</code>, require permission
* <code>BasePermission.READ</code></li>
* <li>Process domain object class <code>BankAccount</code>, configuration attribute
* <code>VOTE_ACL_BANK_ACCOUNT_WRITE</code>, require permission list
@@ -44,7 +44,7 @@ import org.springframework.security.core.Authentication;
/**
* Used by Spring Security's expression-based access control implementation to evaluate
* permissions for a particular object using the ACL module. Similar in behaviour to
* <code> org.springframework.security.acls.AclEntryVoter AclEntryVoter </code>
* {@link org.springframework.security.acls.AclEntryVoter AclEntryVoter}.
*
* @author Luke Taylor
* @since 3.0
@@ -1,79 +0,0 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.acls.aot.hint;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.aot.hint.TypeReference;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.security.acls.domain.AclImpl;
import org.springframework.security.acls.domain.AuditLogger;
import org.springframework.security.acls.domain.BasePermission;
import org.springframework.security.acls.domain.GrantedAuthoritySid;
import org.springframework.security.acls.domain.ObjectIdentityImpl;
import org.springframework.security.acls.domain.PrincipalSid;
import org.springframework.security.acls.model.AccessControlEntry;
import org.springframework.security.acls.model.Acl;
import org.springframework.security.acls.model.AuditableAccessControlEntry;
import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.security.acls.model.Sid;
/**
* {@link RuntimeHintsRegistrar} for ACL (Access Control List) classes.
*
* @author Josh Long
*/
class AclRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
registerAclDomainHints(hints);
registerJdbcSchemaHints(hints);
}
private void registerAclDomainHints(RuntimeHints hints) {
// Register core ACL domain types
Stream
.of(Acl.class, AccessControlEntry.class, AuditableAccessControlEntry.class, ObjectIdentity.class, Sid.class,
AclImpl.class, AccessControlEntry.class, AuditLogger.class, ObjectIdentityImpl.class,
PrincipalSid.class, GrantedAuthoritySid.class, BasePermission.class)
.forEach((c) -> hints.reflection()
.registerType(TypeReference.of(c),
(builder) -> builder.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.ACCESS_DECLARED_FIELDS)));
}
private void registerJdbcSchemaHints(RuntimeHints hints) {
String[] sqlFiles = new String[] { "createAclSchema.sql", "createAclSchemaMySQL.sql",
"createAclSchemaOracle.sql", "createAclSchemaPostgres.sql", "createAclSchemaSqlServer.sql",
"createAclSchemaWithAclClassIdType.sql", "select.sql" };
for (String sqlFile : sqlFiles) {
Resource sqlResource = new ClassPathResource(sqlFile);
if (sqlResource.exists()) {
hints.resources().registerResource(sqlResource);
}
}
}
}
@@ -1,23 +0,0 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* AOT and native image hint support for ACLs.
*/
@NullMarked
package org.springframework.security.acls.aot.hint;
import org.jspecify.annotations.NullMarked;
@@ -18,8 +18,6 @@ package org.springframework.security.acls.domain;
import java.io.Serializable;
import org.jspecify.annotations.Nullable;
import org.springframework.security.acls.model.AccessControlEntry;
import org.springframework.security.acls.model.Acl;
import org.springframework.security.acls.model.AuditableAccessControlEntry;
@@ -38,7 +36,7 @@ public class AccessControlEntryImpl implements AccessControlEntry, AuditableAcce
private Permission permission;
private final @Nullable Serializable id;
private final Serializable id;
private final Sid sid;
@@ -48,7 +46,7 @@ public class AccessControlEntryImpl implements AccessControlEntry, AuditableAcce
private final boolean granting;
public AccessControlEntryImpl(@Nullable Serializable id, Acl acl, Sid sid, Permission permission, boolean granting,
public AccessControlEntryImpl(Serializable id, Acl acl, Sid sid, Permission permission, boolean granting,
boolean auditSuccess, boolean auditFailure) {
Assert.notNull(acl, "Acl required");
Assert.notNull(sid, "Sid required");
@@ -135,7 +133,7 @@ public class AccessControlEntryImpl implements AccessControlEntry, AuditableAcce
}
@Override
public @Nullable Serializable getId() {
public Serializable getId() {
return this.id;
}
@@ -20,7 +20,7 @@ import org.springframework.security.acls.model.Acl;
/**
* Strategy used by {@link AclImpl} to determine whether a principal is permitted to call
* administrative methods on the <code>AclImpl</code>.
* adminstrative methods on the <code>AclImpl</code>.
*
* @author Ben Alex
*/
@@ -99,8 +99,7 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
Authentication authentication = context.getAuthentication();
// Check if authorized by virtue of ACL ownership
Sid currentUser = createCurrentUser(authentication);
Sid owner = acl.getOwner();
if (owner != null && currentUser.equals(owner)
if (currentUser.equals(acl.getOwner())
&& ((changeType == CHANGE_GENERAL) || (changeType == CHANGE_OWNERSHIP))) {
return;
}
@@ -109,8 +108,8 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
Collection<? extends GrantedAuthority> reachableGrantedAuthorities = this.roleHierarchy
.getReachableGrantedAuthorities(authentication.getAuthorities());
Set<String> authorities = AuthorityUtils.authorityListToSet(reachableGrantedAuthorities);
if (owner instanceof GrantedAuthoritySid
&& authorities.contains(((GrantedAuthoritySid) owner).getGrantedAuthority())) {
if (acl.getOwner() instanceof GrantedAuthoritySid
&& authorities.contains(((GrantedAuthoritySid) acl.getOwner()).getGrantedAuthority())) {
return;
}
@@ -20,8 +20,6 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.security.acls.model.AccessControlEntry;
import org.springframework.security.acls.model.Acl;
import org.springframework.security.acls.model.AuditableAcl;
@@ -43,7 +41,7 @@ import org.springframework.util.ObjectUtils;
*/
public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
private @Nullable Acl parentAcl;
private Acl parentAcl;
private transient AclAuthorizationStrategy aclAuthorizationStrategy;
@@ -56,10 +54,10 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
private Serializable id;
// OwnershipAcl
private @Nullable Sid owner;
private Sid owner;
// includes all SIDs the WHERE clause covered, even if there was no ACE for a SID
private @Nullable List<Sid> loadedSids = null;
private List<Sid> loadedSids = null;
private boolean entriesInheriting = true;
@@ -99,8 +97,8 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
* @param owner the owner (required)
*/
public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy,
PermissionGrantingStrategy grantingStrategy, @Nullable Acl parentAcl, @Nullable List<Sid> loadedSids,
boolean entriesInheriting, Sid owner) {
PermissionGrantingStrategy grantingStrategy, Acl parentAcl, List<Sid> loadedSids, boolean entriesInheriting,
Sid owner) {
Assert.notNull(objectIdentity, "Object Identity required");
Assert.notNull(id, "Id required");
Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required");
@@ -119,7 +117,7 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
* Private no-argument constructor for use by reflection-based persistence tools along
* with field-level access.
*/
@SuppressWarnings({ "unused", "NullAway.Init" })
@SuppressWarnings("unused")
private AclImpl() {
}
@@ -201,7 +199,7 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
}
@Override
public boolean isSidLoaded(@Nullable List<Sid> sids) {
public boolean isSidLoaded(List<Sid> sids) {
// If loadedSides is null, this indicates all SIDs were loaded
// Also return true if the caller didn't specify a SID to find
if ((this.loadedSids == null) || (sids == null) || sids.isEmpty()) {
@@ -240,19 +238,19 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
}
@Override
public @Nullable Sid getOwner() {
public Sid getOwner() {
return this.owner;
}
@Override
public void setParent(@Nullable Acl newParent) {
public void setParent(Acl newParent) {
this.aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL);
Assert.isTrue(newParent == null || !newParent.equals(this), "Cannot be the parent of yourself");
this.parentAcl = newParent;
}
@Override
public @Nullable Acl getParentAcl() {
public Acl getParentAcl() {
return this.parentAcl;
}
@@ -42,7 +42,7 @@ public class GrantedAuthoritySid implements Sid {
public GrantedAuthoritySid(GrantedAuthority grantedAuthority) {
Assert.notNull(grantedAuthority, "GrantedAuthority required");
Assert.notNull(grantedAuthority.getAuthority(),
"This Sid is only compatible with GrantedAuthority that provide a non-null getAuthority()");
"This Sid is only compatible with GrantedAuthoritys that provide a non-null getAuthority()");
this.grantedAuthority = grantedAuthority.getAuthority();
}
@@ -18,8 +18,6 @@ package org.springframework.security.acls.domain;
import java.io.Serializable;
import org.jspecify.annotations.Nullable;
import org.springframework.cache.Cache;
import org.springframework.security.acls.model.AclCache;
import org.springframework.security.acls.model.MutableAcl;
@@ -80,13 +78,13 @@ public class SpringCacheBasedAclCache implements AclCache {
}
@Override
public @Nullable MutableAcl getFromCache(ObjectIdentity objectIdentity) {
public MutableAcl getFromCache(ObjectIdentity objectIdentity) {
Assert.notNull(objectIdentity, "ObjectIdentity required");
return getFromCache((Object) objectIdentity);
}
@Override
public @Nullable MutableAcl getFromCache(Serializable pk) {
public MutableAcl getFromCache(Serializable pk) {
Assert.notNull(pk, "Primary key (identifier) required");
return getFromCache((Object) pk);
}
@@ -103,16 +101,12 @@ public class SpringCacheBasedAclCache implements AclCache {
this.cache.put(acl.getId(), acl);
}
private @Nullable MutableAcl getFromCache(Object key) {
private MutableAcl getFromCache(Object key) {
Cache.ValueWrapper element = this.cache.get(key);
if (element == null) {
return null;
}
Object value = element.get();
if (value == null) {
return null;
}
return initializeTransientFields((MutableAcl) value);
return initializeTransientFields((MutableAcl) element.get());
}
private MutableAcl initializeTransientFields(MutableAcl value) {
@@ -17,7 +17,4 @@
/**
* Basic implementation of access control lists (ACLs) interfaces.
*/
@NullMarked
package org.springframework.security.acls.domain;
import org.jspecify.annotations.NullMarked;
@@ -23,7 +23,6 @@ import java.util.UUID;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.core.convert.ConversionFailedException;
import org.springframework.core.convert.ConversionService;
@@ -68,10 +67,10 @@ class AclClassIdUtils {
* @return The identifier in the appropriate target Java type. Typically Long or UUID.
* @throws SQLException
*/
@Nullable Serializable identifierFrom(Serializable identifier, ResultSet resultSet) throws SQLException {
Class<? extends Serializable> classIdType = classIdTypeFrom(resultSet);
if (isString(identifier) && classIdType != null && canConvertFromStringTo(classIdType)) {
return convertFromStringTo((String) identifier, classIdType);
Serializable identifierFrom(Serializable identifier, ResultSet resultSet) throws SQLException {
if (isString(identifier) && hasValidClassIdType(resultSet)
&& canConvertFromStringTo(classIdTypeFrom(resultSet))) {
return convertFromStringTo((String) identifier, classIdTypeFrom(resultSet));
}
// Assume it should be a Long type
return convertToLong(identifier);
@@ -87,38 +86,28 @@ class AclClassIdUtils {
}
}
private @Nullable Class<? extends Serializable> classIdTypeFrom(ResultSet resultSet) throws SQLException {
try {
return classIdTypeFrom(resultSet.getString(DEFAULT_CLASS_ID_TYPE_COLUMN_NAME));
}
catch (SQLException ex) {
log.debug("Unable to obtain the class id type", ex);
return null;
}
private <T extends Serializable> Class<T> classIdTypeFrom(ResultSet resultSet) throws SQLException {
return classIdTypeFrom(resultSet.getString(DEFAULT_CLASS_ID_TYPE_COLUMN_NAME));
}
private @Nullable Class<? extends Serializable> classIdTypeFrom(String className) {
private <T extends Serializable> Class<T> classIdTypeFrom(String className) {
if (className == null) {
return null;
}
try {
return Class.forName(className).asSubclass(Serializable.class);
return (Class) Class.forName(className);
}
catch (ClassNotFoundException ex) {
log.debug("Unable to find class id type on classpath", ex);
return null;
}
catch (ClassCastException ex) {
log.debug("Class id type is not a Serializable type", ex);
return null;
}
}
private <T> boolean canConvertFromStringTo(Class<T> targetType) {
return this.conversionService.canConvert(String.class, targetType);
}
private <T extends Serializable> @Nullable T convertFromStringTo(String identifier, Class<T> targetType) {
private <T extends Serializable> T convertFromStringTo(String identifier, Class<T> targetType) {
return this.conversionService.convert(identifier, targetType);
}
@@ -132,7 +121,7 @@ class AclClassIdUtils {
* exception occurred
* @throws IllegalArgumentException if targetType is null
*/
private @Nullable Long convertToLong(Serializable identifier) {
private Long convertToLong(Serializable identifier) {
if (this.conversionService.canConvert(identifier.getClass(), Long.class)) {
return this.conversionService.convert(identifier, Long.class);
}
@@ -151,10 +140,10 @@ class AclClassIdUtils {
private static class StringToLongConverter implements Converter<String, Long> {
@Override
public Long convert(@Nullable String identifierAsString) {
public Long convert(String identifierAsString) {
if (identifierAsString == null) {
throw new ConversionFailedException(TypeDescriptor.valueOf(String.class),
TypeDescriptor.valueOf(Long.class), identifierAsString, new NullPointerException());
TypeDescriptor.valueOf(Long.class), null, null);
}
return Long.parseLong(identifierAsString);
@@ -165,10 +154,10 @@ class AclClassIdUtils {
private static class StringToUUIDConverter implements Converter<String, UUID> {
@Override
public UUID convert(@Nullable String identifierAsString) {
public UUID convert(String identifierAsString) {
if (identifierAsString == null) {
throw new ConversionFailedException(TypeDescriptor.valueOf(String.class),
TypeDescriptor.valueOf(UUID.class), identifierAsString, new NullPointerException());
TypeDescriptor.valueOf(UUID.class), null, null);
}
return UUID.fromString(identifierAsString);
@@ -31,8 +31,6 @@ import java.util.Set;
import javax.sql.DataSource;
import org.jspecify.annotations.Nullable;
import org.springframework.core.convert.ConversionException;
import org.springframework.core.convert.ConversionService;
import org.springframework.jdbc.core.JdbcTemplate;
@@ -67,11 +65,10 @@ import org.springframework.util.Assert;
* NB: This implementation does attempt to provide reasonably optimised lookups - within
* the constraints of a normalised database and standard ANSI SQL features. If you are
* willing to sacrifice either of these constraints (e.g. use a particular database
* feature such as hierarchical queries or materialized views, or reduce normalisation)
* you are likely to achieve better performance. In such situations you will need to
* provide your own custom <code>LookupStrategy</code>. This class does not support
* subclassing, as it is likely to change in future releases and therefore subclassing is
* unsupported.
* feature such as hierarchical queries or materalized views, or reduce normalisation) you
* are likely to achieve better performance. In such situations you will need to provide
* your own custom <code>LookupStrategy</code>. This class does not support subclassing,
* as it is likely to change in future releases and therefore subclassing is unsupported.
* <p>
* There are two SQL queries executed, one in the <tt>lookupPrimaryKeys</tt> method and
* one in <tt>lookupObjectIdentities</tt>. These are built from the same select and "order
@@ -226,8 +223,7 @@ public class BasicLookupStrategy implements LookupStrategy {
* @param findNow Long-based primary keys to retrieve
* @param sids
*/
private void lookupPrimaryKeys(final Map<Serializable, Acl> acls, final Set<Long> findNow,
final @Nullable List<Sid> sids) {
private void lookupPrimaryKeys(final Map<Serializable, Acl> acls, final Set<Long> findNow, final List<Sid> sids) {
Assert.notNull(acls, "ACLs are required");
Assert.notEmpty(findNow, "Items to find now required");
String sql = computeRepeatingSql(this.lookupPrimaryKeysWhereClause, findNow.size());
@@ -267,7 +263,7 @@ public class BasicLookupStrategy implements LookupStrategy {
* automatically create entries if required)
*/
@Override
public final Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, @Nullable List<Sid> sids) {
public final Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids) {
Assert.isTrue(this.batchSize >= 1, "BatchSize must be >= 1");
Assert.notEmpty(objects, "Objects to lookup required");
// Map<ObjectIdentity,Acl>
@@ -326,7 +322,7 @@ public class BasicLookupStrategy implements LookupStrategy {
* properly-configured parent ACLs.
*/
private Map<ObjectIdentity, Acl> lookupObjectIdentities(final Collection<ObjectIdentity> objectIdentities,
@Nullable List<Sid> sids) {
List<Sid> sids) {
Assert.notEmpty(objectIdentities, "Must provide identities to lookup");
// contains Acls with StubAclParents
@@ -402,10 +398,8 @@ public class BasicLookupStrategy implements LookupStrategy {
}
// Now we have the parent (if there is one), create the true AclImpl
Sid owner = inputAcl.getOwner();
Assert.isTrue(owner != null, "Owner is required");
AclImpl result = new AclImpl(inputAcl.getObjectIdentity(), inputAcl.getId(), this.aclAuthorizationStrategy,
this.grantingStrategy, parent, null, inputAcl.isEntriesInheriting(), owner);
this.grantingStrategy, parent, null, inputAcl.isEntriesInheriting(), inputAcl.getOwner());
// Copy the "aces" from the input to the destination
@@ -511,9 +505,9 @@ public class BasicLookupStrategy implements LookupStrategy {
private final Map<Serializable, Acl> acls;
private final @Nullable List<Sid> sids;
private final List<Sid> sids;
ProcessResultSet(Map<Serializable, Acl> acls, @Nullable List<Sid> sids) {
ProcessResultSet(Map<Serializable, Acl> acls, List<Sid> sids) {
Assert.notNull(acls, "ACLs cannot be null");
this.acls = acls;
this.sids = sids; // can be null
@@ -584,9 +578,6 @@ public class BasicLookupStrategy implements LookupStrategy {
// target id type, e.g. UUID.
Serializable identifier = (Serializable) rs.getObject("object_id_identity");
identifier = BasicLookupStrategy.this.aclClassIdUtils.identifierFrom(identifier, rs);
if (identifier == null) {
throw new IllegalStateException("Identifier cannot be null");
}
ObjectIdentity objectIdentity = BasicLookupStrategy.this.objectIdentityGenerator
.createObjectIdentity(identifier, rs.getString("class"));
@@ -678,7 +669,7 @@ public class BasicLookupStrategy implements LookupStrategy {
}
@Override
public boolean isSidLoaded(@Nullable List<Sid> sids) {
public boolean isSidLoaded(List<Sid> sids) {
throw new UnsupportedOperationException("Stub only");
}
@@ -27,7 +27,6 @@ import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.core.convert.ConversionService;
import org.springframework.jdbc.core.JdbcOperations;
@@ -99,7 +98,7 @@ public class JdbcAclService implements AclService {
}
@Override
public @Nullable List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity) {
public List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity) {
Object[] args = { parentIdentity.getIdentifier().toString(), parentIdentity.getType() };
List<ObjectIdentity> objects = this.jdbcOperations.query(this.findChildrenSql,
(rs, rowNum) -> mapObjectIdentityRow(rs), args);
@@ -110,14 +109,11 @@ public class JdbcAclService implements AclService {
String javaType = rs.getString("class");
Serializable identifier = (Serializable) rs.getObject("obj_id");
identifier = this.aclClassIdUtils.identifierFrom(identifier, rs);
if (identifier == null) {
throw new IllegalStateException("Identifier cannot be null");
}
return this.objectIdentityGenerator.createObjectIdentity(identifier, javaType);
}
@Override
public Acl readAclById(ObjectIdentity object, @Nullable List<Sid> sids) throws NotFoundException {
public Acl readAclById(ObjectIdentity object, List<Sid> sids) throws NotFoundException {
Map<ObjectIdentity, Acl> map = readAclsById(Collections.singletonList(object), sids);
Assert.isTrue(map.containsKey(object),
() -> "There should have been an Acl entry for ObjectIdentity " + object);
@@ -135,7 +131,7 @@ public class JdbcAclService implements AclService {
}
@Override
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, @Nullable List<Sid> sids)
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids)
throws NotFoundException {
Map<ObjectIdentity, Acl> result = this.lookupStrategy.readAclsById(objects, sids);
// Check every requested object identity was found (throw NotFoundException if
@@ -164,7 +160,7 @@ public class JdbcAclService implements AclService {
this.findChildrenSql = DEFAULT_SELECT_ACL_WITH_PARENT_SQL_WITH_CLASS_ID_TYPE;
}
else {
log.debug("Find children statement has already been overridden, so not overriding the default");
log.debug("Find children statement has already been overridden, so not overridding the default");
}
}
}
@@ -22,8 +22,6 @@ import java.util.List;
import javax.sql.DataSource;
import org.jspecify.annotations.Nullable;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.security.acls.domain.AccessControlEntryImpl;
@@ -52,7 +50,7 @@ import org.springframework.util.Assert;
* The default settings are for HSQLDB. If you are using a different database you will
* probably need to set the {@link #setSidIdentityQuery(String) sidIdentityQuery} and
* {@link #setClassIdentityQuery(String) classIdentityQuery} properties appropriately. The
* other queries, SQL inserts and updates can also be customized to accommodate schema
* other queries, SQL inserts and updates can also be customized to accomodate schema
* variations, but must produce results consistent with those expected by the defaults.
* <p>
* See the appendix of the Spring Security reference manual for more information on the
@@ -122,7 +120,6 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
// Need to retrieve the current principal, in order to know who "owns" this ACL
// (can be changed later on)
Authentication auth = this.securityContextHolderStrategy.getContext().getAuthentication();
Assert.isTrue(auth != null, "Authentication required");
PrincipalSid sid = new PrincipalSid(auth);
// Create the acl_object_identity row
@@ -158,12 +155,9 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
Assert.isTrue(entry_ instanceof AccessControlEntryImpl, "Unknown ACE class");
AccessControlEntryImpl entry = (AccessControlEntryImpl) entry_;
Assert.state(acl.getId() != null, "ACL ID cannot be null");
stmt.setLong(1, (Long) acl.getId());
stmt.setInt(2, i);
Long sidPrimaryKey = createOrRetrieveSidPrimaryKey(entry.getSid(), true);
Assert.state(sidPrimaryKey != null, "SID primary key cannot be null");
stmt.setLong(3, sidPrimaryKey);
stmt.setLong(3, createOrRetrieveSidPrimaryKey(entry.getSid(), true));
stmt.setInt(4, entry.getPermission().getMask());
stmt.setBoolean(5, entry.isGranting());
stmt.setBoolean(6, entry.isAuditSuccess());
@@ -195,14 +189,11 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
* @param allowCreate true if creation is permitted if not found
* @return the primary key or null if not found
*/
protected @Nullable Long createOrRetrieveClassPrimaryKey(String type, boolean allowCreate, Class idType) {
List<@Nullable Long> classIds = this.jdbcOperations.queryForList(this.selectClassPrimaryKey, Long.class, type);
protected Long createOrRetrieveClassPrimaryKey(String type, boolean allowCreate, Class idType) {
List<Long> classIds = this.jdbcOperations.queryForList(this.selectClassPrimaryKey, Long.class, type);
if (!classIds.isEmpty()) {
Long result = classIds.get(0);
if (result != null) {
return result;
}
return classIds.get(0);
}
if (allowCreate) {
@@ -213,9 +204,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
this.jdbcOperations.update(this.insertClass, type, idType.getCanonicalName());
}
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running");
Long result = this.jdbcOperations.queryForObject(this.classIdentityQuery, Long.class);
Assert.state(result != null, "Failed to retrieve class primary key");
return result;
return this.jdbcOperations.queryForObject(this.classIdentityQuery, Long.class);
}
return null;
@@ -230,7 +219,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
* @throws IllegalArgumentException if the <tt>Sid</tt> is not a recognized
* implementation.
*/
protected @Nullable Long createOrRetrieveSidPrimaryKey(Sid sid, boolean allowCreate) {
protected Long createOrRetrieveSidPrimaryKey(Sid sid, boolean allowCreate) {
Assert.notNull(sid, "Sid required");
if (sid instanceof PrincipalSid) {
String sidName = ((PrincipalSid) sid).getPrincipal();
@@ -251,22 +240,16 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
* @param allowCreate true if creation is permitted if not found
* @return the primary key or null if not found
*/
protected @Nullable Long createOrRetrieveSidPrimaryKey(String sidName, boolean sidIsPrincipal,
boolean allowCreate) {
List<@Nullable Long> sidIds = this.jdbcOperations.queryForList(this.selectSidPrimaryKey, Long.class,
sidIsPrincipal, sidName);
protected Long createOrRetrieveSidPrimaryKey(String sidName, boolean sidIsPrincipal, boolean allowCreate) {
List<Long> sidIds = this.jdbcOperations.queryForList(this.selectSidPrimaryKey, Long.class, sidIsPrincipal,
sidName);
if (!sidIds.isEmpty()) {
Long result = sidIds.get(0);
if (result != null) {
return result;
}
return sidIds.get(0);
}
if (allowCreate) {
this.jdbcOperations.update(this.insertSid, sidIsPrincipal, sidName);
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running");
Long result = this.jdbcOperations.queryForObject(this.sidIdentityQuery, Long.class);
Assert.state(result != null, "Failed to retrieve sid primary key");
return result;
return this.jdbcOperations.queryForObject(this.sidIdentityQuery, Long.class);
}
return null;
}
@@ -296,9 +279,6 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
}
Long oidPrimaryKey = retrieveObjectIdentityPrimaryKey(objectIdentity);
if (oidPrimaryKey == null) {
throw new NotFoundException("Object identity not found: " + objectIdentity);
}
// Delete this ACL's ACEs in the acl_entry table
deleteEntries(oidPrimaryKey);
@@ -339,11 +319,10 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
* @param oid to find
* @return the object identity or null if not found
*/
protected @Nullable Long retrieveObjectIdentityPrimaryKey(ObjectIdentity oid) {
protected Long retrieveObjectIdentityPrimaryKey(ObjectIdentity oid) {
try {
Long result = this.jdbcOperations.queryForObject(this.selectObjectIdentityPrimaryKey, Long.class,
oid.getType(), oid.getIdentifier().toString());
return result;
return this.jdbcOperations.queryForObject(this.selectObjectIdentityPrimaryKey, Long.class, oid.getType(),
oid.getIdentifier().toString());
}
catch (DataAccessException notFound) {
return null;
@@ -361,11 +340,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
Assert.notNull(acl.getId(), "Object Identity doesn't provide an identifier");
// Delete this ACL's ACEs in the acl_entry table
Long oidPrimaryKey = retrieveObjectIdentityPrimaryKey(acl.getObjectIdentity());
if (oidPrimaryKey == null) {
throw new NotFoundException("Object identity not found for ACL: " + acl.getObjectIdentity());
}
deleteEntries(oidPrimaryKey);
deleteEntries(retrieveObjectIdentityPrimaryKey(acl.getObjectIdentity()));
// Create this ACL's ACEs in the acl_entry table
createEntries(acl);
@@ -496,7 +471,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
this.insertClass = DEFAULT_INSERT_INTO_ACL_CLASS_WITH_ID;
}
else {
log.debug("Insert class statement has already been overridden, so not overriding the default");
log.debug("Insert class statement has already been overridden, so not overridding the default");
}
}
}
@@ -19,8 +19,6 @@ package org.springframework.security.acls.jdbc;
import java.util.List;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.springframework.security.acls.model.Acl;
import org.springframework.security.acls.model.NotFoundException;
import org.springframework.security.acls.model.ObjectIdentity;
@@ -44,6 +42,6 @@ public interface LookupStrategy {
* {@link NotFoundException}, as a chain of {@link LookupStrategy}s may be used to
* automatically create entries if required)
*/
Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, @Nullable List<Sid> sids);
Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids);
}
@@ -17,7 +17,4 @@
/**
* JDBC-based persistence of ACL information
*/
@NullMarked
package org.springframework.security.acls.jdbc;
import org.jspecify.annotations.NullMarked;
@@ -18,8 +18,6 @@ package org.springframework.security.acls.model;
import java.io.Serializable;
import org.jspecify.annotations.Nullable;
/**
* Represents an individual permission assignment within an {@link Acl}.
*
@@ -38,7 +36,7 @@ public interface AccessControlEntry extends Serializable {
* Obtains an identifier that represents this ACE.
* @return the identifier, or <code>null</code> if unsaved
*/
@Nullable Serializable getId();
Serializable getId();
Permission getPermission();
@@ -19,8 +19,6 @@ package org.springframework.security.acls.model;
import java.io.Serializable;
import java.util.List;
import org.jspecify.annotations.Nullable;
/**
* Represents an access control list (ACL) for a domain object.
*
@@ -84,7 +82,7 @@ public interface Acl extends Serializable {
* @return the owner (may be <tt>null</tt> if the implementation does not use
* ownership concepts)
*/
@Nullable Sid getOwner();
Sid getOwner();
/**
* A domain object may have a parent for the purpose of ACL inheritance. If there is a
@@ -105,7 +103,7 @@ public interface Acl extends Serializable {
* @return the parent <tt>Acl</tt> (may be <tt>null</tt> if this <tt>Acl</tt> does not
* have a parent)
*/
@Nullable Acl getParentAcl();
Acl getParentAcl();
/**
* Indicates whether the ACL entries from the {@link #getParentAcl()} should flow down
@@ -191,6 +189,6 @@ public interface Acl extends Serializable {
* @return <tt>true</tt> if every passed <tt>Sid</tt> is represented by this
* <tt>Acl</tt> instance
*/
boolean isSidLoaded(@Nullable List<Sid> sids);
boolean isSidLoaded(List<Sid> sids);
}
@@ -18,8 +18,6 @@ package org.springframework.security.acls.model;
import java.io.Serializable;
import org.jspecify.annotations.Nullable;
import org.springframework.security.acls.jdbc.JdbcAclService;
/**
@@ -33,9 +31,9 @@ public interface AclCache {
void evictFromCache(ObjectIdentity objectIdentity);
@Nullable MutableAcl getFromCache(ObjectIdentity objectIdentity);
MutableAcl getFromCache(ObjectIdentity objectIdentity);
@Nullable MutableAcl getFromCache(Serializable pk);
MutableAcl getFromCache(Serializable pk);
void putInCache(MutableAcl acl);
@@ -19,8 +19,6 @@ package org.springframework.security.acls.model;
import java.util.List;
import java.util.Map;
import org.jspecify.annotations.Nullable;
/**
* Provides retrieval of {@link Acl} instances.
*
@@ -34,7 +32,7 @@ public interface AclService {
* @param parentIdentity to locate children of
* @return the children (or <tt>null</tt> if none were found)
*/
@Nullable List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity);
List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity);
/**
* Same as {@link #readAclsById(List)} except it returns only a single Acl.
@@ -61,7 +59,7 @@ public interface AclService {
* @throws NotFoundException if an {@link Acl} was not found for the requested
* {@link ObjectIdentity}
*/
Acl readAclById(ObjectIdentity object, @Nullable List<Sid> sids) throws NotFoundException;
Acl readAclById(ObjectIdentity object, List<Sid> sids) throws NotFoundException;
/**
* Obtains all the <tt>Acl</tt>s that apply for the passed <tt>Object</tt>s.
@@ -100,7 +98,6 @@ public interface AclService {
* @throws NotFoundException if an {@link Acl} was not found for each requested
* {@link ObjectIdentity}
*/
Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, @Nullable List<Sid> sids)
throws NotFoundException;
Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids) throws NotFoundException;
}
@@ -18,7 +18,4 @@
* Interfaces and shared classes to manage access control lists (ACLs) for domain object
* instances.
*/
@NullMarked
package org.springframework.security.acls.model;
import org.jspecify.annotations.NullMarked;
@@ -24,7 +24,4 @@
* older and more verbose attribute/voter/after-invocation approach from versions before
* Spring Security 3.0.
*/
@NullMarked
package org.springframework.security.acls;
import org.jspecify.annotations.NullMarked;
@@ -1,2 +0,0 @@
org.springframework.aot.hint.RuntimeHintsRegistrar=\
org.springframework.security.acls.aot.hint.AclRuntimeHints
@@ -478,7 +478,6 @@ public class AclImplTests {
}
@Test
@SuppressWarnings("unchecked")
public void hashCodeWithoutStackOverFlow() throws Exception {
Sid sid = new PrincipalSid("pSid");
ObjectIdentity oid = new ObjectIdentityImpl("type", 1);
@@ -29,7 +29,6 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentMatchers;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
@@ -47,6 +46,7 @@ import org.springframework.security.acls.model.Sid;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
@@ -109,8 +109,7 @@ public class JdbcAclServiceTests {
List<ObjectIdentity> result = new ArrayList<>();
result.add(new ObjectIdentityImpl(Object.class, "5577"));
Object[] args = { "1", "org.springframework.security.acls.jdbc.JdbcAclServiceTests$MockLongIdDomainObject" };
given(this.jdbcOperations.query(anyString(), ArgumentMatchers.<RowMapper<ObjectIdentity>>any(), eq(args)))
.willReturn(result);
given(this.jdbcOperations.query(anyString(), any(RowMapper.class), eq(args))).willReturn(result);
ObjectIdentity objectIdentity = new ObjectIdentityImpl(MockLongIdDomainObject.class, 1L);
List<ObjectIdentity> objectIdentities = this.aclService.findChildren(objectIdentity);
assertThat(objectIdentities).hasSize(1);
@@ -80,10 +80,11 @@ public class SpringCacheBasedAclCacheTests {
assertThatIllegalArgumentException().isThrownBy(() -> new SpringCacheBasedAclCache(null, null, null));
}
@SuppressWarnings("rawtypes")
@Test
public void cacheOperationsAclWithoutParent() {
Cache cache = getCache();
Map<?, ?> realCache = (Map<?, ?>) cache.getNativeCache();
Map realCache = (Map) cache.getNativeCache();
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L);
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
@@ -115,10 +116,11 @@ public class SpringCacheBasedAclCacheTests {
assertThat(realCache).isEmpty();
}
@SuppressWarnings("rawtypes")
@Test
public void cacheOperationsAclWithParent() throws Exception {
Cache cache = getCache();
Map<?, ?> realCache = (Map<?, ?>) cache.getNativeCache();
Map realCache = (Map) cache.getNativeCache();
Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL");
auth.setAuthenticated(true);
SecurityContextHolder.getContext().setAuthentication(auth);
+4 -9
View File
@@ -1,16 +1,13 @@
apply plugin: 'io.spring.convention.spring-module'
apply plugin: 'io.freefair.aspectj'
apply plugin: 'compile-warnings-error'
compileAspectj {
sourceCompatibility = "17"
targetCompatibility = "17"
ajcOptions.compilerArgs += ['-Xlint:ignore']
sourceCompatibility "17"
targetCompatibility "17"
}
compileTestAspectj {
sourceCompatibility = "17"
targetCompatibility = "17"
ajcOptions.compilerArgs += ['-Xlint:ignore']
sourceCompatibility "17"
targetCompatibility "17"
}
dependencies {
@@ -21,8 +18,6 @@ dependencies {
api 'org.springframework:spring-context'
api 'org.springframework:spring-core'
optional project(':spring-security-access')
testImplementation 'org.springframework:spring-aop'
testImplementation "org.assertj:assertj-core"
testImplementation "org.junit.jupiter:junit-jupiter-api"
-1
View File
@@ -1,7 +1,6 @@
import io.spring.gradle.convention.SpringModulePlugin
apply plugin: 'io.spring.convention.bom'
apply plugin: 'compile-warnings-error'
dependencies {
constraints {
+36 -11
View File
@@ -1,7 +1,5 @@
import io.spring.gradle.IncludeRepoTask
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import trang.RncToXsd
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
buildscript {
dependencies {
@@ -12,7 +10,7 @@ buildscript {
classpath libs.com.netflix.nebula.nebula.project.plugin
}
repositories {
maven { url='https://plugins.gradle.org/m2/' }
maven { url 'https://plugins.gradle.org/m2/' }
}
}
@@ -37,7 +35,7 @@ ext.milestoneBuild = !(snapshotBuild || releaseBuild)
repositories {
mavenCentral()
maven { url = "https://repo.spring.io/milestone" }
maven { url "https://repo.spring.io/milestone" }
}
springRelease {
@@ -48,19 +46,46 @@ springRelease {
replaceSnapshotVersionInReferenceDocUrl = true
}
def toolchainVersion() {
if (project.hasProperty('testToolchain')) {
return project.property('testToolchain').toString().toInteger()
}
return 17
}
subprojects {
java {
toolchain {
languageVersion = JavaLanguageVersion.of(toolchainVersion())
}
}
kotlin {
jvmToolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
tasks.withType(JavaCompile).configureEach {
options.encoding = "UTF-8"
options.compilerArgs.add("-parameters")
options.release.set(17)
}
}
allprojects {
if (!['spring-security-bom', 'spring-security-docs'].contains(project.name)) {
apply plugin: 'io.spring.javaformat'
apply plugin: 'checkstyle'
pluginManager.withPlugin("io.spring.convention.checkstyle") {
dependencies {
checkstyle libs.io.spring.javaformat.spring.javaformat.checkstyle
pluginManager.withPlugin("io.spring.convention.checkstyle", { plugin ->
configure(plugin) {
dependencies {
checkstyle libs.io.spring.javaformat.spring.javaformat.checkstyle
}
checkstyle {
toolVersion = '8.34'
}
}
checkstyle {
toolVersion = '8.34'
}
}
})
if (project.name.contains('sample')) {
tasks.whenTaskAdded { task ->
+1 -4
View File
@@ -1,6 +1,5 @@
plugins {
id "java-gradle-plugin"
id "groovy-gradle-plugin"
id "java"
id "groovy"
}
@@ -12,7 +11,7 @@ java {
repositories {
gradlePluginPortal()
mavenCentral()
maven { url = 'https://repo.spring.io/snapshot' }
maven { url 'https://repo.spring.io/milestone' }
}
sourceSets {
@@ -64,7 +63,6 @@ configurations {
dependencies {
implementation platform(libs.io.projectreactor.reactor.bom)
implementation libs.spring.nullability
implementation libs.com.google.code.gson.gson
implementation libs.com.thaiopensource.trag
implementation libs.net.sourceforge.saxon.saxon
@@ -78,7 +76,6 @@ dependencies {
implementation libs.com.github.spullara.mustache.java.compiler
implementation libs.io.spring.javaformat.spring.javaformat.gradle.plugin
implementation libs.io.spring.nohttp.nohttp.gradle
implementation libs.org.jetbrains.kotlin.kotlin.gradle.plugin
implementation (libs.net.sourceforge.htmlunit) {
exclude group: 'org.eclipse.jetty.websocket', module: 'websocket-client'
}
@@ -1,10 +0,0 @@
import org.gradle.api.tasks.compile.JavaCompile
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
tasks.withType(JavaCompile) {
options.compilerArgs += "-Werror"
}
tasks.withType(KotlinCompile) {
kotlinOptions.allWarningsAsErrors = true
}
@@ -81,8 +81,8 @@ class ArtifactoryPlugin implements Plugin<Project> {
repository {
repoKey = isSnapshot ? snapshotRepository : isMilestone ? milestoneRepository : releaseRepository
if(project.hasProperty('artifactoryUsername')) {
username = project.artifactoryUsername
password = project.artifactoryPassword
username = artifactoryUsername
password = artifactoryPassword
}
}
}
@@ -31,12 +31,12 @@ public class DocsPlugin implements Plugin<Project> {
into 'api'
}
into 'docs'
duplicatesStrategy = 'exclude'
duplicatesStrategy 'exclude'
}
Task docs = project.tasks.create("docs") {
group = 'Documentation'
description = 'An aggregator task to generate all the documentation'
description 'An aggregator task to generate all the documentation'
dependsOn docsZip
}
project.tasks.assemble.dependsOn docs
@@ -90,7 +90,7 @@ public class IntegrationTestPlugin implements Plugin<Project> {
project.plugins.withType(IdeaPlugin) {
project.idea {
module {
testSources.from(project.file('src/integration-test/java'))
testSourceDirs += project.file('src/integration-test/java')
scopes.TEST.plus += [ project.configurations.integrationTestCompileClasspath ]
}
}
@@ -105,7 +105,7 @@ public class IntegrationTestPlugin implements Plugin<Project> {
project.plugins.withType(IdeaPlugin) {
project.idea {
module {
testSources.from(project.file('src/integration-test/groovy'))
testSourceDirs += project.file('src/integration-test/groovy')
}
}
}
@@ -34,7 +34,7 @@ class JacocoPlugin implements Plugin<Project> {
project.tasks.check.dependsOn project.tasks.jacocoTestReport
project.jacoco {
toolVersion = '0.8.14'
toolVersion = '0.8.9'
}
}
}
@@ -26,7 +26,7 @@ import org.gradle.api.Action;
import org.gradle.api.JavaVersion
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaPluginExtension;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.javadoc.Javadoc;
import org.slf4j.Logger;
@@ -71,7 +71,7 @@ public class JavadocApiPlugin implements Plugin<Project> {
}
api.setMaxMemory("1024m");
api.setDestinationDir(project.layout.getBuildDirectory().dir("api").get().getAsFile());
api.setDestinationDir(new File(project.getBuildDir(), "api"));
project.getPluginManager().apply("io.spring.convention.javadoc-options");
}
@@ -99,7 +99,7 @@ public class JavadocApiPlugin implements Plugin<Project> {
public void execute(SpringModulePlugin plugin) {
logger.info("Added sources for {}", project);
JavaPluginExtension java = project.getExtensions().getByType(JavaPluginExtension.class);
JavaPluginConvention java = project.getConvention().getPlugin(JavaPluginConvention.class);
SourceSet mainSourceSet = java.getSourceSets().getByName("main");
api.setSource(api.getSource().plus(mainSourceSet.getAllJava()));
@@ -61,7 +61,7 @@ public class ManagementConfigurationPlugin implements Plugin<Project> {
PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class);
publishing.getPublications().withType(MavenPublication.class, (mavenPublication -> {
mavenPublication.versionMapping((versions) ->
versions.allVariants((versionMapping) -> versionMapping.fromResolutionResult())
versions.allVariants(versionMapping -> versionMapping.fromResolutionResult())
);
}));
});
@@ -80,11 +80,6 @@ class RepositoryConventionPlugin implements Plugin<Project> {
}
url = 'https://repo.spring.io/release/'
}
forceMavenRepositories.findAll { it.startsWith('https://') || it.startsWith('file://') }.each { mavenUrl ->
maven {
url mavenUrl
}
}
}
}
@@ -32,15 +32,12 @@ public class SchemaZipPlugin implements Plugin<Project> {
for (def key : schemas.keySet()) {
def shortName = key.replaceAll(/http.*schema.(.*).spring-.*/, '$1')
assert shortName != key
def schemaResourceName = schemas.get(key)
File xsdFile = module.sourceSets.main.resources.find {
it.path.endsWith(schemaResourceName)
}
if (xsdFile == null) {
throw new IllegalStateException("Could not find schema file for resource name " + schemaResourceName + " in src/main/resources")
it.path.endsWith(schemas.get(key))
}
assert xsdFile != null
schemaZip.into (shortName) {
duplicatesStrategy = 'exclude'
duplicatesStrategy 'exclude'
from xsdFile.path
}
versionlessXsd.getInputFiles().from(xsdFile.path)
@@ -35,7 +35,6 @@ class SpringModulePlugin extends AbstractSpringJavaPlugin {
pluginManager.apply(SpringMavenPlugin.class);
pluginManager.apply(CheckClasspathForProhibitedDependenciesPlugin.class);
pluginManager.apply("io.spring.convention.jacoco");
pluginManager.apply("java-toolchain");
def deployArtifacts = project.task("deployArtifacts")
deployArtifacts.group = 'Deploy tasks'
@@ -1,36 +0,0 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
def toolchainVersion() {
if (project.hasProperty('testToolchain')) {
return project.property('testToolchain').toString().toInteger()
}
return 25
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(toolchainVersion())
}
}
tasks.withType(JavaCompile).configureEach {
options.encoding = "UTF-8"
options.compilerArgs.add("-parameters")
options.release = 17
}
pluginManager.withPlugin("org.jetbrains.kotlin.jvm") {
kotlin {
jvmToolchain {
languageVersion = JavaLanguageVersion.of(toolchainVersion())
}
}
tasks.withType(KotlinCompile).configureEach {
compilerOptions {
javaParameters = true
jvmTarget.set(JvmTarget.JVM_17)
}
}
}
@@ -1,7 +0,0 @@
import org.gradle.api.tasks.javadoc.Javadoc
project.tasks.withType(Javadoc).configureEach {
options.addBooleanOption('Werror', true)
// temporarily disable missing to get build to pass with JDK 25
options.addStringOption('Xdoclint:all,-missing')
}
@@ -1,17 +0,0 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id 'kotlin'
}
project.plugins.withId("org.jetbrains.kotlin.jvm", (kotlinProject) -> {
project.tasks.withType(KotlinCompile).configureEach {
kotlinOptions {
languageVersion = '2.2'
apiVersion = '2.2'
freeCompilerArgs = ["-Xjsr305=strict", "-Xsuppress-version-warnings"]
jvmTarget = '17'
}
}
})
@@ -1,3 +0,0 @@
plugins {
id 'io.spring.nullability'
}
@@ -1,30 +0,0 @@
import org.gradle.api.tasks.compile.JavaCompile
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
/**
* We need to compile with JDK 25 for nullability support, but using JDK 25 means that our tests will fail due to the
* <a href="https://docs.oracle.com/en/java/javase/25/security/security-manager-is-permanently-disabled.html">removal
* of the Java Security Manager</a>. For example, in JDK 25 {@code Subject.getSubject(AccessControlContext)} throws an
* {@code UnsupportedOperationException}.
*
* To resolve this, we must migrate tests to use the new APIs (e.g. {@code Subject.current()}) but those APIs are not
* available in the JDK 17 source, so compiling with JDK 25 and release 17 fails. The plugin overrides the test
* compilation to use release 25.
*
* @see <a href="https://docs.oracle.com/en/java/javase/25/security/security-manager-is-permanently-disabled.html">The
* Security Manager Is Permanently Disabled</a>
* @see <a href="https://inside.java/2024/07/08/quality-heads-up/">Quality Outreach Heads-up - JDK 23: Re-Specified
* Subject.getSubject API</a>
*/
tasks.withType(JavaCompile).configureEach { task ->
if (task.name == 'compileTestJava' || task.name == 'compileIntegrationTestJava') {
task.options.release.set(25)
}
}
tasks.withType(KotlinCompile).configureEach { task ->
if (task.name == 'compileTestKotlin' || task.name == 'compileIntegrationTestKotlin') {
task.kotlinOptions.jvmTarget = '25'
}
}
@@ -81,6 +81,9 @@ public class CheckClasspathForProhibitedDependencies extends DefaultTask {
if (group.startsWith("javax")) {
return true;
}
if (group.equals("commons-logging")) {
return true;
}
if (group.equals("org.slf4j") && id.getName().equals("jcl-over-slf4j")) {
return true;
}
@@ -46,7 +46,7 @@ public class CheckExpectedBranchVersionPlugin implements Plugin<Project> {
task.setDescription("Check if the project version matches the branch version");
task.onlyIf("skipCheckExpectedBranchVersion property is false or not present", CheckExpectedBranchVersionPlugin::skipPropertyFalseOrNotPresent);
task.getVersion().convention(project.provider(() -> project.getVersion().toString()));
task.getBranchName().convention(project.getProviders().exec((execSpec) -> execSpec.setCommandLine("git", "symbolic-ref", "--short", "HEAD")).getStandardOutput().getAsText());
task.getBranchName().convention(project.getProviders().exec(execSpec -> execSpec.setCommandLine("git", "symbolic-ref", "--short", "HEAD")).getStandardOutput().getAsText());
task.getOutputFile().convention(project.getLayout().getBuildDirectory().file("check-expected-branch-version"));
});
project.getTasks().named(JavaBasePlugin.CHECK_TASK_NAME, checkTask -> checkTask.dependsOn(checkExpectedBranchVersionTask));
@@ -83,8 +83,12 @@ public class VerifyDependenciesVersionsPlugin implements Plugin<Project> {
String transitiveNimbusJoseJwtVersion = TransitiveDependencyLookupUtils.lookupJwtVersion(oauth2OidcSdkVersion);
String expectedNimbusJoseJwtVersion = this.getExpectedNimbusJoseJwtVersion().get();
if (!transitiveNimbusJoseJwtVersion.equals(expectedNimbusJoseJwtVersion)) {
String message = String.format("Found transitive nimbus-jose-jwt:%s in oauth2-oidc-sdk:%s, but the project contains a different version of nimbus-jose-jwt [%s]. Please align the versions.", transitiveNimbusJoseJwtVersion, oauth2OidcSdkVersion, expectedNimbusJoseJwtVersion);
throw new VerificationException(message);
String transitiveNimbusJoseJwtMajorMinorVersion = transitiveNimbusJoseJwtVersion.substring(0, transitiveNimbusJoseJwtVersion.lastIndexOf("."));
String expectedNimbusJoseJwtMajorMinorVersion = expectedNimbusJoseJwtVersion.substring(0, expectedNimbusJoseJwtVersion.lastIndexOf("."));
if (!transitiveNimbusJoseJwtMajorMinorVersion.equals(expectedNimbusJoseJwtMajorMinorVersion)) {
String message = String.format("Found transitive nimbus-jose-jwt:%s in oauth2-oidc-sdk:%s, but the project contains a different version of nimbus-jose-jwt [%s]. Please align the major/minor versions.", transitiveNimbusJoseJwtVersion, oauth2OidcSdkVersion, expectedNimbusJoseJwtVersion);
throw new VerificationException(message);
}
}
String message = String.format("Found transitive nimbus-jose-jwt:%s in oauth2-oidc-sdk:%s, the project contains expected version of nimbus-jose-jwt [%s]. Verified all versions align.", transitiveNimbusJoseJwtVersion, oauth2OidcSdkVersion, expectedNimbusJoseJwtVersion);
try {
@@ -17,6 +17,8 @@ package io.spring.gradle;
import org.apache.commons.io.FileUtils;
import org.gradle.testkit.runner.GradleRunner;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import java.io.File;
import java.io.IOException;
@@ -23,6 +23,8 @@ import org.gradle.testfixtures.ProjectBuilder;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import java.io.File;
import static org.assertj.core.api.Assertions.assertThat;
/**
@@ -5,6 +5,7 @@ import org.apache.commons.io.FileUtils;
import org.gradle.testkit.runner.BuildResult;
import org.gradle.testkit.runner.TaskOutcome;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
-8
View File
@@ -1,9 +1,3 @@
plugins {
id 'security-nullability'
id 'javadoc-warnings-error'
id 'compile-warnings-error'
}
apply plugin: 'io.spring.convention.spring-module'
dependencies {
@@ -17,11 +11,9 @@ dependencies {
api 'org.springframework:spring-web'
optional 'com.fasterxml.jackson.core:jackson-databind'
optional 'tools.jackson.core:jackson-databind'
provided 'jakarta.servlet:jakarta.servlet-api'
testImplementation project(path : ':spring-security-web', configuration : 'tests')
testImplementation "org.assertj:assertj-core"
testImplementation "org.junit.jupiter:junit-jupiter-api"
testImplementation "org.junit.jupiter:junit-jupiter-params"
@@ -16,8 +16,6 @@
package org.springframework.security.cas;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
@@ -36,7 +34,7 @@ public class ServiceProperties implements InitializingBean {
public static final String DEFAULT_CAS_SERVICE_PARAMETER = "service";
private @Nullable String service;
private String service;
private boolean authenticateAllArtifacts;
@@ -64,7 +62,7 @@ public class ServiceProperties implements InitializingBean {
* </pre>
* @return the URL of the service the user is authenticating to
*/
public final @Nullable String getService() {
public final String getService() {
return this.service;
}
@@ -21,6 +21,7 @@ import java.util.ArrayList;
import org.apereo.cas.client.validation.Assertion;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.SpringSecurityCoreVersion;
/**
* Temporary authentication object needed to load the user details service.
@@ -30,7 +31,7 @@ import org.springframework.security.authentication.AbstractAuthenticationToken;
*/
public final class CasAssertionAuthenticationToken extends AbstractAuthenticationToken {
private static final long serialVersionUID = 620L;
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
private final Assertion assertion;
@@ -16,15 +16,11 @@
package org.springframework.security.cas.authentication;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apereo.cas.client.validation.Assertion;
import org.apereo.cas.client.validation.TicketValidationException;
import org.apereo.cas.client.validation.TicketValidator;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.MessageSource;
@@ -37,9 +33,7 @@ import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.cas.ServiceProperties;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityMessageSource;
import org.springframework.security.core.authority.FactorGrantedAuthority;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
@@ -68,9 +62,6 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
private static final Log logger = LogFactory.getLog(CasAuthenticationProvider.class);
private static final String AUTHORITY = FactorGrantedAuthority.CAS_AUTHORITY;
@SuppressWarnings("NullAway.Init")
private AuthenticationUserDetailsService<CasAssertionAuthenticationToken> authenticationUserDetailsService;
private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker();
@@ -79,13 +70,11 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
private StatelessTicketCache statelessTicketCache = new NullStatelessTicketCache();
@SuppressWarnings("NullAway.Init")
private String key;
@SuppressWarnings("NullAway.Init")
private TicketValidator ticketValidator;
private @Nullable ServiceProperties serviceProperties;
private ServiceProperties serviceProperties;
private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();
@@ -100,7 +89,7 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
}
@Override
public @Nullable Authentication authenticate(Authentication authentication) throws AuthenticationException {
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
if (!supports(authentication.getClass())) {
return null;
}
@@ -140,17 +129,12 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
private CasAuthenticationToken authenticateNow(final Authentication authentication) throws AuthenticationException {
try {
Object credentials = authentication.getCredentials();
if (credentials == null) {
throw new BadCredentialsException("Authentication.getCredentials() cannot be null");
}
Assertion assertion = this.ticketValidator.validate(credentials.toString(), getServiceUrl(authentication));
Assertion assertion = this.ticketValidator.validate(authentication.getCredentials().toString(),
getServiceUrl(authentication));
UserDetails userDetails = loadUserByAssertion(assertion);
this.userDetailsChecker.check(userDetails);
Collection<GrantedAuthority> authorities = new ArrayList<>(
this.authoritiesMapper.mapAuthorities(userDetails.getAuthorities()));
authorities.add(FactorGrantedAuthority.fromAuthority(AUTHORITY));
return new CasAuthenticationToken(this.key, userDetails, credentials, authorities, userDetails, assertion);
return new CasAuthenticationToken(this.key, userDetails, authentication.getCredentials(),
this.authoritiesMapper.mapAuthorities(userDetails.getAuthorities()), userDetails, assertion);
}
catch (TicketValidationException ex) {
throw new BadCredentialsException(ex.getMessage(), ex);
@@ -165,7 +149,7 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
* @param authentication
* @return
*/
private @Nullable String getServiceUrl(Authentication authentication) {
private String getServiceUrl(Authentication authentication) {
String serviceUrl;
if (authentication.getDetails() instanceof ServiceAuthenticationDetails) {
return ((ServiceAuthenticationDetails) authentication.getDetails()).getServiceUrl();
@@ -231,7 +215,7 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
return this.statelessTicketCache;
}
protected @Nullable TicketValidator getTicketValidator() {
protected TicketValidator getTicketValidator() {
return this.ticketValidator;
}
@@ -20,10 +20,10 @@ import java.io.Serializable;
import java.util.Collection;
import org.apereo.cas.client.validation.Assertion;
import org.jspecify.annotations.Nullable;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityCoreVersion;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
@@ -36,7 +36,7 @@ import org.springframework.util.ObjectUtils;
*/
public class CasAuthenticationToken extends AbstractAuthenticationToken implements Serializable {
private static final long serialVersionUID = 620L;
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
private final Object credentials;
@@ -105,19 +105,6 @@ public class CasAuthenticationToken extends AbstractAuthenticationToken implemen
setAuthenticated(true);
}
protected CasAuthenticationToken(Builder<?> builder) {
super(builder);
Assert.isTrue(!"".equals(builder.principal), "principal cannot be null or empty");
Assert.notNull(!"".equals(builder.credentials), "credentials cannot be null or empty");
Assert.notNull(builder.userDetails, "userDetails cannot be null");
Assert.notNull(builder.assertion, "assertion cannot be null");
this.keyHash = builder.keyHash;
this.principal = builder.principal;
this.credentials = builder.credentials;
this.userDetails = builder.userDetails;
this.assertion = builder.assertion;
}
private static Integer extractKeyHash(String key) {
Assert.hasLength(key, "key cannot be null or empty");
return key.hashCode();
@@ -167,11 +154,6 @@ public class CasAuthenticationToken extends AbstractAuthenticationToken implemen
return this.userDetails;
}
@Override
public Builder<?> toBuilder() {
return new Builder<>(this);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
@@ -181,81 +163,4 @@ public class CasAuthenticationToken extends AbstractAuthenticationToken implemen
return (sb.toString());
}
/**
* A builder of {@link CasAuthenticationToken} instances
*
* @since 7.0
*/
public static class Builder<B extends Builder<B>> extends AbstractAuthenticationBuilder<B> {
private Integer keyHash;
private Object principal;
private Object credentials;
private UserDetails userDetails;
private Assertion assertion;
protected Builder(CasAuthenticationToken token) {
super(token);
this.keyHash = token.keyHash;
this.principal = token.principal;
this.credentials = token.credentials;
this.userDetails = token.userDetails;
this.assertion = token.assertion;
}
/**
* Use this key
* @param key the key to use
* @return the {@link Builder} for further configurations
*/
public B key(String key) {
this.keyHash = key.hashCode();
return (B) this;
}
@Override
public B principal(@Nullable Object principal) {
Assert.notNull(principal, "principal cannot be null");
this.principal = principal;
return (B) this;
}
@Override
public B credentials(@Nullable Object credentials) {
Assert.notNull(credentials, "credentials cannot be null");
this.credentials = credentials;
return (B) this;
}
/**
* Use this {@link UserDetails}
* @param userDetails the {@link UserDetails} to use
* @return the {@link Builder} for further configurations
*/
public B userDetails(UserDetails userDetails) {
this.userDetails = userDetails;
return (B) this;
}
/**
* Use this {@link Assertion}
* @param assertion the {@link Assertion} to use
* @return the {@link Builder} for further configurations
*/
public B assertion(Assertion assertion) {
this.assertion = assertion;
return (B) this;
}
@Override
public CasAuthenticationToken build() {
return new CasAuthenticationToken(this);
}
}
}
@@ -19,10 +19,9 @@ package org.springframework.security.cas.authentication;
import java.io.Serial;
import java.util.Collection;
import org.jspecify.annotations.Nullable;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityCoreVersion;
import org.springframework.util.Assert;
/**
@@ -39,11 +38,11 @@ public class CasServiceTicketAuthenticationToken extends AbstractAuthenticationT
static final String CAS_STATEFUL_IDENTIFIER = "_cas_stateful_";
@Serial
private static final long serialVersionUID = 620L;
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
private final String identifier;
private @Nullable Object credentials;
private Object credentials;
/**
* This constructor can be safely used by any code that wishes to create a
@@ -52,7 +51,7 @@ public class CasServiceTicketAuthenticationToken extends AbstractAuthenticationT
*
*/
public CasServiceTicketAuthenticationToken(String identifier, Object credentials) {
super((Collection<? extends GrantedAuthority>) null);
super(null);
this.identifier = identifier;
this.credentials = credentials;
setAuthenticated(false);
@@ -75,12 +74,6 @@ public class CasServiceTicketAuthenticationToken extends AbstractAuthenticationT
super.setAuthenticated(true);
}
protected CasServiceTicketAuthenticationToken(Builder<?> builder) {
super(builder);
this.identifier = builder.principal;
this.credentials = builder.credentials;
}
public static CasServiceTicketAuthenticationToken stateful(Object credentials) {
return new CasServiceTicketAuthenticationToken(CAS_STATEFUL_IDENTIFIER, credentials);
}
@@ -94,7 +87,7 @@ public class CasServiceTicketAuthenticationToken extends AbstractAuthenticationT
}
@Override
public @Nullable Object getCredentials() {
public Object getCredentials() {
return this.credentials;
}
@@ -116,46 +109,4 @@ public class CasServiceTicketAuthenticationToken extends AbstractAuthenticationT
this.credentials = null;
}
public Builder<?> toBuilder() {
return new Builder<>(this);
}
/**
* A builder of {@link CasServiceTicketAuthenticationToken} instances
*
* @since 7.0
*/
public static class Builder<B extends Builder<B>> extends AbstractAuthenticationBuilder<B> {
private String principal;
private @Nullable Object credentials;
protected Builder(CasServiceTicketAuthenticationToken token) {
super(token);
this.principal = token.identifier;
this.credentials = token.credentials;
}
@Override
public B principal(@Nullable Object principal) {
Assert.isInstanceOf(String.class, principal, "principal must be of type String");
this.principal = (String) principal;
return (B) this;
}
@Override
public B credentials(@Nullable Object credentials) {
Assert.notNull(credentials, "credentials cannot be null");
this.credentials = credentials;
return (B) this;
}
@Override
public CasServiceTicketAuthenticationToken build() {
return new CasServiceTicketAuthenticationToken(this);
}
}
}
@@ -16,8 +16,6 @@
package org.springframework.security.cas.authentication;
import org.jspecify.annotations.Nullable;
/**
* Implementation of @link {@link StatelessTicketCache} that has no backing cache. Useful
* in instances where storing of tickets for stateless session management is not required.
@@ -35,7 +33,7 @@ public final class NullStatelessTicketCache implements StatelessTicketCache {
* @return null since we are not storing any tickets.
*/
@Override
public @Nullable CasAuthenticationToken getByTicketId(final String serviceTicket) {
public CasAuthenticationToken getByTicketId(final String serviceTicket) {
return null;
}
@@ -18,7 +18,6 @@ package org.springframework.security.cas.authentication;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.cache.Cache;
import org.springframework.core.log.LogMessage;
@@ -43,7 +42,7 @@ public class SpringCacheBasedTicketCache implements StatelessTicketCache {
}
@Override
public @Nullable CasAuthenticationToken getByTicketId(final String serviceTicket) {
public CasAuthenticationToken getByTicketId(final String serviceTicket) {
final Cache.ValueWrapper element = (serviceTicket != null) ? this.cache.get(serviceTicket) : null;
logger.debug(LogMessage.of(() -> "Cache hit: " + (element != null) + "; service ticket: " + serviceTicket));
return (element != null) ? (CasAuthenticationToken) element.get() : null;
@@ -16,8 +16,6 @@
package org.springframework.security.cas.authentication;
import org.jspecify.annotations.Nullable;
/**
* Caches CAS service tickets and CAS proxy tickets for stateless connections.
*
@@ -71,7 +69,7 @@ public interface StatelessTicketCache {
* </p>
* @return the fully populated authentication token
*/
@Nullable CasAuthenticationToken getByTicketId(String serviceTicket);
CasAuthenticationToken getByTicketId(String serviceTicket);
/**
* Adds the specified <code>CasAuthenticationToken</code> to the cache.
@@ -18,7 +18,4 @@
* An {@code AuthenticationProvider} that can process CAS service tickets and proxy
* tickets.
*/
@NullMarked
package org.springframework.security.cas.authentication;
import org.jspecify.annotations.NullMarked;
@@ -1,60 +0,0 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.cas.jackson;
import java.util.Date;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import org.apereo.cas.client.authentication.AttributePrincipal;
/**
* Helps in jackson deserialization of class
* {@link org.apereo.cas.client.validation.AssertionImpl}, which is used with
* {@link org.springframework.security.cas.authentication.CasAuthenticationToken}.
*
* @author Sebastien Deleuze
* @author Jitendra Singh
* @since 7.0
* @see CasJacksonModule
* @see org.springframework.security.jackson.SecurityJacksonModules
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
class AssertionImplMixin {
/**
* Mixin Constructor helps in deserialize
* {@link org.apereo.cas.client.validation.AssertionImpl}
* @param principal the Principal to associate with the Assertion.
* @param validFromDate when the assertion is valid from.
* @param validUntilDate when the assertion is valid to.
* @param authenticationDate when the assertion is authenticated.
* @param attributes the key/value pairs for this attribute.
*/
@JsonCreator
AssertionImplMixin(@JsonProperty("principal") AttributePrincipal principal,
@JsonProperty("validFromDate") Date validFromDate, @JsonProperty("validUntilDate") Date validUntilDate,
@JsonProperty("authenticationDate") Date authenticationDate,
@JsonProperty("attributes") Map<String, Object> attributes) {
}
}
@@ -1,59 +0,0 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.cas.jackson;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import org.apereo.cas.client.proxy.ProxyRetriever;
/**
* Helps in deserialize
* {@link org.apereo.cas.client.authentication.AttributePrincipalImpl} which is used with
* {@link org.springframework.security.cas.authentication.CasAuthenticationToken}.
*
* @author Sebastien Deleuze
* @author Jitendra Singh
* @since 7.0
* @see CasJacksonModule
* @see org.springframework.security.jackson.SecurityJacksonModules
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
class AttributePrincipalImplMixin {
/**
* Mixin Constructor helps in deserialize
* {@link org.apereo.cas.client.authentication.AttributePrincipalImpl}
* @param name the unique identifier for the principal.
* @param attributes the key/value pairs for this principal.
* @param proxyGrantingTicket the ticket associated with this principal.
* @param proxyRetriever the ProxyRetriever implementation to call back to the CAS
* server.
*/
@JsonCreator
AttributePrincipalImplMixin(@JsonProperty("name") String name,
@JsonProperty("attributes") Map<String, Object> attributes,
@JsonProperty("proxyGrantingTicket") String proxyGrantingTicket,
@JsonProperty("proxyRetriever") ProxyRetriever proxyRetriever) {
}
}
@@ -1,69 +0,0 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.cas.jackson;
import java.util.Collection;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import org.apereo.cas.client.validation.Assertion;
import org.springframework.security.cas.authentication.CasAuthenticationProvider;
import org.springframework.security.cas.authentication.CasAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
/**
* Mixin class which helps in deserialize {@link CasAuthenticationToken} using jackson.
*
* @author Sebastien Deleuze
* @author Jitendra Singh
* @since 7.0
* @see CasJacksonModule
* @see org.springframework.security.jackson.SecurityJacksonModules
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, isGetterVisibility = JsonAutoDetect.Visibility.NONE,
getterVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.ANY)
class CasAuthenticationTokenMixin {
/**
* Mixin Constructor helps in deserialize {@link CasAuthenticationToken}
* @param keyHash hashCode of provided key to identify if this object made by a given
* {@link CasAuthenticationProvider}
* @param principal typically the UserDetails object (cannot be <code>null</code>)
* @param credentials the service/proxy ticket ID from CAS (cannot be
* <code>null</code>)
* @param authorities the authorities granted to the user (from the
* {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot
* be <code>null</code>)
* @param userDetails the user details (from the
* {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot
* be <code>null</code>)
* @param assertion the assertion returned from the CAS servers. It contains the
* principal and how to obtain a proxy ticket for the user.
*/
@JsonCreator
CasAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, @JsonProperty("principal") Object principal,
@JsonProperty("credentials") Object credentials,
@JsonProperty("authorities") Collection<? extends GrantedAuthority> authorities,
@JsonProperty("userDetails") UserDetails userDetails, @JsonProperty("assertion") Assertion assertion) {
}
}
@@ -1,71 +0,0 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.cas.jackson;
import org.apereo.cas.client.authentication.AttributePrincipalImpl;
import org.apereo.cas.client.validation.AssertionImpl;
import tools.jackson.core.Version;
import tools.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
import org.springframework.security.cas.authentication.CasAuthenticationToken;
import org.springframework.security.jackson.SecurityJacksonModule;
import org.springframework.security.jackson.SecurityJacksonModules;
/**
* Jackson module for spring-security-cas. This module register
* {@link AssertionImplMixin}, {@link AttributePrincipalImplMixin} and
* {@link CasAuthenticationTokenMixin}. If no default typing enabled by default then it'll
* enable it because typing info is needed to properly serialize/deserialize objects. In
* order to use this module just add this module into your JsonMapper configuration.
*
* <p>
* The recommended way to configure it is to use {@link SecurityJacksonModules} in order
* to enable properly automatic inclusion of type information with related validation.
*
* <pre>
* ClassLoader loader = getClass().getClassLoader();
* JsonMapper mapper = JsonMapper.builder()
* .addModules(SecurityJacksonModules.getModules(loader))
* .build();
* </pre>
*
* @author Sebastien Deleuze
* @author Jitendra Singh
* @since 7.0
* @see SecurityJacksonModules
*/
public class CasJacksonModule extends SecurityJacksonModule {
public CasJacksonModule() {
super(CasJacksonModule.class.getName(), new Version(1, 0, 0, null, null, null));
}
@Override
public void configurePolymorphicTypeValidator(BasicPolymorphicTypeValidator.Builder builder) {
builder.allowIfSubType(AssertionImpl.class)
.allowIfSubType(AttributePrincipalImpl.class)
.allowIfSubType(CasAuthenticationToken.class);
}
@Override
public void setupModule(SetupContext context) {
context.setMixIn(AssertionImpl.class, AssertionImplMixin.class);
context.setMixIn(AttributePrincipalImpl.class, AttributePrincipalImplMixin.class);
context.setMixIn(CasAuthenticationToken.class, CasAuthenticationTokenMixin.class);
}
}
@@ -1,23 +0,0 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Jackson 3+ serialization support for CAS.
*/
@NullMarked
package org.springframework.security.cas.jackson;
import org.jspecify.annotations.NullMarked;

Some files were not shown because too many files have changed in this diff Show More