Compare commits
155 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3fbcd5f62a | |||
| edc8735eb8 | |||
| cae3467a8d | |||
| bf2aaa1b18 | |||
| 3690517395 | |||
| d0e9128db5 | |||
| 1864c876d1 | |||
| a17b2a18d9 | |||
| 16c979460e | |||
| ce08aa49f7 | |||
| 0cbc38cdd6 | |||
| e5d62e0bdd | |||
| 70c940fd4f | |||
| eb30fd7f59 | |||
| fbdf4a88a0 | |||
| 260d298cc5 | |||
| b38cf1fc16 | |||
| 5a2bd2b825 | |||
| 91afd49faf | |||
| 78a60d0d84 | |||
| d34fd236f6 | |||
| ad934efc24 | |||
| 11eac05dfd | |||
| 3a36197d7a | |||
| a001f27690 | |||
| 5ba4ab5e11 | |||
| 27319e3f9b | |||
| ec462e8bc5 | |||
| 8fcf181ff0 | |||
| dd0b26a992 | |||
| a4111a606b | |||
| 63d79a97db | |||
| 505fe3abed | |||
| 0220e471bb | |||
| c3c2bcd6b7 | |||
| 39fdceab59 | |||
| 65d53beff8 | |||
| 34afa64c0c | |||
| b5e1c3770b | |||
| 9710492619 | |||
| 6dc8cd1f60 | |||
| 9436796973 | |||
| 92160fa26f | |||
| 51239359ed | |||
| 57fc29e614 | |||
| e48f26e51e | |||
| a26a64d213 | |||
| 3b7e3a6c5c | |||
| fa533ea5e2 | |||
| a04025c114 | |||
| 99cede5e08 | |||
| 1564076276 | |||
| 389ba794fa | |||
| ae09f36291 | |||
| c4a0dfe838 | |||
| bcef6ed74f | |||
| d02a9a3c46 | |||
| c8581683da | |||
| a4126aa27d | |||
| f631a0fcd5 | |||
| 656ad72608 | |||
| 0e84f31a00 | |||
| d76ccc6856 | |||
| 9c76ab69f0 | |||
| 868342b3a9 | |||
| ce000ed190 | |||
| 5354e4d2c5 | |||
| e6957bb854 | |||
| db48d4ca50 | |||
| 547d174f3e | |||
| d2d1275b39 | |||
| 54cd987dbc | |||
| 9495a332bc | |||
| 7bf776ec38 | |||
| 1ccd600a18 | |||
| 7a302a9eb8 | |||
| e47a6714a5 | |||
| a4d7ac24c8 | |||
| b9cae82b89 | |||
| e8aef09b4f | |||
| f6354250a1 | |||
| f8d417dc03 | |||
| 79bacf8204 | |||
| 9bcfeab1d6 | |||
| 254c9c9b2d | |||
| a5d963387b | |||
| e5d9659b8f | |||
| 99c4f58c34 | |||
| cb60d8b3ed | |||
| c1aa99fdd2 | |||
| f1a211ae0c | |||
| a1481572ed | |||
| eb01394427 | |||
| 0ff3474e2d | |||
| 2ce4aecec7 | |||
| 7c90300912 | |||
| 0d3d6f75f8 | |||
| a10a35c2ac | |||
| ee13d19503 | |||
| eb83c35ded | |||
| db34de59bc | |||
| 3c0fef59b5 | |||
| da94fbe431 | |||
| a081402383 | |||
| f3c8262a00 | |||
| 0954638d57 | |||
| 857ef6fe08 | |||
| 55815103a5 | |||
| 26c63aeb01 | |||
| b7df86197c | |||
| c84c438075 | |||
| 1ad4323cec | |||
| 1e7db094d1 | |||
| 6c5b6d1c51 | |||
| 456604ab45 | |||
| 15b9a50060 | |||
| fcc1bd598d | |||
| 1f3dd53bdf | |||
| a6b5c05da9 | |||
| 9c054474a8 | |||
| 593f7c4490 | |||
| 4e20d56d2d | |||
| 26aa253633 | |||
| af2668f7cb | |||
| 0a084135ec | |||
| 5571ad1b27 | |||
| e3a715b8f5 | |||
| 2f04512e01 | |||
| 23444dd13f | |||
| 883765b2de | |||
| c032b20178 | |||
| 58e7ba4a4b | |||
| db8b6322e2 | |||
| 72554f7f36 | |||
| af8786150e | |||
| 65e83f8e7a | |||
| 96cfbd1e6c | |||
| ab6e9d2d1f | |||
| a53ca7c3d0 | |||
| af40d7e35a | |||
| daf8cfe8d2 | |||
| 75b537f99a | |||
| 55d61224e5 | |||
| d1b7f8a119 | |||
| 85c906290d | |||
| 68f08c26d0 | |||
| 5353d499b4 | |||
| 60df37b026 | |||
| d9a937f0c1 | |||
| 06893bc047 | |||
| 1d75b907f9 | |||
| 7dbd69fee1 | |||
| 816f3cd64d | |||
| 147081f771 | |||
| 0bc9313fdd |
@@ -1,40 +0,0 @@
|
||||
version: 2
|
||||
|
||||
registries:
|
||||
spring-milestones:
|
||||
type: maven-repository
|
||||
url: https://repo.spring.io/milestone
|
||||
|
||||
updates:
|
||||
|
||||
- package-ecosystem: "gradle"
|
||||
target-branch: "main"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
time: "03:00"
|
||||
timezone: "Etc/UTC"
|
||||
labels: [ "type: dependency-upgrade" ]
|
||||
registries:
|
||||
- "spring-milestones"
|
||||
ignore:
|
||||
- dependency-name: "com.nimbusds:nimbus-jose-jwt" # nimbus-jose-jwt gets updated when oauth2-oidc-sdk is updated to ensure consistency
|
||||
- dependency-name: "org.python:jython" # jython updates break integration tests
|
||||
- dependency-name: "org.apache.directory.server:*" # ApacheDS version > 1.5.5 contains break changes
|
||||
- dependency-name: "org.junit:junit-bom"
|
||||
update-types: [ "version-update:semver-major" ]
|
||||
- dependency-name: "org.mockito:mockito-bom"
|
||||
update-types: [ "version-update:semver-major" ]
|
||||
- dependency-name: "*"
|
||||
update-types: [ "version-update:semver-major", "version-update:semver-minor" ]
|
||||
|
||||
# GitHub Actions
|
||||
|
||||
- package-ecosystem: github-actions
|
||||
target-branch: "main"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
ignore:
|
||||
- dependency-name: "spring-io/*"
|
||||
- dependency-name: "spring-security-release-tools/*"
|
||||
@@ -0,0 +1,80 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL Advanced"
|
||||
|
||||
on:
|
||||
push: # run if we update the workflow
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '39 13 * * 4'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze (${{ matrix.language }})
|
||||
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
||||
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
||||
# - https://gh.io/supported-runners-and-hardware-resources
|
||||
# - https://gh.io/using-larger-runners (GitHub.com only)
|
||||
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# required for all workflows
|
||||
security-events: write
|
||||
|
||||
# required to fetch internal or private CodeQL packs
|
||||
packages: read
|
||||
|
||||
# only required for workflows in private repositories
|
||||
actions: read
|
||||
contents: read
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- language: actions
|
||||
build-mode: none
|
||||
# CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
|
||||
# Use `c-cpp` to analyze code written in C, C++ or both
|
||||
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
|
||||
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
|
||||
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
|
||||
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
|
||||
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
|
||||
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Add any setup steps before running the `github/codeql-action/init` action.
|
||||
# This includes steps like installing compilers or runtimes (`actions/setup-node`
|
||||
# or others). This is typically only required for manual builds.
|
||||
# - name: Setup runtime (example)
|
||||
# uses: actions/setup-example@v1
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
build-mode: ${{ matrix.build-mode }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
queries: security-extended,security-and-quality
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
@@ -1,57 +0,0 @@
|
||||
name: Auto Merge Forward Dependabot Commits
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: dependabot-auto-merge-forward
|
||||
|
||||
jobs:
|
||||
get-supported-branches:
|
||||
uses: spring-io/spring-security-release-tools/.github/workflows/retrieve-spring-supported-versions.yml@actions-v1
|
||||
with:
|
||||
project: spring-security
|
||||
type: oss
|
||||
repository_name: spring-projects/spring-security
|
||||
|
||||
auto-merge-forward-dependabot:
|
||||
name: Auto Merge Forward Dependabot Commits
|
||||
runs-on: ubuntu-latest
|
||||
needs: [get-supported-branches]
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Checkout
|
||||
id: checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.GH_ACTIONS_REPO_TOKEN }}
|
||||
- name: Setup GitHub User
|
||||
id: setup-gh-user
|
||||
run: |
|
||||
git config user.name 'github-actions[bot]'
|
||||
git config user.email 'github-actions[bot]@users.noreply.github.com'
|
||||
- name: Run Auto Merge Forward
|
||||
id: run-auto-merge-forward
|
||||
uses: spring-io/spring-security-release-tools/.github/actions/auto-merge-forward@actions-v1
|
||||
with:
|
||||
branches: ${{ needs.get-supported-branches.outputs.supported_versions }},main
|
||||
from-author: dependabot[bot]
|
||||
notify_result:
|
||||
name: Check for failures
|
||||
needs: [ auto-merge-forward-dependabot ]
|
||||
if: failure()
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
steps:
|
||||
- name: Send Slack message
|
||||
uses: Gamesight/slack-workflow-status@v1.3.0
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
slack_webhook_url: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
channel: '#spring-security-ci'
|
||||
name: 'CI Notifier'
|
||||
@@ -4,7 +4,8 @@ on:
|
||||
schedule:
|
||||
- cron: '0 2 * * *' # 2am UTC
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
jobs:
|
||||
upgrade_wrapper:
|
||||
name: Execution
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
name: Mark Duplicate Dependabot PRs
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
|
||||
jobs:
|
||||
check_duplicate_prs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.pull_request.merged == true && github.event.pull_request.user.login == 'dependabot[bot]'
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Extract Dependency Name from PR Title
|
||||
id: extract
|
||||
run: |
|
||||
PR_TITLE="${{ github.event.pull_request.title }}"
|
||||
DEPENDENCY_NAME=$(echo "$PR_TITLE" | awk -F ' from ' '{print $1}')
|
||||
echo "dependency_name=$DEPENDENCY_NAME" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Find PRs
|
||||
id: find_duplicates
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
PRS=$(gh pr list --search 'milestone:${{ github.event.pull_request.milestone.title }} is:merged in:title "${{ steps.extract.outputs.dependency_name }}"' --json number --jq 'map(.number) | join(",")')
|
||||
echo "prs=$PRS" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Label Duplicate PRs
|
||||
if: steps.find_duplicates.outputs.prs != ''
|
||||
env:
|
||||
PRS: ${{ steps.find_duplicates.outputs.prs }}
|
||||
CURRENT_PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
shell: bash
|
||||
run: |
|
||||
for i in ${PRS//,/ }
|
||||
do
|
||||
if [ ! $i -eq "$CURRENT_PR_NUMBER" ]; then
|
||||
echo "Marking PR $i as duplicate"
|
||||
gh pr edit "$i" --add-label "status: duplicate"
|
||||
gh pr comment "$i" --body "Duplicate of #$CURRENT_PR_NUMBER"
|
||||
fi
|
||||
done
|
||||
@@ -1,63 +0,0 @@
|
||||
name: Merge Dependabot PR
|
||||
|
||||
on: pull_request_target
|
||||
|
||||
run-name: Merge Dependabot PR ${{ github.ref_name }}
|
||||
|
||||
permissions: write-all
|
||||
|
||||
jobs:
|
||||
merge-dependabot-pr:
|
||||
name: Merge Dependabot PR
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.pull_request.user.login == 'dependabot[bot]' && github.repository == 'spring-projects/spring-security' }}
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
show-progress: false
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 17
|
||||
|
||||
- name: Set Milestone to Dependabot Pull Request
|
||||
id: set-milestone
|
||||
run: |
|
||||
if test -f pom.xml
|
||||
then
|
||||
CURRENT_VERSION=$(mvn help:evaluate -Dexpression="project.version" -q -DforceStdout)
|
||||
else
|
||||
CURRENT_VERSION=$(cat gradle.properties | sed -n '/^version=/ { s/^version=//;p }')
|
||||
fi
|
||||
export CANDIDATE_VERSION=${CURRENT_VERSION/-SNAPSHOT}
|
||||
MILESTONE=$(gh api repos/$GITHUB_REPOSITORY/milestones --jq 'map(select(.due_on != null and (.title | startswith(env.CANDIDATE_VERSION)))) | .[0] | .title')
|
||||
|
||||
if [ -z $MILESTONE ]
|
||||
then
|
||||
gh run cancel ${{ github.run_id }}
|
||||
echo "::warning title=Cannot merge::No scheduled milestone for $CURRENT_VERSION version"
|
||||
else
|
||||
gh pr edit ${{ github.event.pull_request.number }} --milestone $MILESTONE
|
||||
echo mergeEnabled=true >> $GITHUB_OUTPUT
|
||||
fi
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Merge Dependabot pull request
|
||||
if: steps.set-milestone.outputs.mergeEnabled
|
||||
run: gh pr merge ${{ github.event.pull_request.number }} --auto --rebase
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_ACTIONS_REPO_TOKEN }}
|
||||
send-notification:
|
||||
name: Send Notification
|
||||
needs: [ merge-dependabot-pr ]
|
||||
if: ${{ failure() || cancelled() }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Send Notification
|
||||
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@v1
|
||||
with:
|
||||
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
|
||||
@@ -1,22 +0,0 @@
|
||||
name: Trigger Dependabot Auto Merge Forward
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '*.x'
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
trigger-worflow:
|
||||
name: Trigger Workflow
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.commits[0].author.username == 'dependabot[bot]' && github.repository == 'spring-projects/spring-security' }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
id: checkout
|
||||
uses: actions/checkout@v4
|
||||
- id: trigger
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_ACTIONS_REPO_TOKEN }}
|
||||
run: gh workflow run dependabot-auto-merge-forward.yml -r main
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
matrix:
|
||||
branch: [ '5.8.x', '6.2.x', '6.3.x', 'main' ]
|
||||
steps:
|
||||
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@852920ba3fb1f28b35a2f13201133bc00ef33677
|
||||
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@e28269199d1d27975cf7f65e16d6095c555b3cd0
|
||||
name: Update
|
||||
with:
|
||||
docs-branch: ${{ matrix.branch }}
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: Update on docs-build
|
||||
steps:
|
||||
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@852920ba3fb1f28b35a2f13201133bc00ef33677
|
||||
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@e28269199d1d27975cf7f65e16d6095c555b3cd0
|
||||
name: Update
|
||||
with:
|
||||
docs-branch: 'docs-build'
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
name: Update dependabot.yml
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
|
||||
get-supported-branches:
|
||||
uses: spring-io/spring-security-release-tools/.github/workflows/retrieve-spring-supported-versions.yml@actions-v1
|
||||
with:
|
||||
project: spring-security
|
||||
type: oss
|
||||
repository_name: spring-projects/spring-security
|
||||
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [get-supported-branches]
|
||||
if: ${{ (github.repository == 'spring-projects/spring-security') && (github.ref == 'refs/heads/main') }}
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- uses: spring-io/spring-security-release-tools/.github/actions/generate-dependabot-yml@actions-v1
|
||||
name: Update dependabot.yml
|
||||
with:
|
||||
gradle-branches: ${{ needs.get-supported-branches.outputs.supported_versions }},main
|
||||
github-actions-branches: ${{ needs.get-supported-branches.outputs.supported_versions }},main,docs-build
|
||||
gh-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- uses: stefanzweifel/git-auto-commit-action@v5
|
||||
with:
|
||||
commit_message: Update dependabot.yml
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -144,7 +144,7 @@ public class PreAuthorizeAspectTests {
|
||||
protected void protectedMethod() {
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('X')")
|
||||
@PreAuthorize("hasRole('A')")
|
||||
void publicCallsPrivate() {
|
||||
privateMethod();
|
||||
}
|
||||
|
||||
+1
-1
@@ -124,7 +124,7 @@ wrapperUpgrade {
|
||||
gradle {
|
||||
'spring-security' {
|
||||
repo = 'spring-projects/spring-security'
|
||||
baseBranch = '6.2.x' // runs only on 6.2.x and the update is merged forward to main
|
||||
baseBranch = '6.3.x' // runs only on 6.3.x and the update is merged forward to main
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -183,6 +183,9 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
|
||||
BeanDefinitionBuilder csrfAuthenticationStrategy = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(CsrfAuthenticationStrategy.class);
|
||||
csrfAuthenticationStrategy.addConstructorArgReference(this.csrfRepositoryRef);
|
||||
if (StringUtils.hasText(this.requestHandlerRef)) {
|
||||
csrfAuthenticationStrategy.addPropertyReference("requestHandler", this.requestHandlerRef);
|
||||
}
|
||||
return csrfAuthenticationStrategy.getBeanDefinition();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,700 @@
|
||||
/*
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Field;
|
||||
import java.time.Instant;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import org.apereo.cas.client.validation.AssertionImpl;
|
||||
import org.instancio.Instancio;
|
||||
import org.instancio.InstancioApi;
|
||||
import org.instancio.InstancioOfClassApi;
|
||||
import org.instancio.Select;
|
||||
import org.instancio.generator.Generator;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.access.AuthorizationServiceException;
|
||||
import org.springframework.security.access.SecurityConfig;
|
||||
import org.springframework.security.access.hierarchicalroles.CycleInRoleHierarchyException;
|
||||
import org.springframework.security.access.intercept.RunAsUserToken;
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.authentication.AccountExpiredException;
|
||||
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.CredentialsExpiredException;
|
||||
import org.springframework.security.authentication.DisabledException;
|
||||
import org.springframework.security.authentication.InsufficientAuthenticationException;
|
||||
import org.springframework.security.authentication.InternalAuthenticationServiceException;
|
||||
import org.springframework.security.authentication.LockedException;
|
||||
import org.springframework.security.authentication.ProviderNotFoundException;
|
||||
import org.springframework.security.authentication.RememberMeAuthenticationToken;
|
||||
import org.springframework.security.authentication.TestAuthentication;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent;
|
||||
import org.springframework.security.authentication.event.AuthenticationFailureCredentialsExpiredEvent;
|
||||
import org.springframework.security.authentication.event.AuthenticationFailureDisabledEvent;
|
||||
import org.springframework.security.authentication.event.AuthenticationFailureExpiredEvent;
|
||||
import org.springframework.security.authentication.event.AuthenticationFailureLockedEvent;
|
||||
import org.springframework.security.authentication.event.AuthenticationFailureProviderNotFoundEvent;
|
||||
import org.springframework.security.authentication.event.AuthenticationFailureProxyUntrustedEvent;
|
||||
import org.springframework.security.authentication.event.AuthenticationFailureServiceExceptionEvent;
|
||||
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
|
||||
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent;
|
||||
import org.springframework.security.authentication.event.LogoutSuccessEvent;
|
||||
import org.springframework.security.authentication.jaas.JaasAuthenticationToken;
|
||||
import org.springframework.security.authentication.jaas.event.JaasAuthenticationFailedEvent;
|
||||
import org.springframework.security.authentication.jaas.event.JaasAuthenticationSuccessEvent;
|
||||
import org.springframework.security.authentication.ott.DefaultOneTimeToken;
|
||||
import org.springframework.security.authentication.ott.InvalidOneTimeTokenException;
|
||||
import org.springframework.security.authentication.ott.OneTimeTokenAuthenticationToken;
|
||||
import org.springframework.security.authentication.password.CompromisedPasswordException;
|
||||
import org.springframework.security.authorization.AuthorityAuthorizationDecision;
|
||||
import org.springframework.security.authorization.AuthorizationDecision;
|
||||
import org.springframework.security.authorization.AuthorizationDeniedException;
|
||||
import org.springframework.security.authorization.event.AuthorizationEvent;
|
||||
import org.springframework.security.authorization.event.AuthorizationGrantedEvent;
|
||||
import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken;
|
||||
import org.springframework.security.cas.authentication.CasAuthenticationToken;
|
||||
import org.springframework.security.cas.authentication.CasServiceTicketAuthenticationToken;
|
||||
import org.springframework.security.config.annotation.AlreadyBuiltException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextImpl;
|
||||
import org.springframework.security.core.context.TransientSecurityContext;
|
||||
import org.springframework.security.core.session.AbstractSessionEvent;
|
||||
import org.springframework.security.core.session.ReactiveSessionInformation;
|
||||
import org.springframework.security.core.session.SessionInformation;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.ldap.ppolicy.PasswordPolicyControl;
|
||||
import org.springframework.security.ldap.ppolicy.PasswordPolicyErrorStatus;
|
||||
import org.springframework.security.ldap.ppolicy.PasswordPolicyException;
|
||||
import org.springframework.security.ldap.ppolicy.PasswordPolicyResponseControl;
|
||||
import org.springframework.security.ldap.userdetails.LdapAuthority;
|
||||
import org.springframework.security.oauth2.client.ClientAuthorizationException;
|
||||
import org.springframework.security.oauth2.client.ClientAuthorizationRequiredException;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
|
||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthorizationCodeAuthenticationToken;
|
||||
import org.springframework.security.oauth2.client.authentication.OAuth2LoginAuthenticationToken;
|
||||
import org.springframework.security.oauth2.client.authentication.TestOAuth2AuthenticationTokens;
|
||||
import org.springframework.security.oauth2.client.authentication.TestOAuth2AuthorizationCodeAuthenticationTokens;
|
||||
import org.springframework.security.oauth2.client.oidc.authentication.logout.OidcLogoutToken;
|
||||
import org.springframework.security.oauth2.client.oidc.authentication.logout.TestOidcLogoutTokens;
|
||||
import org.springframework.security.oauth2.client.oidc.session.OidcSessionInformation;
|
||||
import org.springframework.security.oauth2.client.oidc.session.TestOidcSessionInformations;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.client.registration.TestClientRegistrations;
|
||||
import org.springframework.security.oauth2.core.DefaultOAuth2AuthenticatedPrincipal;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2DeviceCode;
|
||||
import org.springframework.security.oauth2.core.OAuth2Error;
|
||||
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2UserCode;
|
||||
import org.springframework.security.oauth2.core.TestOAuth2AccessTokens;
|
||||
import org.springframework.security.oauth2.core.TestOAuth2AuthenticatedPrincipals;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationExchange;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponse;
|
||||
import org.springframework.security.oauth2.core.endpoint.TestOAuth2AuthorizationExchanges;
|
||||
import org.springframework.security.oauth2.core.endpoint.TestOAuth2AuthorizationRequests;
|
||||
import org.springframework.security.oauth2.core.endpoint.TestOAuth2AuthorizationResponses;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
|
||||
import org.springframework.security.oauth2.core.oidc.TestOidcIdTokens;
|
||||
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
|
||||
import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
|
||||
import org.springframework.security.oauth2.core.oidc.user.TestOidcUsers;
|
||||
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
|
||||
import org.springframework.security.oauth2.core.user.TestOAuth2Users;
|
||||
import org.springframework.security.oauth2.jwt.BadJwtException;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
import org.springframework.security.oauth2.jwt.JwtDecoderInitializationException;
|
||||
import org.springframework.security.oauth2.jwt.JwtEncodingException;
|
||||
import org.springframework.security.oauth2.jwt.JwtException;
|
||||
import org.springframework.security.oauth2.jwt.JwtValidationException;
|
||||
import org.springframework.security.oauth2.jwt.TestJwts;
|
||||
import org.springframework.security.oauth2.server.resource.BearerTokenError;
|
||||
import org.springframework.security.oauth2.server.resource.BearerTokenErrors;
|
||||
import org.springframework.security.oauth2.server.resource.InvalidBearerTokenException;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthentication;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.resource.introspection.BadOpaqueTokenException;
|
||||
import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionAuthenticatedPrincipal;
|
||||
import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionException;
|
||||
import org.springframework.security.saml2.Saml2Exception;
|
||||
import org.springframework.security.saml2.core.Saml2Error;
|
||||
import org.springframework.security.saml2.core.Saml2X509Credential;
|
||||
import org.springframework.security.saml2.credentials.TestSaml2X509Credentials;
|
||||
import org.springframework.security.saml2.provider.service.authentication.DefaultSaml2AuthenticatedPrincipal;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationToken;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2PostAuthenticationRequest;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2RedirectAuthenticationRequest;
|
||||
import org.springframework.security.saml2.provider.service.authentication.TestSaml2AuthenticationTokens;
|
||||
import org.springframework.security.saml2.provider.service.authentication.TestSaml2Authentications;
|
||||
import org.springframework.security.saml2.provider.service.authentication.TestSaml2LogoutRequests;
|
||||
import org.springframework.security.saml2.provider.service.authentication.TestSaml2PostAuthenticationRequests;
|
||||
import org.springframework.security.saml2.provider.service.authentication.TestSaml2RedirectAuthenticationRequests;
|
||||
import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequest;
|
||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
|
||||
import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations;
|
||||
import org.springframework.security.web.PortResolverImpl;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetails;
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedCredentialsNotFoundException;
|
||||
import org.springframework.security.web.authentication.rememberme.CookieTheftException;
|
||||
import org.springframework.security.web.authentication.rememberme.InvalidCookieException;
|
||||
import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationException;
|
||||
import org.springframework.security.web.authentication.session.SessionAuthenticationException;
|
||||
import org.springframework.security.web.authentication.session.SessionFixationProtectionEvent;
|
||||
import org.springframework.security.web.authentication.switchuser.AuthenticationSwitchUserEvent;
|
||||
import org.springframework.security.web.authentication.www.NonceExpiredException;
|
||||
import org.springframework.security.web.csrf.CsrfException;
|
||||
import org.springframework.security.web.csrf.DefaultCsrfToken;
|
||||
import org.springframework.security.web.csrf.InvalidCsrfTokenException;
|
||||
import org.springframework.security.web.csrf.MissingCsrfTokenException;
|
||||
import org.springframework.security.web.firewall.RequestRejectedException;
|
||||
import org.springframework.security.web.savedrequest.DefaultSavedRequest;
|
||||
import org.springframework.security.web.savedrequest.SimpleSavedRequest;
|
||||
import org.springframework.security.web.server.firewall.ServerExchangeRejectedException;
|
||||
import org.springframework.security.web.session.HttpSessionCreatedEvent;
|
||||
import org.springframework.security.web.session.HttpSessionIdChangedEvent;
|
||||
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientInputs;
|
||||
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientOutputs;
|
||||
import org.springframework.security.web.webauthn.api.AuthenticatorAssertionResponse;
|
||||
import org.springframework.security.web.webauthn.api.AuthenticatorAttachment;
|
||||
import org.springframework.security.web.webauthn.api.AuthenticatorTransport;
|
||||
import org.springframework.security.web.webauthn.api.Bytes;
|
||||
import org.springframework.security.web.webauthn.api.CredProtectAuthenticationExtensionsClientInput;
|
||||
import org.springframework.security.web.webauthn.api.CredentialPropertiesOutput;
|
||||
import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExtensionsClientInput;
|
||||
import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExtensionsClientInputs;
|
||||
import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExtensionsClientOutputs;
|
||||
import org.springframework.security.web.webauthn.api.ImmutablePublicKeyCredentialUserEntity;
|
||||
import org.springframework.security.web.webauthn.api.PublicKeyCredential;
|
||||
import org.springframework.security.web.webauthn.api.PublicKeyCredentialDescriptor;
|
||||
import org.springframework.security.web.webauthn.api.PublicKeyCredentialRequestOptions;
|
||||
import org.springframework.security.web.webauthn.api.PublicKeyCredentialType;
|
||||
import org.springframework.security.web.webauthn.api.PublicKeyCredentialUserEntity;
|
||||
import org.springframework.security.web.webauthn.api.TestAuthenticationAssertionResponses;
|
||||
import org.springframework.security.web.webauthn.api.TestBytes;
|
||||
import org.springframework.security.web.webauthn.api.TestPublicKeyCredential;
|
||||
import org.springframework.security.web.webauthn.api.TestPublicKeyCredentialRequestOptions;
|
||||
import org.springframework.security.web.webauthn.api.TestPublicKeyCredentialUserEntity;
|
||||
import org.springframework.security.web.webauthn.api.UserVerificationRequirement;
|
||||
import org.springframework.security.web.webauthn.authentication.WebAuthnAuthentication;
|
||||
import org.springframework.security.web.webauthn.authentication.WebAuthnAuthenticationRequestToken;
|
||||
import org.springframework.security.web.webauthn.management.RelyingPartyAuthenticationRequest;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
final class SerializationSamples {
|
||||
|
||||
static final Map<Class<?>, Generator<?>> generatorByClassName = new HashMap<>();
|
||||
|
||||
static final Map<Class<?>, Supplier<InstancioApi<?>>> instancioByClassName = new HashMap<>();
|
||||
|
||||
static {
|
||||
UserDetails user = TestAuthentication.user();
|
||||
Authentication authentication = TestAuthentication.authenticated(user);
|
||||
SecurityContext securityContext = new SecurityContextImpl(authentication);
|
||||
|
||||
// oauth2-core
|
||||
generatorByClassName.put(DefaultOAuth2User.class, (r) -> TestOAuth2Users.create());
|
||||
generatorByClassName.put(OAuth2AuthorizationRequest.class,
|
||||
(r) -> TestOAuth2AuthorizationRequests.request().build());
|
||||
generatorByClassName.put(OAuth2AuthorizationResponse.class,
|
||||
(r) -> TestOAuth2AuthorizationResponses.success().build());
|
||||
generatorByClassName.put(OAuth2UserAuthority.class, (r) -> new OAuth2UserAuthority(Map.of("username", "user")));
|
||||
generatorByClassName.put(OAuth2AuthorizationExchange.class, (r) -> TestOAuth2AuthorizationExchanges.success());
|
||||
generatorByClassName.put(OidcUserInfo.class, (r) -> OidcUserInfo.builder().email("email@example.com").build());
|
||||
generatorByClassName.put(SessionInformation.class,
|
||||
(r) -> new SessionInformation(user, r.alphanumeric(4), new Date(1704378933936L)));
|
||||
generatorByClassName.put(ReactiveSessionInformation.class,
|
||||
(r) -> new ReactiveSessionInformation(user, r.alphanumeric(4), Instant.ofEpochMilli(1704378933936L)));
|
||||
generatorByClassName.put(OAuth2AccessToken.class, (r) -> TestOAuth2AccessTokens.scopes("scope"));
|
||||
generatorByClassName.put(OAuth2DeviceCode.class,
|
||||
(r) -> new OAuth2DeviceCode("token", Instant.now(), Instant.now()));
|
||||
generatorByClassName.put(OAuth2RefreshToken.class,
|
||||
(r) -> new OAuth2RefreshToken("refreshToken", Instant.now(), Instant.now()));
|
||||
generatorByClassName.put(OAuth2UserCode.class,
|
||||
(r) -> new OAuth2UserCode("token", Instant.now(), Instant.now()));
|
||||
generatorByClassName.put(DefaultOidcUser.class, (r) -> TestOidcUsers.create());
|
||||
generatorByClassName.put(OidcUserAuthority.class,
|
||||
(r) -> new OidcUserAuthority(TestOidcIdTokens.idToken().build(),
|
||||
new OidcUserInfo(Map.of("claim", "value")), "claim"));
|
||||
generatorByClassName.put(OAuth2AuthenticationException.class,
|
||||
(r) -> new OAuth2AuthenticationException(new OAuth2Error("error", "description", "uri"), "message",
|
||||
new RuntimeException()));
|
||||
generatorByClassName.put(OAuth2AuthorizationException.class,
|
||||
(r) -> new OAuth2AuthorizationException(new OAuth2Error("error", "description", "uri"), "message",
|
||||
new RuntimeException()));
|
||||
|
||||
// oauth2-client
|
||||
ClientRegistration.Builder clientRegistrationBuilder = TestClientRegistrations.clientRegistration();
|
||||
ClientRegistration clientRegistration = clientRegistrationBuilder.build();
|
||||
WebAuthenticationDetails details = new WebAuthenticationDetails("remote", "sessionId");
|
||||
generatorByClassName.put(ClientRegistration.class, (r) -> clientRegistration);
|
||||
generatorByClassName.put(ClientRegistration.ProviderDetails.class,
|
||||
(r) -> clientRegistration.getProviderDetails());
|
||||
generatorByClassName.put(ClientRegistration.ProviderDetails.UserInfoEndpoint.class,
|
||||
(r) -> clientRegistration.getProviderDetails().getUserInfoEndpoint());
|
||||
generatorByClassName.put(ClientRegistration.Builder.class, (r) -> clientRegistrationBuilder);
|
||||
generatorByClassName.put(OAuth2AuthorizedClient.class,
|
||||
(r) -> new OAuth2AuthorizedClient(clientRegistration, "principal", TestOAuth2AccessTokens.noScopes()));
|
||||
generatorByClassName.put(OAuth2LoginAuthenticationToken.class, (r) -> {
|
||||
var token = new OAuth2LoginAuthenticationToken(clientRegistration,
|
||||
TestOAuth2AuthorizationExchanges.success());
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(OAuth2AuthorizationCodeAuthenticationToken.class, (r) -> {
|
||||
var token = TestOAuth2AuthorizationCodeAuthenticationTokens.authenticated();
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(OAuth2AuthenticationToken.class, (r) -> {
|
||||
var token = TestOAuth2AuthenticationTokens.authenticated();
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(OidcIdToken.class, (r) -> TestOidcIdTokens.idToken().build());
|
||||
generatorByClassName.put(OidcLogoutToken.class,
|
||||
(r) -> TestOidcLogoutTokens.withSessionId("issuer", "sessionId").issuedAt(Instant.now()).build());
|
||||
generatorByClassName.put(OidcSessionInformation.class, (r) -> TestOidcSessionInformations.create());
|
||||
generatorByClassName.put(DefaultOAuth2AuthenticatedPrincipal.class, (r) -> {
|
||||
OAuth2AuthenticatedPrincipal principal = TestOAuth2AuthenticatedPrincipals.active();
|
||||
return new DefaultOAuth2AuthenticatedPrincipal(principal.getName(), principal.getAttributes(),
|
||||
(Collection<GrantedAuthority>) principal.getAuthorities());
|
||||
});
|
||||
generatorByClassName.put(ClientAuthorizationException.class,
|
||||
(r) -> new ClientAuthorizationException(new OAuth2Error("error", "description", "uri"), "id", "message",
|
||||
new RuntimeException()));
|
||||
generatorByClassName.put(ClientAuthorizationRequiredException.class,
|
||||
(r) -> new ClientAuthorizationRequiredException("id"));
|
||||
|
||||
// oauth2-jose
|
||||
generatorByClassName.put(BadJwtException.class, (r) -> new BadJwtException("token", new RuntimeException()));
|
||||
generatorByClassName.put(JwtDecoderInitializationException.class,
|
||||
(r) -> new JwtDecoderInitializationException("message", new RuntimeException()));
|
||||
generatorByClassName.put(JwtEncodingException.class,
|
||||
(r) -> new JwtEncodingException("message", new RuntimeException()));
|
||||
generatorByClassName.put(JwtException.class, (r) -> new JwtException("message", new RuntimeException()));
|
||||
generatorByClassName.put(JwtValidationException.class,
|
||||
(r) -> new JwtValidationException("message", List.of(new OAuth2Error("error", "description", "uri"))));
|
||||
|
||||
// oauth2-jwt
|
||||
generatorByClassName.put(Jwt.class, (r) -> TestJwts.user());
|
||||
|
||||
// oauth2-resource-server
|
||||
generatorByClassName
|
||||
.put(org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken.class, (r) -> {
|
||||
var token = new org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken(
|
||||
"token");
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(BearerTokenAuthenticationToken.class, (r) -> {
|
||||
var token = new BearerTokenAuthenticationToken("token");
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(BearerTokenAuthentication.class, (r) -> {
|
||||
var token = new BearerTokenAuthentication(TestOAuth2AuthenticatedPrincipals.active(),
|
||||
TestOAuth2AccessTokens.noScopes(), user.getAuthorities());
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(JwtAuthenticationToken.class, (r) -> {
|
||||
var token = new JwtAuthenticationToken(TestJwts.user());
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(BearerTokenError.class, (r) -> BearerTokenErrors.invalidToken("invalid token"));
|
||||
generatorByClassName.put(OAuth2IntrospectionAuthenticatedPrincipal.class,
|
||||
(r) -> TestOAuth2AuthenticatedPrincipals.active());
|
||||
generatorByClassName.put(InvalidBearerTokenException.class,
|
||||
(r) -> new InvalidBearerTokenException("description", new RuntimeException()));
|
||||
generatorByClassName.put(BadOpaqueTokenException.class,
|
||||
(r) -> new BadOpaqueTokenException("message", new RuntimeException()));
|
||||
generatorByClassName.put(OAuth2IntrospectionException.class,
|
||||
(r) -> new OAuth2IntrospectionException("message", new RuntimeException()));
|
||||
|
||||
// config
|
||||
generatorByClassName.put(AlreadyBuiltException.class, (r) -> new AlreadyBuiltException("message"));
|
||||
|
||||
// core
|
||||
generatorByClassName.put(RunAsUserToken.class, (r) -> {
|
||||
RunAsUserToken token = new RunAsUserToken("key", user, "creds", user.getAuthorities(),
|
||||
AnonymousAuthenticationToken.class);
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(RememberMeAuthenticationToken.class, (r) -> {
|
||||
RememberMeAuthenticationToken token = new RememberMeAuthenticationToken("key", user, user.getAuthorities());
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(UsernamePasswordAuthenticationToken.class, (r) -> {
|
||||
var token = UsernamePasswordAuthenticationToken.unauthenticated(user, "creds");
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(JaasAuthenticationToken.class, (r) -> {
|
||||
var token = new JaasAuthenticationToken(user, "creds", null);
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(OneTimeTokenAuthenticationToken.class,
|
||||
(r) -> applyDetails(new OneTimeTokenAuthenticationToken("username", "token")));
|
||||
generatorByClassName.put(AccessDeniedException.class,
|
||||
(r) -> new AccessDeniedException("access denied", new RuntimeException()));
|
||||
generatorByClassName.put(AuthorizationServiceException.class,
|
||||
(r) -> new AuthorizationServiceException("access denied", new RuntimeException()));
|
||||
generatorByClassName.put(AccountExpiredException.class,
|
||||
(r) -> new AccountExpiredException("error", new RuntimeException()));
|
||||
generatorByClassName.put(AuthenticationCredentialsNotFoundException.class,
|
||||
(r) -> new AuthenticationCredentialsNotFoundException("error", new RuntimeException()));
|
||||
generatorByClassName.put(AuthenticationServiceException.class,
|
||||
(r) -> new AuthenticationServiceException("error", new RuntimeException()));
|
||||
generatorByClassName.put(BadCredentialsException.class,
|
||||
(r) -> new BadCredentialsException("error", new RuntimeException()));
|
||||
generatorByClassName.put(CredentialsExpiredException.class,
|
||||
(r) -> new CredentialsExpiredException("error", new RuntimeException()));
|
||||
generatorByClassName.put(DisabledException.class,
|
||||
(r) -> new DisabledException("error", new RuntimeException()));
|
||||
generatorByClassName.put(InsufficientAuthenticationException.class,
|
||||
(r) -> new InsufficientAuthenticationException("error", new RuntimeException()));
|
||||
generatorByClassName.put(InternalAuthenticationServiceException.class,
|
||||
(r) -> new InternalAuthenticationServiceException("error", new RuntimeException()));
|
||||
generatorByClassName.put(LockedException.class, (r) -> new LockedException("error", new RuntimeException()));
|
||||
generatorByClassName.put(ProviderNotFoundException.class, (r) -> new ProviderNotFoundException("error"));
|
||||
generatorByClassName.put(InvalidOneTimeTokenException.class, (r) -> new InvalidOneTimeTokenException("error"));
|
||||
generatorByClassName.put(CompromisedPasswordException.class,
|
||||
(r) -> new CompromisedPasswordException("error", new RuntimeException()));
|
||||
generatorByClassName.put(UsernameNotFoundException.class,
|
||||
(r) -> new UsernameNotFoundException("error", new RuntimeException()));
|
||||
generatorByClassName.put(TestingAuthenticationToken.class,
|
||||
(r) -> applyDetails(new TestingAuthenticationToken("username", "password")));
|
||||
generatorByClassName.put(AuthenticationFailureBadCredentialsEvent.class,
|
||||
(r) -> new AuthenticationFailureBadCredentialsEvent(authentication,
|
||||
new BadCredentialsException("message")));
|
||||
generatorByClassName.put(AuthenticationFailureCredentialsExpiredEvent.class,
|
||||
(r) -> new AuthenticationFailureCredentialsExpiredEvent(authentication,
|
||||
new CredentialsExpiredException("message")));
|
||||
generatorByClassName.put(AuthenticationFailureDisabledEvent.class,
|
||||
(r) -> new AuthenticationFailureDisabledEvent(authentication, new DisabledException("message")));
|
||||
generatorByClassName.put(AuthenticationFailureExpiredEvent.class,
|
||||
(r) -> new AuthenticationFailureExpiredEvent(authentication, new AccountExpiredException("message")));
|
||||
generatorByClassName.put(AuthenticationFailureLockedEvent.class,
|
||||
(r) -> new AuthenticationFailureLockedEvent(authentication, new LockedException("message")));
|
||||
generatorByClassName.put(AuthenticationFailureProviderNotFoundEvent.class,
|
||||
(r) -> new AuthenticationFailureProviderNotFoundEvent(authentication,
|
||||
new ProviderNotFoundException("message")));
|
||||
generatorByClassName.put(AuthenticationFailureProxyUntrustedEvent.class,
|
||||
(r) -> new AuthenticationFailureProxyUntrustedEvent(authentication,
|
||||
new AuthenticationServiceException("message")));
|
||||
generatorByClassName.put(AuthenticationFailureServiceExceptionEvent.class,
|
||||
(r) -> new AuthenticationFailureServiceExceptionEvent(authentication,
|
||||
new AuthenticationServiceException("message")));
|
||||
generatorByClassName.put(AuthenticationSuccessEvent.class,
|
||||
(r) -> new AuthenticationSuccessEvent(authentication));
|
||||
generatorByClassName.put(InteractiveAuthenticationSuccessEvent.class,
|
||||
(r) -> new InteractiveAuthenticationSuccessEvent(authentication, Authentication.class));
|
||||
generatorByClassName.put(LogoutSuccessEvent.class, (r) -> new LogoutSuccessEvent(authentication));
|
||||
generatorByClassName.put(JaasAuthenticationFailedEvent.class,
|
||||
(r) -> new JaasAuthenticationFailedEvent(authentication, new RuntimeException("message")));
|
||||
generatorByClassName.put(JaasAuthenticationSuccessEvent.class,
|
||||
(r) -> new JaasAuthenticationSuccessEvent(authentication));
|
||||
generatorByClassName.put(AbstractSessionEvent.class, (r) -> new AbstractSessionEvent(securityContext));
|
||||
generatorByClassName.put(SecurityConfig.class, (r) -> new SecurityConfig("value"));
|
||||
generatorByClassName.put(TransientSecurityContext.class, (r) -> new TransientSecurityContext(authentication));
|
||||
generatorByClassName.put(AuthorizationDeniedException.class,
|
||||
(r) -> new AuthorizationDeniedException("message", new AuthorizationDecision(false)));
|
||||
generatorByClassName.put(AuthorizationDecision.class, (r) -> new AuthorizationDecision(true));
|
||||
generatorByClassName.put(AuthorityAuthorizationDecision.class,
|
||||
(r) -> new AuthorityAuthorizationDecision(true, AuthorityUtils.createAuthorityList("ROLE_USER")));
|
||||
generatorByClassName.put(CycleInRoleHierarchyException.class, (r) -> new CycleInRoleHierarchyException());
|
||||
generatorByClassName.put(AuthorizationEvent.class,
|
||||
(r) -> new AuthorizationEvent(new SerializableSupplier<>(authentication), "source",
|
||||
new AuthorizationDecision(true)));
|
||||
generatorByClassName.put(AuthorizationGrantedEvent.class,
|
||||
(r) -> new AuthorizationGrantedEvent<>(new SerializableSupplier<>(authentication), "source",
|
||||
new AuthorizationDecision(true)));
|
||||
instancioByClassName.put(AuthorizationGrantedEvent.class, () -> {
|
||||
InstancioOfClassApi<?> instancio = Instancio.of(AuthorizationGrantedEvent.class);
|
||||
instancio.withTypeParameters(String.class);
|
||||
instancio.supply(Select.all(AuthorizationGrantedEvent.class),
|
||||
generatorByClassName.get(AuthorizationGrantedEvent.class));
|
||||
return instancio;
|
||||
});
|
||||
|
||||
// cas
|
||||
generatorByClassName.put(CasServiceTicketAuthenticationToken.class, (r) -> {
|
||||
CasServiceTicketAuthenticationToken token = CasServiceTicketAuthenticationToken.stateless("creds");
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(CasAuthenticationToken.class, (r) -> {
|
||||
var token = new CasAuthenticationToken("key", user, "Password", user.getAuthorities(), user,
|
||||
new AssertionImpl("test"));
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(CasAssertionAuthenticationToken.class, (r) -> {
|
||||
var token = new CasAssertionAuthenticationToken(new AssertionImpl("test"), "ticket");
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
|
||||
// ldap
|
||||
generatorByClassName.put(LdapAuthority.class,
|
||||
(r) -> new LdapAuthority("USER", "username", Map.of("attribute", List.of("value1", "value2"))));
|
||||
generatorByClassName.put(PasswordPolicyException.class,
|
||||
(r) -> new PasswordPolicyException(PasswordPolicyErrorStatus.INSUFFICIENT_PASSWORD_QUALITY));
|
||||
generatorByClassName.put(PasswordPolicyControl.class, (r) -> new PasswordPolicyControl(true));
|
||||
generatorByClassName.put(PasswordPolicyResponseControl.class, (r) -> {
|
||||
byte[] encodedResponse = { 0x30, 0x05, (byte) 0xA0, 0x03, (byte) 0xA0, 0x1, 0x21 };
|
||||
return new PasswordPolicyResponseControl(encodedResponse);
|
||||
});
|
||||
|
||||
// saml2-service-provider
|
||||
generatorByClassName.put(Saml2AuthenticationException.class,
|
||||
(r) -> new Saml2AuthenticationException(new Saml2Error("code", "descirption"), "message",
|
||||
new IOException("fail")));
|
||||
generatorByClassName.put(Saml2Exception.class, (r) -> new Saml2Exception("message", new IOException("fail")));
|
||||
generatorByClassName.put(DefaultSaml2AuthenticatedPrincipal.class,
|
||||
(r) -> TestSaml2Authentications.authentication().getPrincipal());
|
||||
generatorByClassName.put(Saml2Authentication.class,
|
||||
(r) -> applyDetails(TestSaml2Authentications.authentication()));
|
||||
generatorByClassName.put(Saml2PostAuthenticationRequest.class,
|
||||
(r) -> TestSaml2PostAuthenticationRequests.create());
|
||||
generatorByClassName.put(Saml2RedirectAuthenticationRequest.class,
|
||||
(r) -> TestSaml2RedirectAuthenticationRequests.create());
|
||||
generatorByClassName.put(Saml2X509Credential.class,
|
||||
(r) -> TestSaml2X509Credentials.relyingPartyVerifyingCredential());
|
||||
generatorByClassName.put(RelyingPartyRegistration.AssertingPartyDetails.class,
|
||||
(r) -> TestRelyingPartyRegistrations.full().build().getAssertingPartyMetadata());
|
||||
generatorByClassName.put(RelyingPartyRegistration.class, (r) -> TestRelyingPartyRegistrations.full().build());
|
||||
generatorByClassName.put(Saml2AuthenticationToken.class, (r) -> {
|
||||
Saml2AuthenticationToken token = TestSaml2AuthenticationTokens.tokenRequested();
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(Saml2LogoutRequest.class, (r) -> TestSaml2LogoutRequests.create());
|
||||
|
||||
// web
|
||||
generatorByClassName.put(AnonymousAuthenticationToken.class, (r) -> {
|
||||
Collection<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("ROLE_USER");
|
||||
return applyDetails(new AnonymousAuthenticationToken("key", "username", authorities));
|
||||
});
|
||||
generatorByClassName.put(PreAuthenticatedAuthenticationToken.class, (r) -> {
|
||||
PreAuthenticatedAuthenticationToken token = new PreAuthenticatedAuthenticationToken(user, "creds",
|
||||
user.getAuthorities());
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(PreAuthenticatedCredentialsNotFoundException.class,
|
||||
(r) -> new PreAuthenticatedCredentialsNotFoundException("message", new IOException("fail")));
|
||||
generatorByClassName.put(CookieTheftException.class, (r) -> new CookieTheftException("message"));
|
||||
generatorByClassName.put(InvalidCookieException.class, (r) -> new InvalidCookieException("message"));
|
||||
generatorByClassName.put(RememberMeAuthenticationException.class,
|
||||
(r) -> new RememberMeAuthenticationException("message", new IOException("fail")));
|
||||
generatorByClassName.put(SessionAuthenticationException.class,
|
||||
(r) -> new SessionAuthenticationException("message"));
|
||||
generatorByClassName.put(NonceExpiredException.class,
|
||||
(r) -> new NonceExpiredException("message", new IOException("fail")));
|
||||
generatorByClassName.put(CsrfException.class, (r) -> new CsrfException("message"));
|
||||
generatorByClassName.put(org.springframework.security.web.server.csrf.CsrfException.class,
|
||||
(r) -> new org.springframework.security.web.server.csrf.CsrfException("message"));
|
||||
generatorByClassName.put(InvalidCsrfTokenException.class,
|
||||
(r) -> new InvalidCsrfTokenException(new DefaultCsrfToken("header", "parameter", "token"), "token"));
|
||||
generatorByClassName.put(MissingCsrfTokenException.class, (r) -> new MissingCsrfTokenException("token"));
|
||||
generatorByClassName.put(DefaultCsrfToken.class, (r) -> new DefaultCsrfToken("header", "parameter", "token"));
|
||||
generatorByClassName.put(org.springframework.security.web.server.csrf.DefaultCsrfToken.class,
|
||||
(r) -> new org.springframework.security.web.server.csrf.DefaultCsrfToken("header", "parameter",
|
||||
"token"));
|
||||
generatorByClassName.put(RequestRejectedException.class, (r) -> new RequestRejectedException("message"));
|
||||
generatorByClassName.put(ServerExchangeRejectedException.class,
|
||||
(r) -> new ServerExchangeRejectedException("message"));
|
||||
generatorByClassName.put(SessionFixationProtectionEvent.class,
|
||||
(r) -> new SessionFixationProtectionEvent(authentication, "old", "new"));
|
||||
generatorByClassName.put(AuthenticationSwitchUserEvent.class,
|
||||
(r) -> new AuthenticationSwitchUserEvent(authentication, user));
|
||||
generatorByClassName.put(HttpSessionCreatedEvent.class,
|
||||
(r) -> new HttpSessionCreatedEvent(new MockHttpSession()));
|
||||
generatorByClassName.put(SimpleSavedRequest.class, (r) -> {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/uri");
|
||||
request.setQueryString("query=string");
|
||||
request.setScheme("https");
|
||||
request.setServerName("localhost");
|
||||
request.setServerPort(80);
|
||||
request.setRequestURI("/uri");
|
||||
request.setCookies(new Cookie("name", "value"));
|
||||
request.addHeader("header", "value");
|
||||
request.addParameter("parameter", "value");
|
||||
request.setPathInfo("/path");
|
||||
request.addPreferredLocale(Locale.ENGLISH);
|
||||
return new SimpleSavedRequest(new DefaultSavedRequest(request, new PortResolverImpl(), "continue"));
|
||||
});
|
||||
generatorByClassName.put(HttpSessionIdChangedEvent.class,
|
||||
(r) -> new HttpSessionIdChangedEvent(new MockHttpSession(), "1"));
|
||||
|
||||
// webauthn
|
||||
CredProtectAuthenticationExtensionsClientInput.CredProtect credProtect = new CredProtectAuthenticationExtensionsClientInput.CredProtect(
|
||||
CredProtectAuthenticationExtensionsClientInput.CredProtect.ProtectionPolicy.USER_VERIFICATION_OPTIONAL,
|
||||
true);
|
||||
Bytes id = TestBytes.get();
|
||||
AuthenticationExtensionsClientInputs inputs = new ImmutableAuthenticationExtensionsClientInputs(
|
||||
ImmutableAuthenticationExtensionsClientInput.credProps);
|
||||
// @formatter:off
|
||||
PublicKeyCredentialDescriptor descriptor = PublicKeyCredentialDescriptor.builder()
|
||||
.id(id)
|
||||
.type(PublicKeyCredentialType.PUBLIC_KEY)
|
||||
.transports(Set.of(AuthenticatorTransport.USB))
|
||||
.build();
|
||||
// @formatter:on
|
||||
generatorByClassName.put(AuthenticatorTransport.class, (a) -> AuthenticatorTransport.USB);
|
||||
generatorByClassName.put(PublicKeyCredentialType.class, (k) -> PublicKeyCredentialType.PUBLIC_KEY);
|
||||
generatorByClassName.put(UserVerificationRequirement.class, (r) -> UserVerificationRequirement.REQUIRED);
|
||||
generatorByClassName.put(CredProtectAuthenticationExtensionsClientInput.CredProtect.class, (c) -> credProtect);
|
||||
generatorByClassName.put(CredProtectAuthenticationExtensionsClientInput.class,
|
||||
(c) -> new CredProtectAuthenticationExtensionsClientInput(credProtect));
|
||||
generatorByClassName.put(ImmutableAuthenticationExtensionsClientInputs.class, (i) -> inputs);
|
||||
Field credPropsField = ReflectionUtils.findField(ImmutableAuthenticationExtensionsClientInput.class,
|
||||
"credProps");
|
||||
generatorByClassName.put(credPropsField.getType(),
|
||||
(i) -> ImmutableAuthenticationExtensionsClientInput.credProps);
|
||||
generatorByClassName.put(Bytes.class, (b) -> id);
|
||||
generatorByClassName.put(PublicKeyCredentialDescriptor.class, (d) -> descriptor);
|
||||
// @formatter:off
|
||||
generatorByClassName.put(PublicKeyCredentialRequestOptions.class, (o) -> TestPublicKeyCredentialRequestOptions.create()
|
||||
.extensions(inputs)
|
||||
.allowCredentials(List.of(descriptor))
|
||||
.build()
|
||||
);
|
||||
|
||||
CredentialPropertiesOutput credentialOutput = new CredentialPropertiesOutput(false);
|
||||
AuthenticationExtensionsClientOutputs outputs = new ImmutableAuthenticationExtensionsClientOutputs(credentialOutput);
|
||||
AuthenticatorAssertionResponse response = TestAuthenticationAssertionResponses.createAuthenticatorAssertionResponse()
|
||||
.build();
|
||||
PublicKeyCredential<AuthenticatorAssertionResponse> credential = TestPublicKeyCredential.createPublicKeyCredential(
|
||||
response, outputs)
|
||||
.build();
|
||||
RelyingPartyAuthenticationRequest authRequest = new RelyingPartyAuthenticationRequest(
|
||||
TestPublicKeyCredentialRequestOptions.create().build(),
|
||||
credential
|
||||
);
|
||||
WebAuthnAuthenticationRequestToken requestToken = new WebAuthnAuthenticationRequestToken(authRequest);
|
||||
requestToken.setDetails(details);
|
||||
generatorByClassName.put(CredentialPropertiesOutput.class, (o) -> credentialOutput);
|
||||
generatorByClassName.put(ImmutableAuthenticationExtensionsClientOutputs.class, (o) -> outputs);
|
||||
generatorByClassName.put(AuthenticatorAssertionResponse.class, (r) -> response);
|
||||
generatorByClassName.put(RelyingPartyAuthenticationRequest.class, (r) -> authRequest);
|
||||
generatorByClassName.put(PublicKeyCredential.class, (r) -> credential);
|
||||
generatorByClassName.put(WebAuthnAuthenticationRequestToken.class, (r) -> requestToken);
|
||||
generatorByClassName.put(AuthenticatorAttachment.class, (r) -> AuthenticatorAttachment.PLATFORM);
|
||||
// @formatter:on
|
||||
generatorByClassName.put(ImmutablePublicKeyCredentialUserEntity.class,
|
||||
(r) -> TestPublicKeyCredentialUserEntity.userEntity().id(TestBytes.get()).build());
|
||||
generatorByClassName.put(WebAuthnAuthentication.class, (r) -> {
|
||||
PublicKeyCredentialUserEntity userEntity = TestPublicKeyCredentialUserEntity.userEntity()
|
||||
.id(TestBytes.get())
|
||||
.build();
|
||||
List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("ROLE_USER");
|
||||
WebAuthnAuthentication webAuthnAuthentication = new WebAuthnAuthentication(userEntity, authorities);
|
||||
webAuthnAuthentication.setDetails(details);
|
||||
return webAuthnAuthentication;
|
||||
});
|
||||
// @formatter:on
|
||||
generatorByClassName.put(CredentialPropertiesOutput.ExtensionOutput.class,
|
||||
(r) -> new CredentialPropertiesOutput(true).getOutput());
|
||||
|
||||
// One-Time Token
|
||||
DefaultOneTimeToken oneTimeToken = new DefaultOneTimeToken(UUID.randomUUID().toString(), "user",
|
||||
Instant.now().plusSeconds(300));
|
||||
generatorByClassName.put(DefaultOneTimeToken.class, (t) -> oneTimeToken);
|
||||
}
|
||||
|
||||
private SerializationSamples() {
|
||||
|
||||
}
|
||||
|
||||
static InstancioApi<?> instancioWithDefaults(Class<?> clazz) {
|
||||
if (instancioByClassName.containsKey(clazz)) {
|
||||
return instancioByClassName.get(clazz).get();
|
||||
}
|
||||
InstancioOfClassApi<?> instancio = Instancio.of(clazz);
|
||||
ResolvableType[] generics = ResolvableType.forClass(clazz).getGenerics();
|
||||
for (ResolvableType type : generics) {
|
||||
instancio.withTypeParameters(type.resolve());
|
||||
}
|
||||
if (generatorByClassName.containsKey(clazz)) {
|
||||
instancio.supply(Select.all(clazz), generatorByClassName.get(clazz));
|
||||
}
|
||||
return instancio;
|
||||
}
|
||||
|
||||
private static <T extends AbstractAuthenticationToken> T applyDetails(T authentication) {
|
||||
WebAuthenticationDetails details = new WebAuthenticationDetails("remote", "sessionId");
|
||||
authentication.setDetails(details);
|
||||
return authentication;
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static final class SerializableSupplier<T> implements Supplier<T>, Serializable {
|
||||
|
||||
private final T value;
|
||||
|
||||
SerializableSupplier(T value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+35
-618
@@ -30,25 +30,12 @@ import java.lang.reflect.Modifier;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import org.apereo.cas.client.validation.AssertionImpl;
|
||||
import org.instancio.Instancio;
|
||||
import org.instancio.InstancioApi;
|
||||
import org.instancio.InstancioOfClassApi;
|
||||
import org.instancio.Select;
|
||||
import org.instancio.generator.Generator;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
@@ -56,190 +43,8 @@ import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.access.AuthorizationServiceException;
|
||||
import org.springframework.security.access.SecurityConfig;
|
||||
import org.springframework.security.access.intercept.RunAsUserToken;
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.authentication.AccountExpiredException;
|
||||
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.CredentialsExpiredException;
|
||||
import org.springframework.security.authentication.DisabledException;
|
||||
import org.springframework.security.authentication.InsufficientAuthenticationException;
|
||||
import org.springframework.security.authentication.InternalAuthenticationServiceException;
|
||||
import org.springframework.security.authentication.LockedException;
|
||||
import org.springframework.security.authentication.ProviderNotFoundException;
|
||||
import org.springframework.security.authentication.RememberMeAuthenticationToken;
|
||||
import org.springframework.security.authentication.TestAuthentication;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent;
|
||||
import org.springframework.security.authentication.event.AuthenticationFailureCredentialsExpiredEvent;
|
||||
import org.springframework.security.authentication.event.AuthenticationFailureDisabledEvent;
|
||||
import org.springframework.security.authentication.event.AuthenticationFailureExpiredEvent;
|
||||
import org.springframework.security.authentication.event.AuthenticationFailureLockedEvent;
|
||||
import org.springframework.security.authentication.event.AuthenticationFailureProviderNotFoundEvent;
|
||||
import org.springframework.security.authentication.event.AuthenticationFailureProxyUntrustedEvent;
|
||||
import org.springframework.security.authentication.event.AuthenticationFailureServiceExceptionEvent;
|
||||
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
|
||||
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent;
|
||||
import org.springframework.security.authentication.event.LogoutSuccessEvent;
|
||||
import org.springframework.security.authentication.jaas.JaasAuthenticationToken;
|
||||
import org.springframework.security.authentication.jaas.event.JaasAuthenticationFailedEvent;
|
||||
import org.springframework.security.authentication.jaas.event.JaasAuthenticationSuccessEvent;
|
||||
import org.springframework.security.authentication.ott.InvalidOneTimeTokenException;
|
||||
import org.springframework.security.authentication.ott.OneTimeTokenAuthenticationToken;
|
||||
import org.springframework.security.authentication.password.CompromisedPasswordException;
|
||||
import org.springframework.security.authorization.AuthorityAuthorizationDecision;
|
||||
import org.springframework.security.authorization.AuthorizationDecision;
|
||||
import org.springframework.security.authorization.AuthorizationDeniedException;
|
||||
import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken;
|
||||
import org.springframework.security.cas.authentication.CasAuthenticationToken;
|
||||
import org.springframework.security.cas.authentication.CasServiceTicketAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.SpringSecurityCoreVersion;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextImpl;
|
||||
import org.springframework.security.core.context.TransientSecurityContext;
|
||||
import org.springframework.security.core.session.AbstractSessionEvent;
|
||||
import org.springframework.security.core.session.ReactiveSessionInformation;
|
||||
import org.springframework.security.core.session.SessionInformation;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.ldap.ppolicy.PasswordPolicyControl;
|
||||
import org.springframework.security.ldap.ppolicy.PasswordPolicyErrorStatus;
|
||||
import org.springframework.security.ldap.ppolicy.PasswordPolicyException;
|
||||
import org.springframework.security.ldap.ppolicy.PasswordPolicyResponseControl;
|
||||
import org.springframework.security.ldap.userdetails.LdapAuthority;
|
||||
import org.springframework.security.oauth2.client.ClientAuthorizationException;
|
||||
import org.springframework.security.oauth2.client.ClientAuthorizationRequiredException;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
|
||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthorizationCodeAuthenticationToken;
|
||||
import org.springframework.security.oauth2.client.authentication.OAuth2LoginAuthenticationToken;
|
||||
import org.springframework.security.oauth2.client.authentication.TestOAuth2AuthenticationTokens;
|
||||
import org.springframework.security.oauth2.client.authentication.TestOAuth2AuthorizationCodeAuthenticationTokens;
|
||||
import org.springframework.security.oauth2.client.oidc.authentication.logout.OidcLogoutToken;
|
||||
import org.springframework.security.oauth2.client.oidc.authentication.logout.TestOidcLogoutTokens;
|
||||
import org.springframework.security.oauth2.client.oidc.session.OidcSessionInformation;
|
||||
import org.springframework.security.oauth2.client.oidc.session.TestOidcSessionInformations;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.client.registration.TestClientRegistrations;
|
||||
import org.springframework.security.oauth2.core.DefaultOAuth2AuthenticatedPrincipal;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2DeviceCode;
|
||||
import org.springframework.security.oauth2.core.OAuth2Error;
|
||||
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2UserCode;
|
||||
import org.springframework.security.oauth2.core.TestOAuth2AccessTokens;
|
||||
import org.springframework.security.oauth2.core.TestOAuth2AuthenticatedPrincipals;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationExchange;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponse;
|
||||
import org.springframework.security.oauth2.core.endpoint.TestOAuth2AuthorizationExchanges;
|
||||
import org.springframework.security.oauth2.core.endpoint.TestOAuth2AuthorizationRequests;
|
||||
import org.springframework.security.oauth2.core.endpoint.TestOAuth2AuthorizationResponses;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
|
||||
import org.springframework.security.oauth2.core.oidc.TestOidcIdTokens;
|
||||
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
|
||||
import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
|
||||
import org.springframework.security.oauth2.core.oidc.user.TestOidcUsers;
|
||||
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
|
||||
import org.springframework.security.oauth2.core.user.TestOAuth2Users;
|
||||
import org.springframework.security.oauth2.jwt.BadJwtException;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
import org.springframework.security.oauth2.jwt.JwtDecoderInitializationException;
|
||||
import org.springframework.security.oauth2.jwt.JwtEncodingException;
|
||||
import org.springframework.security.oauth2.jwt.JwtException;
|
||||
import org.springframework.security.oauth2.jwt.JwtValidationException;
|
||||
import org.springframework.security.oauth2.jwt.TestJwts;
|
||||
import org.springframework.security.oauth2.server.resource.BearerTokenError;
|
||||
import org.springframework.security.oauth2.server.resource.BearerTokenErrors;
|
||||
import org.springframework.security.oauth2.server.resource.InvalidBearerTokenException;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthentication;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.resource.introspection.BadOpaqueTokenException;
|
||||
import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionAuthenticatedPrincipal;
|
||||
import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionException;
|
||||
import org.springframework.security.saml2.Saml2Exception;
|
||||
import org.springframework.security.saml2.core.Saml2Error;
|
||||
import org.springframework.security.saml2.core.Saml2X509Credential;
|
||||
import org.springframework.security.saml2.credentials.TestSaml2X509Credentials;
|
||||
import org.springframework.security.saml2.provider.service.authentication.DefaultSaml2AuthenticatedPrincipal;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationToken;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2PostAuthenticationRequest;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2RedirectAuthenticationRequest;
|
||||
import org.springframework.security.saml2.provider.service.authentication.TestSaml2AuthenticationTokens;
|
||||
import org.springframework.security.saml2.provider.service.authentication.TestSaml2Authentications;
|
||||
import org.springframework.security.saml2.provider.service.authentication.TestSaml2PostAuthenticationRequests;
|
||||
import org.springframework.security.saml2.provider.service.authentication.TestSaml2RedirectAuthenticationRequests;
|
||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
|
||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration.AssertingPartyDetails;
|
||||
import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations;
|
||||
import org.springframework.security.web.PortResolverImpl;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetails;
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedCredentialsNotFoundException;
|
||||
import org.springframework.security.web.authentication.rememberme.CookieTheftException;
|
||||
import org.springframework.security.web.authentication.rememberme.InvalidCookieException;
|
||||
import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationException;
|
||||
import org.springframework.security.web.authentication.session.SessionAuthenticationException;
|
||||
import org.springframework.security.web.authentication.session.SessionFixationProtectionEvent;
|
||||
import org.springframework.security.web.authentication.switchuser.AuthenticationSwitchUserEvent;
|
||||
import org.springframework.security.web.authentication.www.NonceExpiredException;
|
||||
import org.springframework.security.web.csrf.CsrfException;
|
||||
import org.springframework.security.web.csrf.DefaultCsrfToken;
|
||||
import org.springframework.security.web.csrf.InvalidCsrfTokenException;
|
||||
import org.springframework.security.web.csrf.MissingCsrfTokenException;
|
||||
import org.springframework.security.web.firewall.RequestRejectedException;
|
||||
import org.springframework.security.web.savedrequest.DefaultSavedRequest;
|
||||
import org.springframework.security.web.savedrequest.SimpleSavedRequest;
|
||||
import org.springframework.security.web.server.firewall.ServerExchangeRejectedException;
|
||||
import org.springframework.security.web.session.HttpSessionCreatedEvent;
|
||||
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientInputs;
|
||||
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientOutputs;
|
||||
import org.springframework.security.web.webauthn.api.AuthenticatorAssertionResponse;
|
||||
import org.springframework.security.web.webauthn.api.AuthenticatorAttachment;
|
||||
import org.springframework.security.web.webauthn.api.AuthenticatorTransport;
|
||||
import org.springframework.security.web.webauthn.api.Bytes;
|
||||
import org.springframework.security.web.webauthn.api.CredProtectAuthenticationExtensionsClientInput;
|
||||
import org.springframework.security.web.webauthn.api.CredentialPropertiesOutput;
|
||||
import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExtensionsClientInput;
|
||||
import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExtensionsClientInputs;
|
||||
import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExtensionsClientOutputs;
|
||||
import org.springframework.security.web.webauthn.api.ImmutablePublicKeyCredentialUserEntity;
|
||||
import org.springframework.security.web.webauthn.api.PublicKeyCredential;
|
||||
import org.springframework.security.web.webauthn.api.PublicKeyCredentialDescriptor;
|
||||
import org.springframework.security.web.webauthn.api.PublicKeyCredentialRequestOptions;
|
||||
import org.springframework.security.web.webauthn.api.PublicKeyCredentialType;
|
||||
import org.springframework.security.web.webauthn.api.PublicKeyCredentialUserEntity;
|
||||
import org.springframework.security.web.webauthn.api.TestAuthenticationAssertionResponses;
|
||||
import org.springframework.security.web.webauthn.api.TestBytes;
|
||||
import org.springframework.security.web.webauthn.api.TestPublicKeyCredential;
|
||||
import org.springframework.security.web.webauthn.api.TestPublicKeyCredentialRequestOptions;
|
||||
import org.springframework.security.web.webauthn.api.TestPublicKeyCredentialUserEntity;
|
||||
import org.springframework.security.web.webauthn.api.UserVerificationRequirement;
|
||||
import org.springframework.security.web.webauthn.authentication.WebAuthnAuthentication;
|
||||
import org.springframework.security.web.webauthn.authentication.WebAuthnAuthenticationRequestToken;
|
||||
import org.springframework.security.web.webauthn.management.RelyingPartyAuthenticationRequest;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
@@ -260,411 +65,12 @@ import static org.assertj.core.api.Assertions.fail;
|
||||
*/
|
||||
class SpringSecurityCoreVersionSerializableTests {
|
||||
|
||||
private static final Map<Class<?>, Generator<?>> generatorByClassName = new HashMap<>();
|
||||
|
||||
static final long securitySerialVersionUid = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
||||
|
||||
static Path currentVersionFolder = Paths.get("src/test/resources/serialized/" + getCurrentVersion());
|
||||
|
||||
static Path previousVersionFolder = Paths.get("src/test/resources/serialized/" + getPreviousVersion());
|
||||
|
||||
static {
|
||||
UserDetails user = TestAuthentication.user();
|
||||
Authentication authentication = TestAuthentication.authenticated(user);
|
||||
SecurityContext securityContext = new SecurityContextImpl(authentication);
|
||||
|
||||
// oauth2-core
|
||||
generatorByClassName.put(DefaultOAuth2User.class, (r) -> TestOAuth2Users.create());
|
||||
generatorByClassName.put(OAuth2AuthorizationRequest.class,
|
||||
(r) -> TestOAuth2AuthorizationRequests.request().build());
|
||||
generatorByClassName.put(OAuth2AuthorizationResponse.class,
|
||||
(r) -> TestOAuth2AuthorizationResponses.success().build());
|
||||
generatorByClassName.put(OAuth2UserAuthority.class, (r) -> new OAuth2UserAuthority(Map.of("username", "user")));
|
||||
generatorByClassName.put(OAuth2AuthorizationExchange.class, (r) -> TestOAuth2AuthorizationExchanges.success());
|
||||
generatorByClassName.put(OidcUserInfo.class, (r) -> OidcUserInfo.builder().email("email@example.com").build());
|
||||
generatorByClassName.put(SessionInformation.class,
|
||||
(r) -> new SessionInformation(user, r.alphanumeric(4), new Date(1704378933936L)));
|
||||
generatorByClassName.put(ReactiveSessionInformation.class,
|
||||
(r) -> new ReactiveSessionInformation(user, r.alphanumeric(4), Instant.ofEpochMilli(1704378933936L)));
|
||||
generatorByClassName.put(OAuth2AccessToken.class, (r) -> TestOAuth2AccessTokens.scopes("scope"));
|
||||
generatorByClassName.put(OAuth2DeviceCode.class,
|
||||
(r) -> new OAuth2DeviceCode("token", Instant.now(), Instant.now()));
|
||||
generatorByClassName.put(OAuth2RefreshToken.class,
|
||||
(r) -> new OAuth2RefreshToken("refreshToken", Instant.now(), Instant.now()));
|
||||
generatorByClassName.put(OAuth2UserCode.class,
|
||||
(r) -> new OAuth2UserCode("token", Instant.now(), Instant.now()));
|
||||
generatorByClassName.put(DefaultOidcUser.class, (r) -> TestOidcUsers.create());
|
||||
generatorByClassName.put(OidcUserAuthority.class,
|
||||
(r) -> new OidcUserAuthority(TestOidcIdTokens.idToken().build(),
|
||||
new OidcUserInfo(Map.of("claim", "value")), "claim"));
|
||||
generatorByClassName.put(OAuth2AuthenticationException.class,
|
||||
(r) -> new OAuth2AuthenticationException(new OAuth2Error("error", "description", "uri"), "message",
|
||||
new RuntimeException()));
|
||||
generatorByClassName.put(OAuth2AuthorizationException.class,
|
||||
(r) -> new OAuth2AuthorizationException(new OAuth2Error("error", "description", "uri"), "message",
|
||||
new RuntimeException()));
|
||||
|
||||
// oauth2-client
|
||||
ClientRegistration.Builder clientRegistrationBuilder = TestClientRegistrations.clientRegistration();
|
||||
ClientRegistration clientRegistration = clientRegistrationBuilder.build();
|
||||
WebAuthenticationDetails details = new WebAuthenticationDetails("remote", "sessionId");
|
||||
generatorByClassName.put(ClientRegistration.class, (r) -> clientRegistration);
|
||||
generatorByClassName.put(ClientRegistration.ProviderDetails.class,
|
||||
(r) -> clientRegistration.getProviderDetails());
|
||||
generatorByClassName.put(ClientRegistration.ProviderDetails.UserInfoEndpoint.class,
|
||||
(r) -> clientRegistration.getProviderDetails().getUserInfoEndpoint());
|
||||
generatorByClassName.put(ClientRegistration.Builder.class, (r) -> clientRegistrationBuilder);
|
||||
generatorByClassName.put(OAuth2AuthorizedClient.class,
|
||||
(r) -> new OAuth2AuthorizedClient(clientRegistration, "principal", TestOAuth2AccessTokens.noScopes()));
|
||||
generatorByClassName.put(OAuth2LoginAuthenticationToken.class, (r) -> {
|
||||
var token = new OAuth2LoginAuthenticationToken(clientRegistration,
|
||||
TestOAuth2AuthorizationExchanges.success());
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(OAuth2AuthorizationCodeAuthenticationToken.class, (r) -> {
|
||||
var token = TestOAuth2AuthorizationCodeAuthenticationTokens.authenticated();
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(OAuth2AuthenticationToken.class, (r) -> {
|
||||
var token = TestOAuth2AuthenticationTokens.authenticated();
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(OidcIdToken.class, (r) -> TestOidcIdTokens.idToken().build());
|
||||
generatorByClassName.put(OidcLogoutToken.class,
|
||||
(r) -> TestOidcLogoutTokens.withSessionId("issuer", "sessionId").issuedAt(Instant.now()).build());
|
||||
generatorByClassName.put(OidcSessionInformation.class, (r) -> TestOidcSessionInformations.create());
|
||||
generatorByClassName.put(DefaultOAuth2AuthenticatedPrincipal.class, (r) -> {
|
||||
OAuth2AuthenticatedPrincipal principal = TestOAuth2AuthenticatedPrincipals.active();
|
||||
return new DefaultOAuth2AuthenticatedPrincipal(principal.getName(), principal.getAttributes(),
|
||||
(Collection<GrantedAuthority>) principal.getAuthorities());
|
||||
});
|
||||
generatorByClassName.put(ClientAuthorizationException.class,
|
||||
(r) -> new ClientAuthorizationException(new OAuth2Error("error", "description", "uri"), "id", "message",
|
||||
new RuntimeException()));
|
||||
generatorByClassName.put(ClientAuthorizationRequiredException.class,
|
||||
(r) -> new ClientAuthorizationRequiredException("id"));
|
||||
|
||||
// oauth2-jose
|
||||
generatorByClassName.put(BadJwtException.class, (r) -> new BadJwtException("token", new RuntimeException()));
|
||||
generatorByClassName.put(JwtDecoderInitializationException.class,
|
||||
(r) -> new JwtDecoderInitializationException("message", new RuntimeException()));
|
||||
generatorByClassName.put(JwtEncodingException.class,
|
||||
(r) -> new JwtEncodingException("message", new RuntimeException()));
|
||||
generatorByClassName.put(JwtException.class, (r) -> new JwtException("message", new RuntimeException()));
|
||||
generatorByClassName.put(JwtValidationException.class,
|
||||
(r) -> new JwtValidationException("message", List.of(new OAuth2Error("error", "description", "uri"))));
|
||||
|
||||
// oauth2-jwt
|
||||
generatorByClassName.put(Jwt.class, (r) -> TestJwts.user());
|
||||
|
||||
// oauth2-resource-server
|
||||
generatorByClassName
|
||||
.put(org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken.class, (r) -> {
|
||||
var token = new org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken(
|
||||
"token");
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(BearerTokenAuthenticationToken.class, (r) -> {
|
||||
var token = new BearerTokenAuthenticationToken("token");
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(BearerTokenAuthentication.class, (r) -> {
|
||||
var token = new BearerTokenAuthentication(TestOAuth2AuthenticatedPrincipals.active(),
|
||||
TestOAuth2AccessTokens.noScopes(), user.getAuthorities());
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(JwtAuthenticationToken.class, (r) -> {
|
||||
var token = new JwtAuthenticationToken(TestJwts.user());
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(BearerTokenError.class, (r) -> BearerTokenErrors.invalidToken("invalid token"));
|
||||
generatorByClassName.put(OAuth2IntrospectionAuthenticatedPrincipal.class,
|
||||
(r) -> TestOAuth2AuthenticatedPrincipals.active());
|
||||
generatorByClassName.put(InvalidBearerTokenException.class,
|
||||
(r) -> new InvalidBearerTokenException("description", new RuntimeException()));
|
||||
generatorByClassName.put(BadOpaqueTokenException.class,
|
||||
(r) -> new BadOpaqueTokenException("message", new RuntimeException()));
|
||||
generatorByClassName.put(OAuth2IntrospectionException.class,
|
||||
(r) -> new OAuth2IntrospectionException("message", new RuntimeException()));
|
||||
|
||||
// core
|
||||
generatorByClassName.put(RunAsUserToken.class, (r) -> {
|
||||
RunAsUserToken token = new RunAsUserToken("key", user, "creds", user.getAuthorities(),
|
||||
AnonymousAuthenticationToken.class);
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(RememberMeAuthenticationToken.class, (r) -> {
|
||||
RememberMeAuthenticationToken token = new RememberMeAuthenticationToken("key", user, user.getAuthorities());
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(UsernamePasswordAuthenticationToken.class, (r) -> {
|
||||
var token = UsernamePasswordAuthenticationToken.unauthenticated(user, "creds");
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(JaasAuthenticationToken.class, (r) -> {
|
||||
var token = new JaasAuthenticationToken(user, "creds", null);
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(OneTimeTokenAuthenticationToken.class,
|
||||
(r) -> applyDetails(new OneTimeTokenAuthenticationToken("username", "token")));
|
||||
generatorByClassName.put(AccessDeniedException.class,
|
||||
(r) -> new AccessDeniedException("access denied", new RuntimeException()));
|
||||
generatorByClassName.put(AuthorizationServiceException.class,
|
||||
(r) -> new AuthorizationServiceException("access denied", new RuntimeException()));
|
||||
generatorByClassName.put(AccountExpiredException.class,
|
||||
(r) -> new AccountExpiredException("error", new RuntimeException()));
|
||||
generatorByClassName.put(AuthenticationCredentialsNotFoundException.class,
|
||||
(r) -> new AuthenticationCredentialsNotFoundException("error", new RuntimeException()));
|
||||
generatorByClassName.put(AuthenticationServiceException.class,
|
||||
(r) -> new AuthenticationServiceException("error", new RuntimeException()));
|
||||
generatorByClassName.put(BadCredentialsException.class,
|
||||
(r) -> new BadCredentialsException("error", new RuntimeException()));
|
||||
generatorByClassName.put(CredentialsExpiredException.class,
|
||||
(r) -> new CredentialsExpiredException("error", new RuntimeException()));
|
||||
generatorByClassName.put(DisabledException.class,
|
||||
(r) -> new DisabledException("error", new RuntimeException()));
|
||||
generatorByClassName.put(InsufficientAuthenticationException.class,
|
||||
(r) -> new InsufficientAuthenticationException("error", new RuntimeException()));
|
||||
generatorByClassName.put(InternalAuthenticationServiceException.class,
|
||||
(r) -> new InternalAuthenticationServiceException("error", new RuntimeException()));
|
||||
generatorByClassName.put(LockedException.class, (r) -> new LockedException("error", new RuntimeException()));
|
||||
generatorByClassName.put(ProviderNotFoundException.class, (r) -> new ProviderNotFoundException("error"));
|
||||
generatorByClassName.put(InvalidOneTimeTokenException.class, (r) -> new InvalidOneTimeTokenException("error"));
|
||||
generatorByClassName.put(CompromisedPasswordException.class,
|
||||
(r) -> new CompromisedPasswordException("error", new RuntimeException()));
|
||||
generatorByClassName.put(UsernameNotFoundException.class,
|
||||
(r) -> new UsernameNotFoundException("error", new RuntimeException()));
|
||||
generatorByClassName.put(TestingAuthenticationToken.class,
|
||||
(r) -> applyDetails(new TestingAuthenticationToken("username", "password")));
|
||||
generatorByClassName.put(AuthenticationFailureBadCredentialsEvent.class,
|
||||
(r) -> new AuthenticationFailureBadCredentialsEvent(authentication,
|
||||
new BadCredentialsException("message")));
|
||||
generatorByClassName.put(AuthenticationFailureCredentialsExpiredEvent.class,
|
||||
(r) -> new AuthenticationFailureCredentialsExpiredEvent(authentication,
|
||||
new CredentialsExpiredException("message")));
|
||||
generatorByClassName.put(AuthenticationFailureDisabledEvent.class,
|
||||
(r) -> new AuthenticationFailureDisabledEvent(authentication, new DisabledException("message")));
|
||||
generatorByClassName.put(AuthenticationFailureExpiredEvent.class,
|
||||
(r) -> new AuthenticationFailureExpiredEvent(authentication, new AccountExpiredException("message")));
|
||||
generatorByClassName.put(AuthenticationFailureLockedEvent.class,
|
||||
(r) -> new AuthenticationFailureLockedEvent(authentication, new LockedException("message")));
|
||||
generatorByClassName.put(AuthenticationFailureProviderNotFoundEvent.class,
|
||||
(r) -> new AuthenticationFailureProviderNotFoundEvent(authentication,
|
||||
new ProviderNotFoundException("message")));
|
||||
generatorByClassName.put(AuthenticationFailureProxyUntrustedEvent.class,
|
||||
(r) -> new AuthenticationFailureProxyUntrustedEvent(authentication,
|
||||
new AuthenticationServiceException("message")));
|
||||
generatorByClassName.put(AuthenticationFailureServiceExceptionEvent.class,
|
||||
(r) -> new AuthenticationFailureServiceExceptionEvent(authentication,
|
||||
new AuthenticationServiceException("message")));
|
||||
generatorByClassName.put(AuthenticationSuccessEvent.class,
|
||||
(r) -> new AuthenticationSuccessEvent(authentication));
|
||||
generatorByClassName.put(InteractiveAuthenticationSuccessEvent.class,
|
||||
(r) -> new InteractiveAuthenticationSuccessEvent(authentication, Authentication.class));
|
||||
generatorByClassName.put(LogoutSuccessEvent.class, (r) -> new LogoutSuccessEvent(authentication));
|
||||
generatorByClassName.put(JaasAuthenticationFailedEvent.class,
|
||||
(r) -> new JaasAuthenticationFailedEvent(authentication, new RuntimeException("message")));
|
||||
generatorByClassName.put(JaasAuthenticationSuccessEvent.class,
|
||||
(r) -> new JaasAuthenticationSuccessEvent(authentication));
|
||||
generatorByClassName.put(AbstractSessionEvent.class, (r) -> new AbstractSessionEvent(securityContext));
|
||||
generatorByClassName.put(SecurityConfig.class, (r) -> new SecurityConfig("value"));
|
||||
generatorByClassName.put(TransientSecurityContext.class, (r) -> new TransientSecurityContext(authentication));
|
||||
generatorByClassName.put(AuthorizationDeniedException.class,
|
||||
(r) -> new AuthorizationDeniedException("message", new AuthorizationDecision(false)));
|
||||
generatorByClassName.put(AuthorizationDecision.class, (r) -> new AuthorizationDecision(true));
|
||||
generatorByClassName.put(AuthorityAuthorizationDecision.class,
|
||||
(r) -> new AuthorityAuthorizationDecision(true, AuthorityUtils.createAuthorityList("ROLE_USER")));
|
||||
|
||||
// cas
|
||||
generatorByClassName.put(CasServiceTicketAuthenticationToken.class, (r) -> {
|
||||
CasServiceTicketAuthenticationToken token = CasServiceTicketAuthenticationToken.stateless("creds");
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(CasAuthenticationToken.class, (r) -> {
|
||||
var token = new CasAuthenticationToken("key", user, "Password", user.getAuthorities(), user,
|
||||
new AssertionImpl("test"));
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(CasAssertionAuthenticationToken.class, (r) -> {
|
||||
var token = new CasAssertionAuthenticationToken(new AssertionImpl("test"), "ticket");
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
|
||||
// ldap
|
||||
generatorByClassName.put(LdapAuthority.class,
|
||||
(r) -> new LdapAuthority("USER", "username", Map.of("attribute", List.of("value1", "value2"))));
|
||||
generatorByClassName.put(PasswordPolicyException.class,
|
||||
(r) -> new PasswordPolicyException(PasswordPolicyErrorStatus.INSUFFICIENT_PASSWORD_QUALITY));
|
||||
generatorByClassName.put(PasswordPolicyControl.class, (r) -> new PasswordPolicyControl(true));
|
||||
generatorByClassName.put(PasswordPolicyResponseControl.class, (r) -> {
|
||||
byte[] encodedResponse = { 0x30, 0x05, (byte) 0xA0, 0x03, (byte) 0xA0, 0x1, 0x21 };
|
||||
return new PasswordPolicyResponseControl(encodedResponse);
|
||||
});
|
||||
|
||||
// saml2-service-provider
|
||||
generatorByClassName.put(Saml2AuthenticationException.class,
|
||||
(r) -> new Saml2AuthenticationException(new Saml2Error("code", "descirption"), "message",
|
||||
new IOException("fail")));
|
||||
generatorByClassName.put(Saml2Exception.class, (r) -> new Saml2Exception("message", new IOException("fail")));
|
||||
generatorByClassName.put(DefaultSaml2AuthenticatedPrincipal.class,
|
||||
(r) -> TestSaml2Authentications.authentication().getPrincipal());
|
||||
generatorByClassName.put(Saml2Authentication.class,
|
||||
(r) -> applyDetails(TestSaml2Authentications.authentication()));
|
||||
generatorByClassName.put(Saml2PostAuthenticationRequest.class,
|
||||
(r) -> TestSaml2PostAuthenticationRequests.create());
|
||||
generatorByClassName.put(Saml2RedirectAuthenticationRequest.class,
|
||||
(r) -> TestSaml2RedirectAuthenticationRequests.create());
|
||||
generatorByClassName.put(Saml2X509Credential.class,
|
||||
(r) -> TestSaml2X509Credentials.relyingPartyVerifyingCredential());
|
||||
generatorByClassName.put(AssertingPartyDetails.class,
|
||||
(r) -> TestRelyingPartyRegistrations.full().build().getAssertingPartyMetadata());
|
||||
generatorByClassName.put(RelyingPartyRegistration.class, (r) -> TestRelyingPartyRegistrations.full().build());
|
||||
generatorByClassName.put(Saml2AuthenticationToken.class, (r) -> {
|
||||
Saml2AuthenticationToken token = TestSaml2AuthenticationTokens.tokenRequested();
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
|
||||
// web
|
||||
generatorByClassName.put(AnonymousAuthenticationToken.class, (r) -> {
|
||||
Collection<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("ROLE_USER");
|
||||
return applyDetails(new AnonymousAuthenticationToken("key", "username", authorities));
|
||||
});
|
||||
generatorByClassName.put(PreAuthenticatedAuthenticationToken.class, (r) -> {
|
||||
PreAuthenticatedAuthenticationToken token = new PreAuthenticatedAuthenticationToken(user, "creds",
|
||||
user.getAuthorities());
|
||||
token.setDetails(details);
|
||||
return token;
|
||||
});
|
||||
generatorByClassName.put(PreAuthenticatedCredentialsNotFoundException.class,
|
||||
(r) -> new PreAuthenticatedCredentialsNotFoundException("message", new IOException("fail")));
|
||||
generatorByClassName.put(CookieTheftException.class, (r) -> new CookieTheftException("message"));
|
||||
generatorByClassName.put(InvalidCookieException.class, (r) -> new InvalidCookieException("message"));
|
||||
generatorByClassName.put(RememberMeAuthenticationException.class,
|
||||
(r) -> new RememberMeAuthenticationException("message", new IOException("fail")));
|
||||
generatorByClassName.put(SessionAuthenticationException.class,
|
||||
(r) -> new SessionAuthenticationException("message"));
|
||||
generatorByClassName.put(NonceExpiredException.class,
|
||||
(r) -> new NonceExpiredException("message", new IOException("fail")));
|
||||
generatorByClassName.put(CsrfException.class, (r) -> new CsrfException("message"));
|
||||
generatorByClassName.put(org.springframework.security.web.server.csrf.CsrfException.class,
|
||||
(r) -> new org.springframework.security.web.server.csrf.CsrfException("message"));
|
||||
generatorByClassName.put(InvalidCsrfTokenException.class,
|
||||
(r) -> new InvalidCsrfTokenException(new DefaultCsrfToken("header", "parameter", "token"), "token"));
|
||||
generatorByClassName.put(MissingCsrfTokenException.class, (r) -> new MissingCsrfTokenException("token"));
|
||||
generatorByClassName.put(DefaultCsrfToken.class, (r) -> new DefaultCsrfToken("header", "parameter", "token"));
|
||||
generatorByClassName.put(org.springframework.security.web.server.csrf.DefaultCsrfToken.class,
|
||||
(r) -> new org.springframework.security.web.server.csrf.DefaultCsrfToken("header", "parameter",
|
||||
"token"));
|
||||
generatorByClassName.put(RequestRejectedException.class, (r) -> new RequestRejectedException("message"));
|
||||
generatorByClassName.put(ServerExchangeRejectedException.class,
|
||||
(r) -> new ServerExchangeRejectedException("message"));
|
||||
generatorByClassName.put(SessionFixationProtectionEvent.class,
|
||||
(r) -> new SessionFixationProtectionEvent(authentication, "old", "new"));
|
||||
generatorByClassName.put(AuthenticationSwitchUserEvent.class,
|
||||
(r) -> new AuthenticationSwitchUserEvent(authentication, user));
|
||||
generatorByClassName.put(HttpSessionCreatedEvent.class,
|
||||
(r) -> new HttpSessionCreatedEvent(new MockHttpSession()));
|
||||
generatorByClassName.put(SimpleSavedRequest.class, (r) -> {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/uri");
|
||||
request.setQueryString("query=string");
|
||||
request.setScheme("https");
|
||||
request.setServerName("localhost");
|
||||
request.setServerPort(80);
|
||||
request.setRequestURI("/uri");
|
||||
request.setCookies(new Cookie("name", "value"));
|
||||
request.addHeader("header", "value");
|
||||
request.addParameter("parameter", "value");
|
||||
request.setPathInfo("/path");
|
||||
request.addPreferredLocale(Locale.ENGLISH);
|
||||
return new SimpleSavedRequest(new DefaultSavedRequest(request, new PortResolverImpl(), "continue"));
|
||||
});
|
||||
|
||||
// webauthn
|
||||
generatorByClassName.put(Bytes.class, (r) -> TestBytes.get());
|
||||
generatorByClassName.put(ImmutablePublicKeyCredentialUserEntity.class,
|
||||
(r) -> TestPublicKeyCredentialUserEntity.userEntity().id(TestBytes.get()).build());
|
||||
generatorByClassName.put(WebAuthnAuthentication.class, (r) -> {
|
||||
PublicKeyCredentialUserEntity userEntity = TestPublicKeyCredentialUserEntity.userEntity()
|
||||
.id(TestBytes.get())
|
||||
.build();
|
||||
List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("ROLE_USER");
|
||||
WebAuthnAuthentication webAuthnAuthentication = new WebAuthnAuthentication(userEntity, authorities);
|
||||
webAuthnAuthentication.setDetails(details);
|
||||
return webAuthnAuthentication;
|
||||
});
|
||||
|
||||
// webauthn
|
||||
CredProtectAuthenticationExtensionsClientInput.CredProtect credProtect = new CredProtectAuthenticationExtensionsClientInput.CredProtect(
|
||||
CredProtectAuthenticationExtensionsClientInput.CredProtect.ProtectionPolicy.USER_VERIFICATION_OPTIONAL,
|
||||
true);
|
||||
Bytes id = TestBytes.get();
|
||||
AuthenticationExtensionsClientInputs inputs = new ImmutableAuthenticationExtensionsClientInputs(
|
||||
ImmutableAuthenticationExtensionsClientInput.credProps);
|
||||
// @formatter:off
|
||||
PublicKeyCredentialDescriptor descriptor = PublicKeyCredentialDescriptor.builder()
|
||||
.id(id)
|
||||
.type(PublicKeyCredentialType.PUBLIC_KEY)
|
||||
.transports(Set.of(AuthenticatorTransport.USB))
|
||||
.build();
|
||||
// @formatter:on
|
||||
generatorByClassName.put(AuthenticatorTransport.class, (a) -> AuthenticatorTransport.USB);
|
||||
generatorByClassName.put(PublicKeyCredentialType.class, (k) -> PublicKeyCredentialType.PUBLIC_KEY);
|
||||
generatorByClassName.put(UserVerificationRequirement.class, (r) -> UserVerificationRequirement.REQUIRED);
|
||||
generatorByClassName.put(CredProtectAuthenticationExtensionsClientInput.CredProtect.class, (c) -> credProtect);
|
||||
generatorByClassName.put(CredProtectAuthenticationExtensionsClientInput.class,
|
||||
(c) -> new CredProtectAuthenticationExtensionsClientInput(credProtect));
|
||||
generatorByClassName.put(ImmutableAuthenticationExtensionsClientInputs.class, (i) -> inputs);
|
||||
Field credPropsField = ReflectionUtils.findField(ImmutableAuthenticationExtensionsClientInput.class,
|
||||
"credProps");
|
||||
generatorByClassName.put(credPropsField.getType(),
|
||||
(i) -> ImmutableAuthenticationExtensionsClientInput.credProps);
|
||||
generatorByClassName.put(Bytes.class, (b) -> id);
|
||||
generatorByClassName.put(PublicKeyCredentialDescriptor.class, (d) -> descriptor);
|
||||
// @formatter:off
|
||||
generatorByClassName.put(PublicKeyCredentialRequestOptions.class, (o) -> TestPublicKeyCredentialRequestOptions.create()
|
||||
.extensions(inputs)
|
||||
.allowCredentials(List.of(descriptor))
|
||||
.build()
|
||||
);
|
||||
|
||||
CredentialPropertiesOutput credentialOutput = new CredentialPropertiesOutput(false);
|
||||
AuthenticationExtensionsClientOutputs outputs = new ImmutableAuthenticationExtensionsClientOutputs(credentialOutput);
|
||||
AuthenticatorAssertionResponse response = TestAuthenticationAssertionResponses.createAuthenticatorAssertionResponse()
|
||||
.build();
|
||||
PublicKeyCredential<AuthenticatorAssertionResponse> credential = TestPublicKeyCredential.createPublicKeyCredential(
|
||||
response, outputs)
|
||||
.build();
|
||||
RelyingPartyAuthenticationRequest authRequest = new RelyingPartyAuthenticationRequest(
|
||||
TestPublicKeyCredentialRequestOptions.create().build(),
|
||||
credential
|
||||
);
|
||||
WebAuthnAuthenticationRequestToken requestToken = new WebAuthnAuthenticationRequestToken(authRequest);
|
||||
requestToken.setDetails(details);
|
||||
generatorByClassName.put(CredentialPropertiesOutput.class, (o) -> credentialOutput);
|
||||
generatorByClassName.put(ImmutableAuthenticationExtensionsClientOutputs.class, (o) -> outputs);
|
||||
generatorByClassName.put(AuthenticatorAssertionResponse.class, (r) -> response);
|
||||
generatorByClassName.put(RelyingPartyAuthenticationRequest.class, (r) -> authRequest);
|
||||
generatorByClassName.put(PublicKeyCredential.class, (r) -> credential);
|
||||
generatorByClassName.put(WebAuthnAuthenticationRequestToken.class, (r) -> requestToken);
|
||||
generatorByClassName.put(AuthenticatorAttachment.class, (r) -> AuthenticatorAttachment.PLATFORM);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("getClassesToSerialize")
|
||||
@Disabled("This method should only be used to serialize the classes once")
|
||||
@@ -676,7 +82,7 @@ class SpringSecurityCoreVersionSerializableTests {
|
||||
return;
|
||||
}
|
||||
Files.createFile(filePath);
|
||||
Object instance = instancioWithDefaults(clazz).create();
|
||||
Object instance = SerializationSamples.instancioWithDefaults(clazz).create();
|
||||
assertThat(instance).isInstanceOf(clazz);
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream(file);
|
||||
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream)) {
|
||||
@@ -690,7 +96,28 @@ class SpringSecurityCoreVersionSerializableTests {
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("getFilesToDeserialize")
|
||||
@MethodSource("getCurrentSerializedFiles")
|
||||
void shouldBeAbleToDeserializeClassFromCurrentVersion(Path filePath) {
|
||||
try (FileInputStream fileInputStream = new FileInputStream(filePath.toFile());
|
||||
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream)) {
|
||||
Object obj = objectInputStream.readObject();
|
||||
Class<?> clazz = Class.forName(filePath.getFileName().toString().replace(".serialized", ""));
|
||||
assertThat(obj).isInstanceOf(clazz);
|
||||
}
|
||||
catch (IOException | ClassNotFoundException ex) {
|
||||
fail("Could not deserialize " + filePath, ex);
|
||||
}
|
||||
}
|
||||
|
||||
static Stream<Path> getCurrentSerializedFiles() throws Exception {
|
||||
assertThat(currentVersionFolder.toFile().exists())
|
||||
.as("Make sure that the " + currentVersionFolder + " exists and is not empty")
|
||||
.isTrue();
|
||||
return getClassesToSerialize().map((clazz) -> currentVersionFolder.resolve(clazz.getName() + ".serialized"));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("getPreviousSerializedFiles")
|
||||
void shouldBeAbleToDeserializeClassFromPreviousVersion(Path filePath) {
|
||||
try (FileInputStream fileInputStream = new FileInputStream(filePath.toFile());
|
||||
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream)) {
|
||||
@@ -703,7 +130,7 @@ class SpringSecurityCoreVersionSerializableTests {
|
||||
}
|
||||
}
|
||||
|
||||
static Stream<Path> getFilesToDeserialize() throws IOException {
|
||||
static Stream<Path> getPreviousSerializedFiles() throws IOException {
|
||||
assertThat(previousVersionFolder.toFile().exists())
|
||||
.as("Make sure that the " + previousVersionFolder + " exists and is not empty")
|
||||
.isTrue();
|
||||
@@ -739,10 +166,18 @@ class SpringSecurityCoreVersionSerializableTests {
|
||||
|| Arrays.asList(suppressWarnings.value()).contains("Serial");
|
||||
if (!hasSerialVersion && !hasSerialIgnore) {
|
||||
classes.add(clazz);
|
||||
continue;
|
||||
}
|
||||
boolean isReachable = Modifier.isPublic(clazz.getModifiers());
|
||||
boolean hasSampleSerialization = currentVersionFolder.resolve(clazz.getName() + ".serialized")
|
||||
.toFile()
|
||||
.exists();
|
||||
if (hasSerialVersion && isReachable && !hasSampleSerialization) {
|
||||
classes.add(clazz);
|
||||
}
|
||||
}
|
||||
assertThat(classes)
|
||||
.describedAs("Found Serializable classes that are either missing a serialVersionUID or a @SuppressWarnings")
|
||||
assertThat(classes).describedAs(
|
||||
"Found Serializable classes that are either missing a serialVersionUID or a @SuppressWarnings or a sample serialized file")
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
@@ -760,7 +195,7 @@ class SpringSecurityCoreVersionSerializableTests {
|
||||
}
|
||||
boolean matchesExpectedSerialVersion = ObjectStreamClass.lookup(clazz)
|
||||
.getSerialVersionUID() == securitySerialVersionUid;
|
||||
boolean isUnderTest = generatorByClassName.containsKey(clazz);
|
||||
boolean isUnderTest = SerializationSamples.generatorByClassName.containsKey(clazz);
|
||||
if (matchesExpectedSerialVersion || isUnderTest) {
|
||||
classes.add(clazz);
|
||||
}
|
||||
@@ -768,24 +203,6 @@ class SpringSecurityCoreVersionSerializableTests {
|
||||
return classes.stream();
|
||||
}
|
||||
|
||||
private static InstancioApi<?> instancioWithDefaults(Class<?> clazz) {
|
||||
InstancioOfClassApi<?> instancio = Instancio.of(clazz);
|
||||
ResolvableType[] generics = ResolvableType.forClass(clazz).getGenerics();
|
||||
for (ResolvableType type : generics) {
|
||||
instancio.withTypeParameters(type.resolve());
|
||||
}
|
||||
if (generatorByClassName.containsKey(clazz)) {
|
||||
instancio.supply(Select.all(clazz), generatorByClassName.get(clazz));
|
||||
}
|
||||
return instancio;
|
||||
}
|
||||
|
||||
private static <T extends AbstractAuthenticationToken> T applyDetails(T authentication) {
|
||||
WebAuthenticationDetails details = new WebAuthenticationDetails("remote", "sessionId");
|
||||
authentication.setDetails(details);
|
||||
return authentication;
|
||||
}
|
||||
|
||||
private static String getCurrentVersion() {
|
||||
String version = System.getProperty("springSecurityVersion");
|
||||
String[] parts = version.split("\\.");
|
||||
|
||||
+1
@@ -55,6 +55,7 @@ public class Authz {
|
||||
return Mono.just(checkResult(result));
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class AuthzResult extends AuthorizationDecision {
|
||||
|
||||
public AuthzResult(boolean granted) {
|
||||
|
||||
+17
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -56,6 +56,7 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.Role;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.annotation.AnnotationConfigurationException;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.access.PermissionEvaluator;
|
||||
@@ -1103,6 +1104,21 @@ public class PrePostMethodSecurityConfigurationTests {
|
||||
verifyNoInteractions(handler);
|
||||
}
|
||||
|
||||
// gh-16819
|
||||
@Test
|
||||
void autowireWhenDefaultsThenAdvisorAnnotationsAreSorted() {
|
||||
this.spring.register(MethodSecurityServiceConfig.class).autowire();
|
||||
AuthorizationAdvisorProxyFactory proxyFactory = this.spring.getContext()
|
||||
.getBean(AuthorizationAdvisorProxyFactory.class);
|
||||
AnnotationAwareOrderComparator comparator = AnnotationAwareOrderComparator.INSTANCE;
|
||||
AuthorizationAdvisor previous = null;
|
||||
for (AuthorizationAdvisor advisor : proxyFactory) {
|
||||
boolean ordered = previous == null || comparator.compare(previous, advisor) < 0;
|
||||
assertThat(ordered).isTrue();
|
||||
previous = advisor;
|
||||
}
|
||||
}
|
||||
|
||||
private static Consumer<ConfigurableWebApplicationContext> disallowBeanOverriding() {
|
||||
return (context) -> ((AnnotationConfigWebApplicationContext) context).setAllowBeanDefinitionOverriding(false);
|
||||
}
|
||||
|
||||
+4
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -1560,12 +1560,15 @@ public class OAuth2ResourceServerConfigurerTests {
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
DefaultBearerTokenResolver defaultBearerTokenResolver = new DefaultBearerTokenResolver();
|
||||
defaultBearerTokenResolver.setAllowUriQueryParameter(true);
|
||||
http
|
||||
.authorizeRequests()
|
||||
.requestMatchers("/requires-read-scope").access("hasAuthority('SCOPE_message:read')")
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.oauth2ResourceServer()
|
||||
.bearerTokenResolver(defaultBearerTokenResolver)
|
||||
.jwt()
|
||||
.jwkSetUri(this.jwkSetUri);
|
||||
return http.build();
|
||||
|
||||
@@ -336,6 +336,43 @@ public class CsrfConfigTests {
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postWhenUsingCsrfAndXorCsrfTokenRequestAttributeHandlerThenCsrfAuthenticationStrategyUses()
|
||||
throws Exception {
|
||||
this.spring.configLocations(this.xml("WithXorCsrfTokenRequestAttributeHandler"), this.xml("shared-controllers"))
|
||||
.autowire();
|
||||
// @formatter:off
|
||||
MvcResult mvcResult1 = this.mvc.perform(get("/csrf"))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
MockHttpServletRequest request1 = mvcResult1.getRequest();
|
||||
MockHttpSession session = (MockHttpSession) request1.getSession();
|
||||
CsrfTokenRepository repository = WebTestUtils.getCsrfTokenRepository(request1);
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder login = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.session(session)
|
||||
.with(csrf());
|
||||
this.mvc.perform(login)
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("/"));
|
||||
// @formatter:on
|
||||
assertThat(repository.loadToken(request1)).isNull();
|
||||
// @formatter:off
|
||||
MvcResult mvcResult2 = this.mvc.perform(get("/csrf").session(session))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
MockHttpServletRequest request2 = mvcResult2.getRequest();
|
||||
CsrfToken csrfToken = repository.loadToken(request2);
|
||||
CsrfToken csrfTokenAttribute = (CsrfToken) request2.getAttribute(CsrfToken.class.getName());
|
||||
assertThat(csrfTokenAttribute).isNotNull();
|
||||
assertThat(csrfTokenAttribute.getToken()).isNotBlank();
|
||||
assertThat(csrfTokenAttribute.getToken()).isNotEqualTo(csrfToken.getToken());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postWhenHasCsrfTokenButSessionExpiresThenRequestIsCancelledAfterSuccessfulAuthentication()
|
||||
throws Exception {
|
||||
|
||||
+6
-1
@@ -25,10 +25,15 @@
|
||||
|
||||
<c:property-placeholder local-override="true"/>
|
||||
|
||||
<b:bean id="bearerTokenResolver"
|
||||
class="org.springframework.security.oauth2.server.resource.web.DefaultBearerTokenResolver">
|
||||
<b:property name="allowUriQueryParameter" value="true"/>
|
||||
</b:bean>
|
||||
|
||||
<http>
|
||||
<intercept-url pattern="/**" access="authenticated"/>
|
||||
<intercept-url pattern="/requires-read-scope" access="hasAuthority('SCOPE_message:read')"/>
|
||||
<oauth2-resource-server>
|
||||
<oauth2-resource-server bearer-token-resolver-ref="bearerTokenResolver">
|
||||
<jwt jwk-set-uri="${jwk-set-uri:https://idp.example.org}"/>
|
||||
</oauth2-resource-server>
|
||||
</http>
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
+14
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -47,6 +47,7 @@ import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.framework.AopInfrastructureBean;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.security.authorization.AuthorizationProxyFactory;
|
||||
@@ -79,8 +80,8 @@ import org.springframework.util.ClassUtils;
|
||||
* @author Josh Cummings
|
||||
* @since 6.3
|
||||
*/
|
||||
public final class AuthorizationAdvisorProxyFactory
|
||||
implements AuthorizationProxyFactory, Iterable<AuthorizationAdvisor>, AopInfrastructureBean {
|
||||
public final class AuthorizationAdvisorProxyFactory implements AuthorizationProxyFactory,
|
||||
Iterable<AuthorizationAdvisor>, AopInfrastructureBean, SmartInitializingSingleton {
|
||||
|
||||
private static final boolean isReactivePresent = ClassUtils.isPresent("reactor.core.publisher.Mono", null);
|
||||
|
||||
@@ -125,6 +126,7 @@ public final class AuthorizationAdvisorProxyFactory
|
||||
advisors.add(new PostFilterAuthorizationMethodInterceptor());
|
||||
AuthorizationAdvisorProxyFactory proxyFactory = new AuthorizationAdvisorProxyFactory(advisors);
|
||||
proxyFactory.addAdvisor(new AuthorizeReturnObjectMethodInterceptor(proxyFactory));
|
||||
AnnotationAwareOrderComparator.sort(proxyFactory.advisors);
|
||||
return proxyFactory;
|
||||
}
|
||||
|
||||
@@ -142,9 +144,15 @@ public final class AuthorizationAdvisorProxyFactory
|
||||
advisors.add(new PostFilterAuthorizationReactiveMethodInterceptor());
|
||||
AuthorizationAdvisorProxyFactory proxyFactory = new AuthorizationAdvisorProxyFactory(advisors);
|
||||
proxyFactory.addAdvisor(new AuthorizeReturnObjectMethodInterceptor(proxyFactory));
|
||||
AnnotationAwareOrderComparator.sort(proxyFactory.advisors);
|
||||
return proxyFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterSingletonsInstantiated() {
|
||||
AnnotationAwareOrderComparator.sort(this.advisors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy an object to enforce authorization advice.
|
||||
*
|
||||
@@ -165,7 +173,6 @@ public final class AuthorizationAdvisorProxyFactory
|
||||
*/
|
||||
@Override
|
||||
public Object proxy(Object target) {
|
||||
AnnotationAwareOrderComparator.sort(this.advisors);
|
||||
if (target == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -178,9 +185,9 @@ public final class AuthorizationAdvisorProxyFactory
|
||||
}
|
||||
ProxyFactory factory = new ProxyFactory(target);
|
||||
factory.addAdvisors(this.authorizationProxy);
|
||||
for (Advisor advisor : this.advisors) {
|
||||
factory.addAdvisors(advisor);
|
||||
}
|
||||
List<Advisor> advisors = new ArrayList<>(this.advisors);
|
||||
AnnotationAwareOrderComparator.sort(advisors);
|
||||
factory.addAdvisors(advisors);
|
||||
factory.addInterface(AuthorizationProxy.class);
|
||||
factory.setOpaque(true);
|
||||
factory.setProxyTargetClass(!Modifier.isFinal(target.getClass().getModifiers()));
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -48,7 +48,7 @@ public final class AuthorizeReturnObjectMethodInterceptor implements Authorizati
|
||||
private int order = AuthorizationInterceptorsOrder.SECURE_RESULT.getOrder();
|
||||
|
||||
public AuthorizeReturnObjectMethodInterceptor(AuthorizationProxyFactory authorizationProxyFactory) {
|
||||
Assert.notNull(authorizationProxyFactory, "authorizationManager cannot be null");
|
||||
Assert.notNull(authorizationProxyFactory, "authorizationProxyFactory cannot be null");
|
||||
this.authorizationProxyFactory = authorizationProxyFactory;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -214,7 +214,7 @@ final class UniqueSecurityAnnotationScanner<A extends Annotation> extends Abstra
|
||||
|
||||
private static Method findMethod(Method method, Class<?> targetClass) {
|
||||
for (Method candidate : targetClass.getDeclaredMethods()) {
|
||||
if (candidate == method) {
|
||||
if (candidate.equals(method)) {
|
||||
return candidate;
|
||||
}
|
||||
if (isOverride(method, candidate)) {
|
||||
|
||||
+1
-4
@@ -16,18 +16,15 @@
|
||||
|
||||
package org.springframework.security.access.annotation;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Joe Scalise
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class BusinessServiceImpl<E extends Entity> implements BusinessService {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = -4249394090237180795L;
|
||||
|
||||
@Override
|
||||
@Secured({ "ROLE_USER" })
|
||||
public void someUserMethod1() {
|
||||
|
||||
+1
-4
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.security.access.annotation;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -24,11 +23,9 @@ import org.springframework.security.access.prepost.PostFilter;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.access.prepost.PreFilter;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class ExpressionProtectedBusinessServiceImpl implements BusinessService {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = -3320014879907436606L;
|
||||
|
||||
@Override
|
||||
public void someAdminMethod() {
|
||||
}
|
||||
|
||||
+1
-4
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.security.access.annotation;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -27,11 +26,9 @@ import jakarta.annotation.security.RolesAllowed;
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
@PermitAll
|
||||
@SuppressWarnings("serial")
|
||||
public class Jsr250BusinessServiceImpl implements BusinessService {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = -7550211450382764339L;
|
||||
|
||||
@Override
|
||||
@RolesAllowed("ROLE_USER")
|
||||
public void someUserMethod1() {
|
||||
|
||||
+28
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -40,6 +40,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.authentication.TestAuthentication;
|
||||
@@ -360,6 +361,32 @@ public class AuthorizationAdvisorProxyFactoryTests {
|
||||
assertThat(target).isSameAs(this.flight);
|
||||
}
|
||||
|
||||
// gh-16819
|
||||
@Test
|
||||
void advisorsWhenWithDefaultsThenAreSorted() {
|
||||
AuthorizationAdvisorProxyFactory proxyFactory = AuthorizationAdvisorProxyFactory.withDefaults();
|
||||
AnnotationAwareOrderComparator comparator = AnnotationAwareOrderComparator.INSTANCE;
|
||||
AuthorizationAdvisor previous = null;
|
||||
for (AuthorizationAdvisor advisor : proxyFactory) {
|
||||
boolean ordered = previous == null || comparator.compare(previous, advisor) < 0;
|
||||
assertThat(ordered).isTrue();
|
||||
previous = advisor;
|
||||
}
|
||||
}
|
||||
|
||||
// gh-16819
|
||||
@Test
|
||||
void advisorsWhenWithReactiveDefaultsThenAreSorted() {
|
||||
AuthorizationAdvisorProxyFactory proxyFactory = AuthorizationAdvisorProxyFactory.withReactiveDefaults();
|
||||
AnnotationAwareOrderComparator comparator = AnnotationAwareOrderComparator.INSTANCE;
|
||||
AuthorizationAdvisor previous = null;
|
||||
for (AuthorizationAdvisor advisor : proxyFactory) {
|
||||
boolean ordered = previous == null || comparator.compare(previous, advisor) < 0;
|
||||
assertThat(ordered).isTrue();
|
||||
previous = advisor;
|
||||
}
|
||||
}
|
||||
|
||||
private Authentication authenticated(String user, String... authorities) {
|
||||
return TestAuthentication.authenticated(TestAuthentication.withUsername(user).authorities(authorities).build());
|
||||
}
|
||||
|
||||
+1
-1
@@ -111,7 +111,7 @@ final class Argon2EncodingUtils {
|
||||
case "argon2d" -> new Argon2Parameters.Builder(Argon2Parameters.ARGON2_d);
|
||||
case "argon2i" -> new Argon2Parameters.Builder(Argon2Parameters.ARGON2_i);
|
||||
case "argon2id" -> new Argon2Parameters.Builder(Argon2Parameters.ARGON2_id);
|
||||
default -> throw new IllegalArgumentException("Invalid algorithm type: " + parts[0]);
|
||||
default -> throw new IllegalArgumentException("Invalid algorithm type: " + parts[1]);
|
||||
};
|
||||
if (parts[currentPart].startsWith("v=")) {
|
||||
paramsBuilder.withVersion(Integer.parseInt(parts[currentPart].substring(2)));
|
||||
|
||||
@@ -611,7 +611,8 @@ public class BCrypt {
|
||||
int rounds, off;
|
||||
StringBuilder rs = new StringBuilder();
|
||||
|
||||
if (passwordb.length > 72) {
|
||||
// Enforce max length for new passwords only
|
||||
if (!for_check && passwordb.length > 72) {
|
||||
throw new IllegalArgumentException("password cannot be more than 72 bytes");
|
||||
}
|
||||
if (salt == null) {
|
||||
|
||||
+4
-2
@@ -94,8 +94,10 @@ public class Argon2EncodingUtilsTests {
|
||||
|
||||
@Test
|
||||
public void decodeWhenNonexistingAlgorithmThenThrowException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> Argon2EncodingUtils
|
||||
.decode("$argon2x$v=19$m=1024,t=3,p=2$Y1JkRmJDdzIzZ3oyTWx4aw$cGE5Cbd/cx7micVhXVBdH5qTr66JI1iUyuNNVAnErXs"));
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> Argon2EncodingUtils.decode(
|
||||
"$argon2x$v=19$m=1024,t=3,p=2$Y1JkRmJDdzIzZ3oyTWx4aw$cGE5Cbd/cx7micVhXVBdH5qTr66JI1iUyuNNVAnErXs"))
|
||||
.withMessageContaining("argon2x");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+26
-5
@@ -223,13 +223,34 @@ public class BCryptPasswordEncoderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enforcePasswordLength() {
|
||||
public void encodeWhenPasswordOverMaxLengthThenThrowIllegalArgumentException() {
|
||||
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
||||
|
||||
String password72chars = "123456789012345678901234567890123456789012345678901234567890123456789012";
|
||||
assertThat(encoder.matches(password72chars, encoder.encode(password72chars))).isTrue();
|
||||
String password73chars = password72chars.concat("a");
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> encoder.matches(password73chars, encoder.encode(password73chars)));
|
||||
encoder.encode(password72chars);
|
||||
|
||||
String password73chars = password72chars + "3";
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> encoder.encode(password73chars));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchesWhenPasswordOverMaxLengthThenAllowToMatch() {
|
||||
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
||||
|
||||
String password71chars = "12345678901234567890123456789012345678901234567890123456789012345678901";
|
||||
String encodedPassword71chars = "$2a$10$jx3x2FaF.iX5QZ9i3O424Os2Ou5P5JrnedmWYHuDyX8JKA4Unp4xq";
|
||||
assertThat(encoder.matches(password71chars, encodedPassword71chars)).isTrue();
|
||||
|
||||
String password72chars = password71chars + "2";
|
||||
String encodedPassword72chars = "$2a$10$oXYO6/UvbsH5rQEraBkl6uheccBqdB3n.RaWbrimog9hS2GX4lo/O";
|
||||
assertThat(encoder.matches(password72chars, encodedPassword72chars)).isTrue();
|
||||
|
||||
// Max length is 72 bytes, however, we need to ensure backwards compatibility
|
||||
// for previously encoded passwords that are greater than 72 bytes and allow the
|
||||
// match to be performed.
|
||||
String password73chars = password72chars + "3";
|
||||
String encodedPassword73chars = "$2a$10$1l9.kvQTsqNLiCYFqmKtQOHkp.BrgIrwsnTzWo9jdbQRbuBYQ/AVK";
|
||||
assertThat(encoder.matches(password73chars, encodedPassword73chars)).isTrue();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -86,6 +86,7 @@
|
||||
**** xref:servlet/saml2/login/authentication.adoc[SAML2 Authentication Responses]
|
||||
*** xref:servlet/saml2/logout.adoc[SAML2 Logout]
|
||||
*** xref:servlet/saml2/metadata.adoc[SAML2 Metadata]
|
||||
*** xref:servlet/saml2/saml-extension-migration.adoc[Migrating from Spring Security SAML Extension]
|
||||
** xref:servlet/exploits/index.adoc[Protection Against Exploits]
|
||||
*** xref:servlet/exploits/csrf.adoc[]
|
||||
*** xref:servlet/exploits/headers.adoc[]
|
||||
@@ -132,7 +133,7 @@
|
||||
*** xref:servlet/appendix/faq.adoc[FAQ]
|
||||
* xref:reactive/index.adoc[Reactive Applications]
|
||||
** xref:reactive/getting-started.adoc[Getting Started]
|
||||
** Authentication
|
||||
** xref:reactive/authentication/index.adoc[Authentication]
|
||||
*** xref:reactive/authentication/x509.adoc[X.509 Authentication]
|
||||
*** xref:reactive/authentication/logout.adoc[Logout]
|
||||
*** Session Management
|
||||
|
||||
@@ -8,4 +8,4 @@ Once authentication is performed we know the identity and can perform authorizat
|
||||
|
||||
Spring Security provides built-in support for authenticating users.
|
||||
This section is dedicated to generic authentication support that applies in both Servlet and WebFlux environments.
|
||||
Refer to the sections on authentication for xref:servlet/authentication/index.adoc#servlet-authentication[Servlet] and xref:servlet/authentication/index.adoc[WebFlux] for details on what is supported for each stack.
|
||||
Refer to the sections on authentication for xref:servlet/authentication/index.adoc[Servlet] and xref:reactive/authentication/index.adoc[WebFlux] for details on what is supported for each stack.
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
= Spring Security
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Spring Security's documentation can be https://docs.spring.io/spring-security/reference/spring-security-docs.zip[downloaded] as a zip file.
|
||||
====
|
||||
|
||||
Spring Security is a framework that provides xref:features/authentication/index.adoc[authentication], xref:features/authorization/index.adoc[authorization], and xref:features/exploits/index.adoc[protection against common attacks].
|
||||
With first class support for securing both xref:servlet/index.adoc[imperative] and xref:reactive/index.adoc[reactive] applications, it is the de-facto standard for securing Spring-based applications.
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[[webflux-authentication]]
|
||||
= Authentication
|
||||
:page-section-summary-toc: 1
|
||||
@@ -29,7 +29,7 @@ spring:
|
||||
security:
|
||||
oauth2:
|
||||
resourceserver:
|
||||
opaque-token:
|
||||
opaquetoken:
|
||||
introspection-uri: https://idp.example.com/introspect
|
||||
client-id: client
|
||||
client-secret: secret
|
||||
@@ -616,7 +616,7 @@ spring:
|
||||
security:
|
||||
oauth2:
|
||||
resourceserver:
|
||||
opaque-token:
|
||||
opaquetoken:
|
||||
introspection-uri: https://idp.example.org/introspection
|
||||
client-id: client
|
||||
client-secret: secret
|
||||
|
||||
@@ -34,7 +34,7 @@ The attributes on the `<http>` element control some of the properties on the cor
|
||||
Use AuthorizationManager API instead of SecurityMetadataSource (defaults to true)
|
||||
|
||||
[[nsa-http-authorization-manager-ref]]
|
||||
* **access-decision-manager-ref**
|
||||
* **use-authorization-manager**
|
||||
Use this AuthorizationManager instead of deriving one from <intercept-url> elements
|
||||
|
||||
[[nsa-http-access-decision-manager-ref]]
|
||||
|
||||
@@ -259,7 +259,7 @@ Java::
|
||||
+
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
HeaderWriterLogoutHandler clearSiteData = new HeaderWriterLogoutHandler(new ClearSiteDataHeaderWriter());
|
||||
HeaderWriterLogoutHandler clearSiteData = new HeaderWriterLogoutHandler(new ClearSiteDataHeaderWriter(Directives.ALL));
|
||||
http
|
||||
.logout((logout) -> logout.addLogoutHandler(clearSiteData))
|
||||
----
|
||||
@@ -268,7 +268,7 @@ Kotlin::
|
||||
+
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
val clearSiteData = HeaderWriterLogoutHandler(ClearSiteDataHeaderWriter())
|
||||
val clearSiteData = HeaderWriterLogoutHandler(ClearSiteDataHeaderWriter(Directives.ALL))
|
||||
http {
|
||||
logout {
|
||||
addLogoutHandler(clearSiteData)
|
||||
@@ -402,7 +402,7 @@ SecurityContextLogoutHandler logoutHandler = new SecurityContextLogoutHandler();
|
||||
@PostMapping("/my/logout")
|
||||
public String performLogout(Authentication authentication, HttpServletRequest request, HttpServletResponse response) {
|
||||
// .. perform logout
|
||||
this.logoutHandler.doLogout(request, response, authentication);
|
||||
this.logoutHandler.logout(request, response, authentication);
|
||||
return "redirect:/home";
|
||||
}
|
||||
----
|
||||
@@ -416,7 +416,7 @@ val logoutHandler = SecurityContextLogoutHandler()
|
||||
@PostMapping("/my/logout")
|
||||
fun performLogout(val authentication: Authentication, val request: HttpServletRequest, val response: HttpServletResponse): String {
|
||||
// .. perform logout
|
||||
this.logoutHandler.doLogout(request, response, authentication)
|
||||
this.logoutHandler.logout(request, response, authentication)
|
||||
return "redirect:/home"
|
||||
}
|
||||
----
|
||||
|
||||
@@ -8,14 +8,12 @@ The browser automatically checks that the certificate presented by a server has
|
||||
You can also use SSL with "`mutual authentication`". The server then requests a valid certificate from the client as part of the SSL handshake.
|
||||
The server authenticates the client by checking that its certificate is signed by an acceptable authority.
|
||||
If a valid certificate has been provided, it can be obtained through the servlet API in an application.
|
||||
The Spring Security X.509 module extracts the certificate by using a filter.
|
||||
It maps the certificate to an application user and loads that user's set of granted authorities for use with the standard Spring Security infrastructure.
|
||||
|
||||
You can also use SSL with "`mutual authentication`". The server then requests a valid certificate from the client as part of the SSL handshake.
|
||||
The server authenticates the client by checking that its certificate is signed by an acceptable authority.
|
||||
For example, if you use Tomcat, you should read the https://tomcat.apache.org/tomcat-10.1-doc/ssl-howto.html[Tomcat SSL instructions].
|
||||
You should get this working before trying it out with Spring Security.
|
||||
|
||||
The Spring Security X.509 module extracts the certificate by using a filter.
|
||||
It maps the certificate to an application user and loads that user's set of granted authorities for use with the standard Spring Security infrastructure.
|
||||
|
||||
|
||||
== Adding X.509 Authentication to Your Web Application
|
||||
Enabling X.509 client authentication is very straightforward.
|
||||
|
||||
@@ -1048,8 +1048,8 @@ public class SecurityConfig {
|
||||
http
|
||||
.securityMatcher("/api/**") <1>
|
||||
.authorizeHttpRequests(authorize -> authorize
|
||||
.requestMatchers("/user/**").hasRole("USER") <2>
|
||||
.requestMatchers("/admin/**").hasRole("ADMIN") <3>
|
||||
.requestMatchers("/api/user/**").hasRole("USER") <2>
|
||||
.requestMatchers("/api/admin/**").hasRole("ADMIN") <3>
|
||||
.anyRequest().authenticated() <4>
|
||||
)
|
||||
.formLogin(withDefaults());
|
||||
@@ -1071,8 +1071,8 @@ open class SecurityConfig {
|
||||
http {
|
||||
securityMatcher("/api/**") <1>
|
||||
authorizeHttpRequests {
|
||||
authorize("/user/**", hasRole("USER")) <2>
|
||||
authorize("/admin/**", hasRole("ADMIN")) <3>
|
||||
authorize("/api/user/**", hasRole("USER")) <2>
|
||||
authorize("/api/admin/**", hasRole("ADMIN")) <3>
|
||||
authorize(anyRequest, authenticated) <4>
|
||||
}
|
||||
}
|
||||
@@ -1084,8 +1084,8 @@ open class SecurityConfig {
|
||||
======
|
||||
|
||||
<1> Configure `HttpSecurity` to only be applied to URLs that start with `/api/`
|
||||
<2> Allow access to URLs that start with `/user/` to users with the `USER` role
|
||||
<3> Allow access to URLs that start with `/admin/` to users with the `ADMIN` role
|
||||
<2> Allow access to URLs that start with `/api/user/` to users with the `USER` role
|
||||
<3> Allow access to URLs that start with `/api/admin/` to users with the `ADMIN` role
|
||||
<4> Any other request that doesn't match the rules above, will require authentication
|
||||
|
||||
The `securityMatcher(s)` and `requestMatcher(s)` methods will decide which `RequestMatcher` implementation fits best for your application: If {spring-framework-reference-url}web.html#spring-web[Spring MVC] is in the classpath, then javadoc:org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher[] will be used, otherwise, javadoc:org.springframework.security.web.util.matcher.AntPathRequestMatcher[] will be used.
|
||||
@@ -1111,8 +1111,8 @@ public class SecurityConfig {
|
||||
http
|
||||
.securityMatcher(antMatcher("/api/**")) <2>
|
||||
.authorizeHttpRequests(authorize -> authorize
|
||||
.requestMatchers(antMatcher("/user/**")).hasRole("USER") <3>
|
||||
.requestMatchers(regexMatcher("/admin/.*")).hasRole("ADMIN") <4>
|
||||
.requestMatchers(antMatcher("/api/user/**")).hasRole("USER") <3>
|
||||
.requestMatchers(regexMatcher("/api/admin/.*")).hasRole("ADMIN") <4>
|
||||
.requestMatchers(new MyCustomRequestMatcher()).hasRole("SUPERVISOR") <5>
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
@@ -1146,8 +1146,8 @@ open class SecurityConfig {
|
||||
http {
|
||||
securityMatcher(antMatcher("/api/**")) <2>
|
||||
authorizeHttpRequests {
|
||||
authorize(antMatcher("/user/**"), hasRole("USER")) <3>
|
||||
authorize(regexMatcher("/admin/**"), hasRole("ADMIN")) <4>
|
||||
authorize(antMatcher("/api/user/**"), hasRole("USER")) <3>
|
||||
authorize(regexMatcher("/api/admin/**"), hasRole("ADMIN")) <4>
|
||||
authorize(MyCustomRequestMatcher(), hasRole("SUPERVISOR")) <5>
|
||||
authorize(anyRequest, authenticated)
|
||||
}
|
||||
@@ -1161,8 +1161,8 @@ open class SecurityConfig {
|
||||
|
||||
<1> Import the static factory methods from `AntPathRequestMatcher` and `RegexRequestMatcher` to create `RequestMatcher` instances.
|
||||
<2> Configure `HttpSecurity` to only be applied to URLs that start with `/api/`, using `AntPathRequestMatcher`
|
||||
<3> Allow access to URLs that start with `/user/` to users with the `USER` role, using `AntPathRequestMatcher`
|
||||
<4> Allow access to URLs that start with `/admin/` to users with the `ADMIN` role, using `RegexRequestMatcher`
|
||||
<3> Allow access to URLs that start with `/api/user/` to users with the `USER` role, using `AntPathRequestMatcher`
|
||||
<4> Allow access to URLs that start with `/api/admin/` to users with the `ADMIN` role, using `RegexRequestMatcher`
|
||||
<5> Allow access to URLs that match the `MyCustomRequestMatcher` to users with the `SUPERVISOR` role, using a custom `RequestMatcher`
|
||||
|
||||
== Further Reading
|
||||
|
||||
@@ -28,7 +28,7 @@ spring:
|
||||
security:
|
||||
oauth2:
|
||||
resourceserver:
|
||||
opaque-token:
|
||||
opaquetoken:
|
||||
introspection-uri: https://idp.example.com/introspect
|
||||
client-id: client
|
||||
client-secret: secret
|
||||
@@ -786,7 +786,7 @@ spring:
|
||||
security:
|
||||
oauth2:
|
||||
resourceserver:
|
||||
opaque-token:
|
||||
opaquetoken:
|
||||
introspection-uri: https://idp.example.org/introspection
|
||||
client-id: client
|
||||
client-secret: secret
|
||||
|
||||
@@ -103,10 +103,11 @@ spring:
|
||||
security:
|
||||
saml2:
|
||||
relyingparty:
|
||||
okta:
|
||||
identityprovider:
|
||||
entity-id: ...
|
||||
singlesignon.sign-request: false
|
||||
registration:
|
||||
okta:
|
||||
assertingparty:
|
||||
entity-id: ...
|
||||
singlesignon.sign-request: false
|
||||
----
|
||||
|
||||
Java::
|
||||
|
||||
@@ -125,7 +125,7 @@ spring:
|
||||
relyingparty:
|
||||
registration:
|
||||
adfs:
|
||||
identityprovider:
|
||||
assertingparty:
|
||||
entity-id: https://idp.example.com/issuer
|
||||
verification.credentials:
|
||||
- certificate-location: "classpath:idp.crt"
|
||||
@@ -886,16 +886,17 @@ spring:
|
||||
security:
|
||||
saml2:
|
||||
relyingparty:
|
||||
okta:
|
||||
signing.credentials: &relying-party-credentials
|
||||
- private-key-location: classpath:rp.key
|
||||
certificate-location: classpath:rp.crt
|
||||
identityprovider:
|
||||
entity-id: ...
|
||||
azure:
|
||||
signing.credentials: *relying-party-credentials
|
||||
identityprovider:
|
||||
entity-id: ...
|
||||
registration:
|
||||
okta:
|
||||
signing.credentials: &relying-party-credentials
|
||||
- private-key-location: classpath:rp.key
|
||||
certificate-location: classpath:rp.crt
|
||||
assertingparty:
|
||||
entity-id: ...
|
||||
azure:
|
||||
signing.credentials: *relying-party-credentials
|
||||
assertingparty:
|
||||
entity-id: ...
|
||||
----
|
||||
|
||||
Second, in a database, you need not replicate the model of `RelyingPartyRegistration`.
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
= SAML 2.0 Extension Migration
|
||||
|
||||
This document contains guidance for moving SAML 2.0 Service Providers from Spring Security SAML Extensions 1.x to Spring Security Since Spring Security doesn’t provide Identity Provider support, migrating a Spring Security SAML Extensions Identity Provider is out of scope for this document.
|
||||
|
||||
Because the two approaches are as different as they are, this document will tend to cover patterns more than precise search-and-replace steps.
|
||||
|
||||
[[saml2-login-logout]]
|
||||
== Login & Logout
|
||||
|
||||
=== Changes In Approach
|
||||
|
||||
https://github.com/spring-projects/spring-security[Spring Security] takes a slightly different approach from https://github.com/spring-projects/spring-security-saml[Spring Security SAML Extensions] in a few notable ways.
|
||||
|
||||
==== Simplified Enablement
|
||||
|
||||
Spring Security SAML Extensions support for Service Providers is provided by a series of filters enabled by adding each filter manually in the correct order to various Spring Security filter chains.
|
||||
|
||||
Spring Security’s SAML 2.0 Service Provider support is enabled via the Spring Security DSL methods:
|
||||
xref:servlet/saml2/login/index.adoc[`saml2Login`],
|
||||
xref:servlet/saml2/logout.adoc[`saml2Logout`], and
|
||||
xref:servlet/saml2/metadata.adoc[`saml2Metadata`]. It selects the correct filters to add and puts them in the appropriate places in the filter chain.
|
||||
|
||||
==== Stronger Encapsulation
|
||||
|
||||
Like Spring Security SAML Extensions, Spring Security bases it’s SAML support on OpenSAML. The Extensions project exposes OpenSAML over public interfaces, blurring the lines between the two projects, effectively requiring OpenSAML, and making upgrades to later versions of OpenSAML more complicated.
|
||||
|
||||
Spring Security provides stronger encapsulation. No public interfaces expose OpenSAML components and any class that exposes OpenSAML in its public API is named with an `OpenSaml` prefix for additional clarity.
|
||||
|
||||
==== Out-of-the-box Multitenancy
|
||||
|
||||
Spring Security SAML Extensions offered some lightweight support for declaring more than one Identity Provider and accessing it at login time using the `idp` request parameter. This was limiting as far as changing things at runtime was concerned and also doesn’t allow for a many-to-many relationship between relying and asserting parties.
|
||||
|
||||
Spring Security builds SAML 2.0 multitenancy into its default URLs and basic components in the form of a `RelyingPartyRegistration`. This component acts as a link between a Relying Party’s metadata and an Asserting Party’s metadata, and all pairs are available for lookup in a `RelyingPartyRegistrationRepository`. Each URL represents a unique registration pair to be retrieved.
|
||||
|
||||
Whether it’s AuthnRequests, Responses, LogoutRequests, LogoutResponses, or EntityDescriptors, each filter is based off of `RelyingPartyRegistrationRepository` and so is fundamentally multi-tenant.
|
||||
|
||||
=== Examples Matrix
|
||||
|
||||
Both Spring Security and Spring Security SAML Extensions have examples for how to configure the Service Provider:
|
||||
|
||||
[options="header"]
|
||||
|===
|
||||
| Use case | Spring Security | Spring Security SAML Extension
|
||||
|
||||
| Login & Logout | https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/java/saml2/login[Sample] |
|
||||
https://github.com/jzheaux/spring-security-saml-migrate/tree/main/login-logout[Sample]
|
||||
| Login using SAML Extension URLs | https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/java/saml2/custom-urls[Sample] | -
|
||||
| Metadata support | https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/java/saml2/refreshable-metadata[Sample] | -
|
||||
|===
|
||||
|
||||
You can also see a showcase example in https://github.com/spring-projects/spring-security-saml/tree/main/sample[Spring Security SAML Extension]'s GitHub project.
|
||||
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Spring Security does not support HTTP-Redirect binding for SAML 2.0 Responses.
|
||||
According to the SAML specification, the HTTP-Redirect binding is not permitted for SAML Responses due to URL length and signature limitations. Attempting to use this binding may result in unexpected errors.
|
||||
Use HTTP-POST binding instead when configuring your identity provider.
|
||||
====
|
||||
|
||||
[[saml2-unported]]
|
||||
== Unported Features
|
||||
|
||||
There are some features that are not yet ported over and there are as yet no plans to do so:
|
||||
|
||||
* HTTP-Redirect binding for SAML 2.0 Responses
|
||||
* Artifact binding support
|
||||
@@ -2,4 +2,4 @@
|
||||
= Spring MVC Test Integration
|
||||
:page-section-summary-toc: 1
|
||||
|
||||
Spring Security provides comprehensive integration with https://docs.spring.io/spring/docs/current/spring-framework-reference/html/testing.html#spring-mvc-test-framework[Spring MVC Test]
|
||||
Spring Security provides comprehensive integration with {spring-framework-reference-url}testing/mockmvc.html[Spring MVC Test]
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
springBootVersion=3.3.3
|
||||
version=6.4.4
|
||||
version=6.4.6
|
||||
samplesBranch=main
|
||||
org.gradle.jvmargs=-Xmx3g -XX:+HeapDumpOnOutOfMemoryError
|
||||
org.gradle.parallel=true
|
||||
|
||||
+12
-12
@@ -5,20 +5,20 @@ io-spring-javaformat = "0.0.43"
|
||||
io-spring-nohttp = "0.0.11"
|
||||
jakarta-websocket = "2.2.0"
|
||||
org-apache-directory-server = "1.5.5"
|
||||
org-apache-maven-resolver = "1.9.22"
|
||||
org-aspectj = "1.9.22.1"
|
||||
org-apache-maven-resolver = "1.9.23"
|
||||
org-aspectj = "1.9.24"
|
||||
org-bouncycastle = "1.79"
|
||||
org-eclipse-jetty = "11.0.24"
|
||||
org-eclipse-jetty = "11.0.25"
|
||||
org-jetbrains-kotlin = "1.9.25"
|
||||
org-jetbrains-kotlinx = "1.9.0"
|
||||
org-mockito = "5.14.2"
|
||||
org-opensaml = "4.3.2"
|
||||
org-opensaml5 = "5.1.2"
|
||||
org-springframework = "6.2.4"
|
||||
org-springframework = "6.2.7"
|
||||
|
||||
[libraries]
|
||||
ch-qos-logback-logback-classic = "ch.qos.logback:logback-classic:1.5.17"
|
||||
com-fasterxml-jackson-jackson-bom = "com.fasterxml.jackson:jackson-bom:2.18.3"
|
||||
ch-qos-logback-logback-classic = "ch.qos.logback:logback-classic:1.5.18"
|
||||
com-fasterxml-jackson-jackson-bom = "com.fasterxml.jackson:jackson-bom:2.18.4"
|
||||
com-google-inject-guice = "com.google.inject:guice:3.0"
|
||||
com-netflix-nebula-nebula-project-plugin = "com.netflix.nebula:nebula-project-plugin:8.2.0"
|
||||
com-nimbusds-nimbus-jose-jwt = "com.nimbusds:nimbus-jose-jwt:9.37.3"
|
||||
@@ -28,15 +28,15 @@ com-squareup-okhttp3-okhttp = { module = "com.squareup.okhttp3:okhttp", version.
|
||||
com-unboundid-unboundid-ldapsdk = "com.unboundid:unboundid-ldapsdk:6.0.11"
|
||||
com-unboundid-unboundid-ldapsdk7 = "com.unboundid:unboundid-ldapsdk:7.0.1"
|
||||
commons-collections = "commons-collections:commons-collections:3.2.2"
|
||||
io-micrometer-micrometer-observation = "io.micrometer:micrometer-observation:1.14.5"
|
||||
io-micrometer-micrometer-observation = "io.micrometer:micrometer-observation:1.14.7"
|
||||
io-mockk = "io.mockk:mockk:1.13.17"
|
||||
io-projectreactor-reactor-bom = "io.projectreactor:reactor-bom:2023.0.16"
|
||||
io-projectreactor-reactor-bom = "io.projectreactor:reactor-bom:2023.0.18"
|
||||
io-rsocket-rsocket-bom = { module = "io.rsocket:rsocket-bom", version.ref = "io-rsocket" }
|
||||
io-spring-javaformat-spring-javaformat-checkstyle = { module = "io.spring.javaformat:spring-javaformat-checkstyle", version.ref = "io-spring-javaformat" }
|
||||
io-spring-javaformat-spring-javaformat-gradle-plugin = { module = "io.spring.javaformat:spring-javaformat-gradle-plugin", version.ref = "io-spring-javaformat" }
|
||||
io-spring-nohttp-nohttp-checkstyle = { module = "io.spring.nohttp:nohttp-checkstyle", version.ref = "io-spring-nohttp" }
|
||||
io-spring-nohttp-nohttp-gradle = { module = "io.spring.nohttp:nohttp-gradle", version.ref = "io-spring-nohttp" }
|
||||
io-spring-security-release-plugin = "io.spring.gradle:spring-security-release-plugin:1.0.3"
|
||||
io-spring-security-release-plugin = "io.spring.gradle:spring-security-release-plugin:1.0.6"
|
||||
jakarta-annotation-jakarta-annotation-api = "jakarta.annotation:jakarta.annotation-api:2.1.1"
|
||||
jakarta-inject-jakarta-inject-api = "jakarta.inject:jakarta.inject-api:2.0.1"
|
||||
jakarta-persistence-jakarta-persistence-api = "jakarta.persistence:jakarta.persistence-api:3.1.0"
|
||||
@@ -70,7 +70,7 @@ org-bouncycastle-bcprov-jdk15on = { module = "org.bouncycastle:bcprov-jdk18on",
|
||||
org-eclipse-jetty-jetty-server = { module = "org.eclipse.jetty:jetty-server", version.ref = "org-eclipse-jetty" }
|
||||
org-eclipse-jetty-jetty-servlet = { module = "org.eclipse.jetty:jetty-servlet", version.ref = "org-eclipse-jetty" }
|
||||
org-hamcrest = "org.hamcrest:hamcrest:2.2"
|
||||
org-hibernate-orm-hibernate-core = "org.hibernate.orm:hibernate-core:6.6.11.Final"
|
||||
org-hibernate-orm-hibernate-core = "org.hibernate.orm:hibernate-core:6.6.15.Final"
|
||||
org-hsqldb = "org.hsqldb:hsqldb:2.7.4"
|
||||
org-jetbrains-kotlin-kotlin-bom = { module = "org.jetbrains.kotlin:kotlin-bom", version.ref = "org-jetbrains-kotlin" }
|
||||
org-jetbrains-kotlin-kotlin-gradle-plugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.25"
|
||||
@@ -88,8 +88,8 @@ org-seleniumhq-selenium-selenium-support = "org.seleniumhq.selenium:selenium-sup
|
||||
org-skyscreamer-jsonassert = "org.skyscreamer:jsonassert:1.5.3"
|
||||
org-slf4j-log4j-over-slf4j = "org.slf4j:log4j-over-slf4j:1.7.36"
|
||||
org-slf4j-slf4j-api = "org.slf4j:slf4j-api:2.0.17"
|
||||
org-springframework-data-spring-data-bom = "org.springframework.data:spring-data-bom:2024.1.4"
|
||||
org-springframework-ldap-spring-ldap-core = "org.springframework.ldap:spring-ldap-core:3.2.11"
|
||||
org-springframework-data-spring-data-bom = "org.springframework.data:spring-data-bom:2024.1.6"
|
||||
org-springframework-ldap-spring-ldap-core = "org.springframework.ldap:spring-ldap-core:3.2.12"
|
||||
org-springframework-spring-framework-bom = { module = "org.springframework:spring-framework-bom", version.ref = "org-springframework" }
|
||||
org-synchronoss-cloud-nio-multipart-parser = "org.synchronoss.cloud:nio-multipart-parser:1.1.0"
|
||||
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+2
-2
@@ -1,7 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=8d97a97984f6cbd2b85fe4c60a743440a347544bf18818048e611f5288d46c94
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
|
||||
distributionSha256Sum=61ad310d3c7d3e5da131b76bbf22b5a4c0786e9d892dae8c1658d4b484de3caa
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -86,8 +86,7 @@ done
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
||||
' "$PWD" ) || exit
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
@@ -115,7 +114,7 @@ case "$( uname )" in #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
CLASSPATH="\\\"\\\""
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
@@ -206,7 +205,7 @@ fi
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
@@ -214,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
|
||||
Vendored
+2
-2
@@ -70,11 +70,11 @@ goto fail
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
set CLASSPATH=
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
|
||||
+8
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.security.oauth2.client.registration;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@@ -49,6 +50,7 @@ import org.springframework.web.util.UriComponentsBuilder;
|
||||
* @author Rob Winch
|
||||
* @author Josh Cummings
|
||||
* @author Rafiullah Hamedy
|
||||
* @author Evgeniy Cheban
|
||||
* @since 5.1
|
||||
*/
|
||||
public final class ClientRegistrations {
|
||||
@@ -251,6 +253,7 @@ public final class ClientRegistrations {
|
||||
private static ClientRegistration.Builder getBuilder(String issuer,
|
||||
Supplier<ClientRegistration.Builder>... suppliers) {
|
||||
String errorMessage = "Unable to resolve Configuration with the provided Issuer of \"" + issuer + "\"";
|
||||
List<String> errors = new ArrayList<>();
|
||||
for (Supplier<ClientRegistration.Builder> supplier : suppliers) {
|
||||
try {
|
||||
return supplier.get();
|
||||
@@ -259,6 +262,7 @@ public final class ClientRegistrations {
|
||||
if (!ex.getStatusCode().is4xxClientError()) {
|
||||
throw ex;
|
||||
}
|
||||
errors.add(ex.getMessage());
|
||||
// else try another endpoint
|
||||
}
|
||||
catch (IllegalArgumentException | IllegalStateException ex) {
|
||||
@@ -268,6 +272,9 @@ public final class ClientRegistrations {
|
||||
throw new IllegalArgumentException(errorMessage, ex);
|
||||
}
|
||||
}
|
||||
if (!errors.isEmpty()) {
|
||||
throw new IllegalArgumentException(errorMessage + ", errors: " + errors);
|
||||
}
|
||||
throw new IllegalArgumentException(errorMessage);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -245,7 +245,7 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements
|
||||
* be used to create an Authentication for saving.</li>
|
||||
* </ul>
|
||||
* @param authorizedClient the {@link OAuth2AuthorizedClient} to use.
|
||||
* @return the {@link Consumer} to populate the
|
||||
* @return the {@link Consumer} to populate the attributes
|
||||
*/
|
||||
public static Consumer<Map<String, Object>> oauth2AuthorizedClient(OAuth2AuthorizedClient authorizedClient) {
|
||||
return (attributes) -> attributes.put(OAUTH2_AUTHORIZED_CLIENT_ATTR_NAME, authorizedClient);
|
||||
|
||||
+24
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,12 +36,14 @@ import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
|
||||
|
||||
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.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @author Rafiullah Hamedy
|
||||
* @author Evgeniy Cheban
|
||||
* @since 5.1
|
||||
*/
|
||||
public class ClientRegistrationsTests {
|
||||
@@ -569,6 +571,27 @@ public class ClientRegistrationsTests {
|
||||
.isEqualTo(ClientAuthenticationMethod.CLIENT_SECRET_BASIC);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void issuerWhenAllEndpointsFailedThenExceptionIncludesFailureInformation() {
|
||||
this.issuer = createIssuerFromServer("issuer1");
|
||||
this.server.setDispatcher(new Dispatcher() {
|
||||
@Override
|
||||
public MockResponse dispatch(RecordedRequest request) {
|
||||
int responseCode = switch (request.getPath()) {
|
||||
case "/issuer1/.well-known/openid-configuration" -> 405;
|
||||
case "/.well-known/openid-configuration/issuer1" -> 400;
|
||||
default -> 404;
|
||||
};
|
||||
return new MockResponse().setResponseCode(responseCode);
|
||||
}
|
||||
});
|
||||
assertThatExceptionOfType(IllegalArgumentException.class)
|
||||
.isThrownBy(() -> ClientRegistrations.fromIssuerLocation(this.issuer).build())
|
||||
.withMessageContaining("405")
|
||||
.withMessageContaining("400")
|
||||
.withMessageContaining("404");
|
||||
}
|
||||
|
||||
private ClientRegistration.Builder registration(String path) throws Exception {
|
||||
this.issuer = createIssuerFromServer(path);
|
||||
this.response.put("issuer", this.issuer);
|
||||
|
||||
+65
-60
@@ -52,26 +52,77 @@ public final class DefaultBearerTokenResolver implements BearerTokenResolver {
|
||||
|
||||
@Override
|
||||
public String resolve(final HttpServletRequest request) {
|
||||
final String authorizationHeaderToken = resolveFromAuthorizationHeader(request);
|
||||
final String parameterToken = isParameterTokenSupportedForRequest(request)
|
||||
? resolveFromRequestParameters(request) : null;
|
||||
if (authorizationHeaderToken != null) {
|
||||
if (parameterToken != null) {
|
||||
// @formatter:off
|
||||
return resolveToken(
|
||||
resolveFromAuthorizationHeader(request),
|
||||
resolveAccessTokenFromQueryString(request),
|
||||
resolveAccessTokenFromBody(request)
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static String resolveToken(String... accessTokens) {
|
||||
if (accessTokens == null || accessTokens.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String accessToken = null;
|
||||
for (String token : accessTokens) {
|
||||
if (accessToken == null) {
|
||||
accessToken = token;
|
||||
}
|
||||
else if (token != null) {
|
||||
BearerTokenError error = BearerTokenErrors
|
||||
.invalidRequest("Found multiple bearer tokens in the request");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
return authorizationHeaderToken;
|
||||
}
|
||||
if (parameterToken != null && isParameterTokenEnabledForRequest(request)) {
|
||||
if (!StringUtils.hasText(parameterToken)) {
|
||||
BearerTokenError error = BearerTokenErrors
|
||||
.invalidRequest("The requested token parameter is an empty string");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
return parameterToken;
|
||||
|
||||
if (accessToken != null && accessToken.isBlank()) {
|
||||
BearerTokenError error = BearerTokenErrors
|
||||
.invalidRequest("The requested token parameter is an empty string");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
return null;
|
||||
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
private String resolveFromAuthorizationHeader(HttpServletRequest request) {
|
||||
String authorization = request.getHeader(this.bearerTokenHeaderName);
|
||||
if (!StringUtils.startsWithIgnoreCase(authorization, "bearer")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Matcher matcher = authorizationPattern.matcher(authorization);
|
||||
if (!matcher.matches()) {
|
||||
BearerTokenError error = BearerTokenErrors.invalidToken("Bearer token is malformed");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
|
||||
return matcher.group("token");
|
||||
}
|
||||
|
||||
private String resolveAccessTokenFromQueryString(HttpServletRequest request) {
|
||||
if (!this.allowUriQueryParameter || !HttpMethod.GET.name().equals(request.getMethod())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return resolveToken(request.getParameterValues(ACCESS_TOKEN_PARAMETER_NAME));
|
||||
}
|
||||
|
||||
private String resolveAccessTokenFromBody(HttpServletRequest request) {
|
||||
if (!this.allowFormEncodedBodyParameter
|
||||
|| !MediaType.APPLICATION_FORM_URLENCODED_VALUE.equals(request.getContentType())
|
||||
|| HttpMethod.GET.name().equals(request.getMethod())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String queryString = request.getQueryString();
|
||||
if (queryString != null && queryString.contains(ACCESS_TOKEN_PARAMETER_NAME)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return resolveToken(request.getParameterValues(ACCESS_TOKEN_PARAMETER_NAME));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,50 +160,4 @@ public final class DefaultBearerTokenResolver implements BearerTokenResolver {
|
||||
this.bearerTokenHeaderName = bearerTokenHeaderName;
|
||||
}
|
||||
|
||||
private String resolveFromAuthorizationHeader(HttpServletRequest request) {
|
||||
String authorization = request.getHeader(this.bearerTokenHeaderName);
|
||||
if (!StringUtils.startsWithIgnoreCase(authorization, "bearer")) {
|
||||
return null;
|
||||
}
|
||||
Matcher matcher = authorizationPattern.matcher(authorization);
|
||||
if (!matcher.matches()) {
|
||||
BearerTokenError error = BearerTokenErrors.invalidToken("Bearer token is malformed");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
return matcher.group("token");
|
||||
}
|
||||
|
||||
private static String resolveFromRequestParameters(HttpServletRequest request) {
|
||||
String[] values = request.getParameterValues(ACCESS_TOKEN_PARAMETER_NAME);
|
||||
if (values == null || values.length == 0) {
|
||||
return null;
|
||||
}
|
||||
if (values.length == 1) {
|
||||
return values[0];
|
||||
}
|
||||
BearerTokenError error = BearerTokenErrors.invalidRequest("Found multiple bearer tokens in the request");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
|
||||
private boolean isParameterTokenSupportedForRequest(final HttpServletRequest request) {
|
||||
return isFormEncodedRequest(request) || isGetRequest(request);
|
||||
}
|
||||
|
||||
private static boolean isGetRequest(HttpServletRequest request) {
|
||||
return HttpMethod.GET.name().equals(request.getMethod());
|
||||
}
|
||||
|
||||
private static boolean isFormEncodedRequest(HttpServletRequest request) {
|
||||
return MediaType.APPLICATION_FORM_URLENCODED_VALUE.equals(request.getContentType());
|
||||
}
|
||||
|
||||
private static boolean hasAccessTokenInQueryString(HttpServletRequest request) {
|
||||
return (request.getQueryString() != null) && request.getQueryString().contains(ACCESS_TOKEN_PARAMETER_NAME);
|
||||
}
|
||||
|
||||
private boolean isParameterTokenEnabledForRequest(HttpServletRequest request) {
|
||||
return ((this.allowFormEncodedBodyParameter && isFormEncodedRequest(request) && !isGetRequest(request)
|
||||
&& !hasAccessTokenInQueryString(request)) || (this.allowUriQueryParameter && isGetRequest(request)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -77,18 +77,18 @@ public class ServerBearerTokenAuthenticationConverter implements ServerAuthentic
|
||||
}
|
||||
return authorizationHeaderToken;
|
||||
}
|
||||
if (parameterToken != null && isParameterTokenSupportedForRequest(request)) {
|
||||
if (!StringUtils.hasText(parameterToken)) {
|
||||
BearerTokenError error = BearerTokenErrors
|
||||
.invalidRequest("The requested token parameter is an empty string");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
return parameterToken;
|
||||
if (parameterToken != null && !StringUtils.hasText(parameterToken)) {
|
||||
BearerTokenError error = BearerTokenErrors
|
||||
.invalidRequest("The requested token parameter is an empty string");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
return null;
|
||||
return parameterToken;
|
||||
}
|
||||
|
||||
private static String resolveAccessTokenFromRequest(ServerHttpRequest request) {
|
||||
private String resolveAccessTokenFromRequest(ServerHttpRequest request) {
|
||||
if (!isParameterTokenSupportedForRequest(request)) {
|
||||
return null;
|
||||
}
|
||||
List<String> parameterTokens = request.getQueryParams().get("access_token");
|
||||
if (CollectionUtils.isEmpty(parameterTokens)) {
|
||||
return null;
|
||||
|
||||
+37
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -110,6 +110,7 @@ public class DefaultBearerTokenResolverTests {
|
||||
|
||||
@Test
|
||||
public void resolveWhenValidHeaderIsPresentTogetherWithFormParameterThenAuthenticationExceptionIsThrown() {
|
||||
this.resolver.setAllowFormEncodedBodyParameter(true);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "Bearer " + TEST_TOKEN);
|
||||
request.setMethod("POST");
|
||||
@@ -121,6 +122,7 @@ public class DefaultBearerTokenResolverTests {
|
||||
|
||||
@Test
|
||||
public void resolveWhenValidHeaderIsPresentTogetherWithQueryParameterThenAuthenticationExceptionIsThrown() {
|
||||
this.resolver.setAllowUriQueryParameter(true);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "Bearer " + TEST_TOKEN);
|
||||
request.setMethod("GET");
|
||||
@@ -133,6 +135,7 @@ public class DefaultBearerTokenResolverTests {
|
||||
// gh-10326
|
||||
@Test
|
||||
public void resolveWhenRequestContainsTwoAccessTokenQueryParametersThenAuthenticationExceptionIsThrown() {
|
||||
this.resolver.setAllowUriQueryParameter(true);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("GET");
|
||||
request.addParameter("access_token", "token1", "token2");
|
||||
@@ -143,6 +146,7 @@ public class DefaultBearerTokenResolverTests {
|
||||
// gh-10326
|
||||
@Test
|
||||
public void resolveWhenRequestContainsTwoAccessTokenFormParametersThenAuthenticationExceptionIsThrown() {
|
||||
this.resolver.setAllowFormEncodedBodyParameter(true);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("POST");
|
||||
request.setContentType("application/x-www-form-urlencoded");
|
||||
@@ -233,6 +237,19 @@ public class DefaultBearerTokenResolverTests {
|
||||
assertThat(this.resolver.resolve(request)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveWhenPostAndQueryParameterIsSupportedAndFormParameterIsPresentThenTokenIsNotResolved() {
|
||||
this.resolver.setAllowUriQueryParameter(true);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("POST");
|
||||
request.setContentType("application/x-www-form-urlencoded");
|
||||
request.setQueryString("access_token=" + TEST_TOKEN);
|
||||
request.addParameter("access_token", TEST_TOKEN);
|
||||
|
||||
assertThat(this.resolver.resolve(request)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveWhenFormParameterIsPresentAndNotSupportedThenTokenIsNotResolved() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
@@ -261,6 +278,25 @@ public class DefaultBearerTokenResolverTests {
|
||||
assertThat(this.resolver.resolve(request)).isNull();
|
||||
}
|
||||
|
||||
// gh-16038
|
||||
@Test
|
||||
public void resolveWhenRequestContainsTwoAccessTokenFormParametersAndSupportIsDisabledThenTokenIsNotResolved() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("POST");
|
||||
request.setContentType("application/x-www-form-urlencoded");
|
||||
request.addParameter("access_token", "token1", "token2");
|
||||
assertThat(this.resolver.resolve(request)).isNull();
|
||||
}
|
||||
|
||||
// gh-16038
|
||||
@Test
|
||||
public void resolveWhenRequestContainsTwoAccessTokenQueryParametersAndSupportIsDisabledThenTokenIsNotResolved() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("GET");
|
||||
request.addParameter("access_token", "token1", "token2");
|
||||
assertThat(this.resolver.resolve(request)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveWhenQueryParameterIsPresentAndEmptyStringThenTokenIsNotResolved() {
|
||||
this.resolver.setAllowUriQueryParameter(true);
|
||||
|
||||
+11
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -157,6 +157,7 @@ public class ServerBearerTokenAuthenticationConverterTests {
|
||||
@Test
|
||||
public void resolveWhenValidHeaderIsPresentTogetherWithQueryParameterThenAuthenticationExceptionIsThrown() {
|
||||
// @formatter:off
|
||||
this.converter.setAllowUriQueryParameter(true);
|
||||
MockServerHttpRequest.BaseBuilder<?> request = MockServerHttpRequest.get("/")
|
||||
.queryParam("access_token", TEST_TOKEN)
|
||||
.header(HttpHeaders.AUTHORIZATION, "Bearer " + TEST_TOKEN);
|
||||
@@ -205,6 +206,7 @@ public class ServerBearerTokenAuthenticationConverterTests {
|
||||
|
||||
@Test
|
||||
void resolveWhenQueryParameterHasMultipleAccessTokensThenOAuth2AuthenticationException() {
|
||||
this.converter.setAllowUriQueryParameter(true);
|
||||
MockServerHttpRequest.BaseBuilder<?> request = MockServerHttpRequest.get("/")
|
||||
.queryParam("access_token", TEST_TOKEN, TEST_TOKEN);
|
||||
assertThatExceptionOfType(OAuth2AuthenticationException.class).isThrownBy(() -> convertToToken(request))
|
||||
@@ -217,6 +219,14 @@ public class ServerBearerTokenAuthenticationConverterTests {
|
||||
|
||||
}
|
||||
|
||||
// gh-16038
|
||||
@Test
|
||||
void resolveWhenRequestContainsTwoAccessTokenQueryParametersAndSupportIsDisabledThenTokenIsNotResolved() {
|
||||
MockServerHttpRequest.BaseBuilder<?> request = MockServerHttpRequest.get("/")
|
||||
.queryParam("access_token", TEST_TOKEN, TEST_TOKEN);
|
||||
assertThat(convertToToken(request)).isNull();
|
||||
}
|
||||
|
||||
private BearerTokenAuthenticationToken convertToToken(MockServerHttpRequest.BaseBuilder<?> request) {
|
||||
return convertToToken(request.build());
|
||||
}
|
||||
|
||||
+10
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -160,7 +160,7 @@ class BaseOpenSamlAuthenticationProvider implements AuthenticationProvider {
|
||||
String inResponseTo = response.getInResponseTo();
|
||||
result = result.concat(validateInResponseTo(token.getAuthenticationRequest(), inResponseTo));
|
||||
|
||||
String issuer = response.getIssuer().getValue();
|
||||
String issuer = issuer(response);
|
||||
String destination = response.getDestination();
|
||||
String location = token.getRelyingPartyRegistration().getAssertionConsumerServiceLocation();
|
||||
if (StringUtils.hasText(destination) && !destination.equals(location)) {
|
||||
@@ -183,6 +183,13 @@ class BaseOpenSamlAuthenticationProvider implements AuthenticationProvider {
|
||||
};
|
||||
}
|
||||
|
||||
private static String issuer(Response response) {
|
||||
if (response.getIssuer() == null) {
|
||||
return null;
|
||||
}
|
||||
return response.getIssuer().getValue();
|
||||
}
|
||||
|
||||
private static List<String> getStatusCodes(Response response) {
|
||||
if (response.getStatus() == null) {
|
||||
return List.of(StatusCode.SUCCESS);
|
||||
@@ -308,7 +315,7 @@ class BaseOpenSamlAuthenticationProvider implements AuthenticationProvider {
|
||||
}
|
||||
|
||||
private void process(Saml2AuthenticationToken token, Response response) {
|
||||
String issuer = response.getIssuer().getValue();
|
||||
String issuer = issuer(response);
|
||||
this.logger.debug(LogMessage.format("Processing SAML response from %s", issuer));
|
||||
boolean responseSigned = response.isSigned();
|
||||
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+68
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -386,6 +386,24 @@ public class OpenSaml4AuthenticationProviderTests {
|
||||
this.provider.authenticate(token);
|
||||
}
|
||||
|
||||
// gh-16367
|
||||
@Test
|
||||
public void authenticateWhenEncryptedAssertionWithSignatureThenEncryptedAssertionStillAvailable() {
|
||||
Response response = response();
|
||||
Assertion assertion = TestOpenSamlObjects.signed(assertion(),
|
||||
TestSaml2X509Credentials.assertingPartySigningCredential(), RELYING_PARTY_ENTITY_ID);
|
||||
EncryptedAssertion encryptedAssertion = TestOpenSamlObjects.encrypted(assertion,
|
||||
TestSaml2X509Credentials.assertingPartyEncryptingCredential());
|
||||
response.getEncryptedAssertions().add(encryptedAssertion);
|
||||
Saml2AuthenticationToken token = token(signed(response), decrypting(verifying(registration())));
|
||||
OpenSaml4AuthenticationProvider provider = new OpenSaml4AuthenticationProvider();
|
||||
provider.setResponseValidator((t) -> {
|
||||
assertThat(t.getResponse().getEncryptedAssertions()).isNotEmpty();
|
||||
return Saml2ResponseValidatorResult.success();
|
||||
});
|
||||
provider.authenticate(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenEncryptedAssertionWithResponseSignatureThenItSucceeds() {
|
||||
Response response = response();
|
||||
@@ -410,6 +428,26 @@ public class OpenSaml4AuthenticationProviderTests {
|
||||
this.provider.authenticate(token);
|
||||
}
|
||||
|
||||
// gh-16367
|
||||
@Test
|
||||
public void authenticateWhenEncryptedNameIdWithSignatureThenEncryptedNameIdStillAvailable() {
|
||||
Response response = response();
|
||||
Assertion assertion = assertion();
|
||||
NameID nameId = assertion.getSubject().getNameID();
|
||||
EncryptedID encryptedID = TestOpenSamlObjects.encrypted(nameId,
|
||||
TestSaml2X509Credentials.assertingPartyEncryptingCredential());
|
||||
assertion.getSubject().setNameID(null);
|
||||
assertion.getSubject().setEncryptedID(encryptedID);
|
||||
response.getAssertions().add(signed(assertion));
|
||||
Saml2AuthenticationToken token = token(response, decrypting(verifying(registration())));
|
||||
OpenSaml4AuthenticationProvider provider = new OpenSaml4AuthenticationProvider();
|
||||
provider.setAssertionValidator((t) -> {
|
||||
assertThat(t.getAssertion().getSubject().getEncryptedID()).isNotNull();
|
||||
return Saml2ResponseValidatorResult.success();
|
||||
});
|
||||
provider.authenticate(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenEncryptedAttributeThenDecrypts() {
|
||||
Response response = response();
|
||||
@@ -426,6 +464,26 @@ public class OpenSaml4AuthenticationProviderTests {
|
||||
assertThat(principal.getAttribute("name")).containsExactly("value");
|
||||
}
|
||||
|
||||
// gh-16367
|
||||
@Test
|
||||
public void authenticateWhenEncryptedAttributeThenEncryptedAttributesStillAvailable() {
|
||||
Response response = response();
|
||||
Assertion assertion = assertion();
|
||||
EncryptedAttribute attribute = TestOpenSamlObjects.encrypted("name", "value",
|
||||
TestSaml2X509Credentials.assertingPartyEncryptingCredential());
|
||||
AttributeStatement statement = build(AttributeStatement.DEFAULT_ELEMENT_NAME);
|
||||
statement.getEncryptedAttributes().add(attribute);
|
||||
assertion.getAttributeStatements().add(statement);
|
||||
response.getAssertions().add(assertion);
|
||||
Saml2AuthenticationToken token = token(signed(response), decrypting(verifying(registration())));
|
||||
OpenSaml4AuthenticationProvider provider = new OpenSaml4AuthenticationProvider();
|
||||
provider.setAssertionValidator((t) -> {
|
||||
assertThat(t.getAssertion().getAttributeStatements().get(0).getEncryptedAttributes()).isNotEmpty();
|
||||
return Saml2ResponseValidatorResult.success();
|
||||
});
|
||||
provider.authenticate(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenDecryptionKeysAreMissingThenThrowAuthenticationException() {
|
||||
Response response = response();
|
||||
@@ -831,6 +889,15 @@ public class OpenSaml4AuthenticationProviderTests {
|
||||
provider.authenticate(token);
|
||||
}
|
||||
|
||||
// gh-16989
|
||||
@Test
|
||||
public void authenticateWhenNullIssuerThenNoNullPointer() {
|
||||
OpenSaml4AuthenticationProvider provider = new OpenSaml4AuthenticationProvider();
|
||||
Response response = TestOpenSamlObjects.signedResponseWithOneAssertion((r) -> r.setIssuer(null));
|
||||
Saml2AuthenticationToken token = token(response, verifying(registration()));
|
||||
assertThatExceptionOfType(Saml2AuthenticationException.class).isThrownBy(() -> provider.authenticate(token));
|
||||
}
|
||||
|
||||
private <T extends XMLObject> T build(QName qName) {
|
||||
return (T) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(qName).buildObject(qName);
|
||||
}
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+68
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -386,6 +386,24 @@ public class OpenSaml5AuthenticationProviderTests {
|
||||
this.provider.authenticate(token);
|
||||
}
|
||||
|
||||
// gh-16367
|
||||
@Test
|
||||
public void authenticateWhenEncryptedAssertionWithSignatureThenEncryptedAssertionStillAvailable() {
|
||||
Response response = response();
|
||||
Assertion assertion = TestOpenSamlObjects.signed(assertion(),
|
||||
TestSaml2X509Credentials.assertingPartySigningCredential(), RELYING_PARTY_ENTITY_ID);
|
||||
EncryptedAssertion encryptedAssertion = TestOpenSamlObjects.encrypted(assertion,
|
||||
TestSaml2X509Credentials.assertingPartyEncryptingCredential());
|
||||
response.getEncryptedAssertions().add(encryptedAssertion);
|
||||
Saml2AuthenticationToken token = token(signed(response), decrypting(verifying(registration())));
|
||||
OpenSaml5AuthenticationProvider provider = new OpenSaml5AuthenticationProvider();
|
||||
provider.setResponseValidator((t) -> {
|
||||
assertThat(t.getResponse().getEncryptedAssertions()).isNotEmpty();
|
||||
return Saml2ResponseValidatorResult.success();
|
||||
});
|
||||
provider.authenticate(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenEncryptedAssertionWithResponseSignatureThenItSucceeds() {
|
||||
Response response = response();
|
||||
@@ -410,6 +428,26 @@ public class OpenSaml5AuthenticationProviderTests {
|
||||
this.provider.authenticate(token);
|
||||
}
|
||||
|
||||
// gh-16367
|
||||
@Test
|
||||
public void authenticateWhenEncryptedNameIdWithSignatureThenEncryptedNameIdStillAvailable() {
|
||||
Response response = response();
|
||||
Assertion assertion = assertion();
|
||||
NameID nameId = assertion.getSubject().getNameID();
|
||||
EncryptedID encryptedID = TestOpenSamlObjects.encrypted(nameId,
|
||||
TestSaml2X509Credentials.assertingPartyEncryptingCredential());
|
||||
assertion.getSubject().setNameID(null);
|
||||
assertion.getSubject().setEncryptedID(encryptedID);
|
||||
response.getAssertions().add(signed(assertion));
|
||||
Saml2AuthenticationToken token = token(response, decrypting(verifying(registration())));
|
||||
OpenSaml5AuthenticationProvider provider = new OpenSaml5AuthenticationProvider();
|
||||
provider.setAssertionValidator((t) -> {
|
||||
assertThat(t.getAssertion().getSubject().getEncryptedID()).isNotNull();
|
||||
return Saml2ResponseValidatorResult.success();
|
||||
});
|
||||
provider.authenticate(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenEncryptedAttributeThenDecrypts() {
|
||||
Response response = response();
|
||||
@@ -426,6 +464,26 @@ public class OpenSaml5AuthenticationProviderTests {
|
||||
assertThat(principal.getAttribute("name")).containsExactly("value");
|
||||
}
|
||||
|
||||
// gh-16367
|
||||
@Test
|
||||
public void authenticateWhenEncryptedAttributeThenEncryptedAttributesStillAvailable() {
|
||||
Response response = response();
|
||||
Assertion assertion = assertion();
|
||||
EncryptedAttribute attribute = TestOpenSamlObjects.encrypted("name", "value",
|
||||
TestSaml2X509Credentials.assertingPartyEncryptingCredential());
|
||||
AttributeStatement statement = build(AttributeStatement.DEFAULT_ELEMENT_NAME);
|
||||
statement.getEncryptedAttributes().add(attribute);
|
||||
assertion.getAttributeStatements().add(statement);
|
||||
response.getAssertions().add(assertion);
|
||||
Saml2AuthenticationToken token = token(signed(response), decrypting(verifying(registration())));
|
||||
OpenSaml5AuthenticationProvider provider = new OpenSaml5AuthenticationProvider();
|
||||
provider.setAssertionValidator((t) -> {
|
||||
assertThat(t.getAssertion().getAttributeStatements().get(0).getEncryptedAttributes()).isNotEmpty();
|
||||
return Saml2ResponseValidatorResult.success();
|
||||
});
|
||||
provider.authenticate(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenDecryptionKeysAreMissingThenThrowAuthenticationException() {
|
||||
Response response = response();
|
||||
@@ -831,6 +889,15 @@ public class OpenSaml5AuthenticationProviderTests {
|
||||
provider.authenticate(token);
|
||||
}
|
||||
|
||||
// gh-16989
|
||||
@Test
|
||||
public void authenticateWhenNullIssuerThenNoNullPointer() {
|
||||
OpenSaml5AuthenticationProvider provider = new OpenSaml5AuthenticationProvider();
|
||||
Response response = TestOpenSamlObjects.signedResponseWithOneAssertion((r) -> r.setIssuer(null));
|
||||
Saml2AuthenticationToken token = token(response, verifying(registration()));
|
||||
assertThatExceptionOfType(Saml2AuthenticationException.class).isThrownBy(() -> provider.authenticate(token));
|
||||
}
|
||||
|
||||
private <T extends XMLObject> T build(QName qName) {
|
||||
return (T) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(qName).buildObject(qName);
|
||||
}
|
||||
|
||||
+11
-3
@@ -29,6 +29,9 @@ public interface WebInvocationPrivilegeEvaluator {
|
||||
/**
|
||||
* Determines whether the user represented by the supplied <tt>Authentication</tt>
|
||||
* object is allowed to invoke the supplied URI.
|
||||
* <p>
|
||||
* Note this will only match authorization rules that don't require a certain
|
||||
* {@code HttpMethod}.
|
||||
* @param uri the URI excluding the context path (a default context path setting will
|
||||
* be used)
|
||||
*/
|
||||
@@ -36,13 +39,18 @@ public interface WebInvocationPrivilegeEvaluator {
|
||||
|
||||
/**
|
||||
* Determines whether the user represented by the supplied <tt>Authentication</tt>
|
||||
* object is allowed to invoke the supplied URI, with the given .
|
||||
* object is allowed to invoke the supplied URI, with the given parameters.
|
||||
* <p>
|
||||
* Note the default implementation of <tt>FilterInvocationSecurityMetadataSource</tt>
|
||||
* Note:
|
||||
* <ul>
|
||||
* <li>The default implementation of <tt>FilterInvocationSecurityMetadataSource</tt>
|
||||
* disregards the <code>contextPath</code> when evaluating which secure object
|
||||
* metadata applies to a given request URI, so generally the <code>contextPath</code>
|
||||
* is unimportant unless you are using a custom
|
||||
* <code>FilterInvocationSecurityMetadataSource</code>.
|
||||
* <code>FilterInvocationSecurityMetadataSource</code>.</li>
|
||||
* <li>this will only match authorization rules that don't require a certain
|
||||
* {@code HttpMethod}.</li>
|
||||
* </ul>
|
||||
* @param uri the URI excluding the context path
|
||||
* @param contextPath the context path (may be null).
|
||||
* @param method the HTTP method (or null, for any method)
|
||||
|
||||
+7
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -79,6 +79,10 @@ import org.springframework.web.filter.GenericFilterBean;
|
||||
* raised by the <tt>AuthenticationManager</tt> will the be re-thrown. Note that this will
|
||||
* not affect cases where the principal returned by {@link #getPreAuthenticatedPrincipal}
|
||||
* is null, when the chain will still proceed as normal.
|
||||
* <p>
|
||||
* The filter saves the {@link SecurityContext} using the configured
|
||||
* {@link SecurityContextRepository}, which can be set via
|
||||
* {@link #setSecurityContextRepository}.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @author Ruud Senden
|
||||
@@ -253,8 +257,8 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
|
||||
|
||||
/**
|
||||
* Sets the {@link SecurityContextRepository} to save the {@link SecurityContext} on
|
||||
* authentication success. The default action is not to save the
|
||||
* {@link SecurityContext}.
|
||||
* authentication success. The default action is to save the {@link SecurityContext}
|
||||
* in {@link HttpSession} using {@link HttpSessionSecurityContextRepository}.
|
||||
* @param securityContextRepository the {@link SecurityContextRepository} to use.
|
||||
* Cannot be null.
|
||||
*/
|
||||
|
||||
+1
-1
@@ -452,7 +452,7 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
|
||||
<div class="login-form">
|
||||
<h2>Login with Passkeys</h2>
|
||||
<button id="passkey-signin" type="submit" class="primary">Sign in with a passkey</button>
|
||||
</form>
|
||||
</div>
|
||||
""";
|
||||
|
||||
private static final String LOGIN_PAGE_TEMPLATE = """
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -84,7 +84,7 @@ public final class CookieServerCsrfTokenRepository implements ServerCsrfTokenRep
|
||||
*/
|
||||
public static CookieServerCsrfTokenRepository withHttpOnlyFalse() {
|
||||
CookieServerCsrfTokenRepository result = new CookieServerCsrfTokenRepository();
|
||||
result.setCookieCustomizer((cookie) -> cookie.httpOnly(false));
|
||||
result.cookieHttpOnly = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
+9
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -802,42 +802,42 @@ public class StrictServerWebExchangeFirewall implements ServerWebExchangeFirewal
|
||||
|
||||
@Override
|
||||
public Builder method(HttpMethod httpMethod) {
|
||||
return this.delegate.method(httpMethod);
|
||||
return new StrictFirewallBuilder(this.delegate.method(httpMethod));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder uri(URI uri) {
|
||||
return this.delegate.uri(uri);
|
||||
return new StrictFirewallBuilder(this.delegate.uri(uri));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder path(String path) {
|
||||
return this.delegate.path(path);
|
||||
return new StrictFirewallBuilder(this.delegate.path(path));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder contextPath(String contextPath) {
|
||||
return this.delegate.contextPath(contextPath);
|
||||
return new StrictFirewallBuilder(this.delegate.contextPath(contextPath));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder header(String headerName, String... headerValues) {
|
||||
return this.delegate.header(headerName, headerValues);
|
||||
return new StrictFirewallBuilder(this.delegate.header(headerName, headerValues));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder headers(Consumer<HttpHeaders> headersConsumer) {
|
||||
return this.delegate.headers(headersConsumer);
|
||||
return new StrictFirewallBuilder(this.delegate.headers(headersConsumer));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder sslInfo(SslInfo sslInfo) {
|
||||
return this.delegate.sslInfo(sslInfo);
|
||||
return new StrictFirewallBuilder(this.delegate.sslInfo(sslInfo));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder remoteAddress(InetSocketAddress remoteAddress) {
|
||||
return this.delegate.remoteAddress(remoteAddress);
|
||||
return new StrictFirewallBuilder(this.delegate.remoteAddress(remoteAddress));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+13
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -333,9 +333,7 @@ public class Webauthn4JRelyingPartyOperations implements WebAuthnRelyingPartyOpe
|
||||
public PublicKeyCredentialRequestOptions createCredentialRequestOptions(
|
||||
PublicKeyCredentialRequestOptionsRequest request) {
|
||||
Authentication authentication = request.getAuthentication();
|
||||
// FIXME: do not load credentialRecords if anonymous
|
||||
PublicKeyCredentialUserEntity userEntity = findUserEntityOrCreateAndSave(authentication.getName());
|
||||
List<CredentialRecord> credentialRecords = this.userCredentials.findByUserId(userEntity.getId());
|
||||
List<CredentialRecord> credentialRecords = findCredentialRecords(authentication);
|
||||
return PublicKeyCredentialRequestOptions.builder()
|
||||
.allowCredentials(credentialDescriptors(credentialRecords))
|
||||
.challenge(Bytes.random())
|
||||
@@ -346,6 +344,17 @@ public class Webauthn4JRelyingPartyOperations implements WebAuthnRelyingPartyOpe
|
||||
.build();
|
||||
}
|
||||
|
||||
private List<CredentialRecord> findCredentialRecords(Authentication authentication) {
|
||||
if (!this.trustResolver.isAuthenticated(authentication)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
PublicKeyCredentialUserEntity userEntity = this.userEntities.findByUsername(authentication.getName());
|
||||
if (userEntity == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return this.userCredentials.findByUserId(userEntity.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PublicKeyCredentialUserEntity authenticate(RelyingPartyAuthenticationRequest request) {
|
||||
PublicKeyCredentialRequestOptions requestOptions = request.getRequestOptions();
|
||||
|
||||
+16
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -290,6 +290,21 @@ class CookieServerCsrfTokenRepositoryTests {
|
||||
loadAndAssertExpectedValues();
|
||||
}
|
||||
|
||||
// gh-16820
|
||||
@Test
|
||||
void withHttpOnlyFalseWhenCookieCustomizerThenStillDefaultsToFalse() {
|
||||
CookieServerCsrfTokenRepository repository = CookieServerCsrfTokenRepository.withHttpOnlyFalse();
|
||||
repository.setCookieCustomizer((customizer) -> customizer.maxAge(1000));
|
||||
MockServerHttpRequest.BaseBuilder<?> request = MockServerHttpRequest.get("/dummy");
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||
CsrfToken csrfToken = repository.generateToken(exchange).block();
|
||||
repository.saveToken(exchange, csrfToken).block();
|
||||
ResponseCookie cookie = exchange.getResponse().getCookies().getFirst("XSRF-TOKEN");
|
||||
assertThat(cookie).isNotNull();
|
||||
assertThat(cookie.getMaxAge().getSeconds()).isEqualTo(1000);
|
||||
assertThat(cookie.isHttpOnly()).isEqualTo(Boolean.FALSE);
|
||||
}
|
||||
|
||||
private void setExpectedHeaderName(String expectedHeaderName) {
|
||||
this.csrfTokenRepository.setHeaderName(expectedHeaderName);
|
||||
this.expectedHeaderName = expectedHeaderName;
|
||||
|
||||
+14
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -534,4 +534,17 @@ class StrictServerWebExchangeFirewallTests {
|
||||
.isThrownBy(() -> headers.get(invalidHeaderName));
|
||||
}
|
||||
|
||||
// gh-16978
|
||||
@Test
|
||||
void getMutatedFirewalledExchangeHeadersGetHeaderWhenNotAllowedHeaderNameThenException() {
|
||||
String invalidHeaderName = "bad name";
|
||||
this.firewall.setAllowedHeaderNames((name) -> !name.equals(invalidHeaderName));
|
||||
ServerWebExchange exchange = getFirewalledExchange();
|
||||
var mutatedRequest = exchange.getRequest().mutate().method(HttpMethod.POST).build();
|
||||
var mutatedExchange = exchange.mutate().request(mutatedRequest).build();
|
||||
HttpHeaders headers = mutatedExchange.getRequest().getHeaders();
|
||||
assertThatExceptionOfType(ServerExchangeRejectedException.class)
|
||||
.isThrownBy(() -> headers.get(invalidHeaderName));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+48
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -42,6 +42,8 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.userdetails.PasswordEncodedUser;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.web.webauthn.api.AuthenticatorAttestationResponse;
|
||||
import org.springframework.security.web.webauthn.api.AuthenticatorAttestationResponse.AuthenticatorAttestationResponseBuilder;
|
||||
import org.springframework.security.web.webauthn.api.AuthenticatorSelectionCriteria;
|
||||
@@ -66,6 +68,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.assertj.core.api.Assertions.assertThatRuntimeException;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class Webauthn4jRelyingPartyOperationsTests {
|
||||
@@ -536,6 +539,50 @@ class Webauthn4jRelyingPartyOperationsTests {
|
||||
.isEqualTo(creationOptions.getAuthenticatorSelection().getUserVerification());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createCredentialRequestOptionsWhenAnonymousAuthentication() {
|
||||
AnonymousAuthenticationToken authentication = new AnonymousAuthenticationToken("key", "anonymousUser",
|
||||
Set.of(() -> "ROLE_ANONYMOUS"));
|
||||
PublicKeyCredentialRequestOptionsRequest createRequest = new ImmutablePublicKeyCredentialRequestOptionsRequest(
|
||||
authentication);
|
||||
PublicKeyCredentialRequestOptions credentialRequestOptions = this.rpOperations
|
||||
.createCredentialRequestOptions(createRequest);
|
||||
|
||||
assertThat(credentialRequestOptions.getAllowCredentials()).isEmpty();
|
||||
// verify anonymous user not saved
|
||||
verifyNoInteractions(this.userEntities);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createCredentialRequestOptionsWhenNullAuthentication() {
|
||||
PublicKeyCredentialRequestOptionsRequest createRequest = new ImmutablePublicKeyCredentialRequestOptionsRequest(
|
||||
null);
|
||||
PublicKeyCredentialRequestOptions credentialRequestOptions = this.rpOperations
|
||||
.createCredentialRequestOptions(createRequest);
|
||||
|
||||
assertThat(credentialRequestOptions.getAllowCredentials()).isEmpty();
|
||||
// verify anonymous user not saved
|
||||
verifyNoInteractions(this.userEntities);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createCredentialRequestOptionsWhenAuthenticated() {
|
||||
UserDetails user = PasswordEncodedUser.user();
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user, null,
|
||||
user.getAuthorities());
|
||||
PublicKeyCredentialUserEntity userEntity = TestPublicKeyCredentialUserEntity.userEntity().build();
|
||||
CredentialRecord credentialRecord = TestCredentialRecord.userCredential().build();
|
||||
given(this.userEntities.findByUsername(user.getUsername())).willReturn(userEntity);
|
||||
given(this.userCredentials.findByUserId(userEntity.getId())).willReturn(Arrays.asList(credentialRecord));
|
||||
PublicKeyCredentialRequestOptionsRequest createRequest = new ImmutablePublicKeyCredentialRequestOptionsRequest(
|
||||
auth);
|
||||
PublicKeyCredentialRequestOptions credentialRequestOptions = this.rpOperations
|
||||
.createCredentialRequestOptions(createRequest);
|
||||
|
||||
assertThat(credentialRequestOptions.getAllowCredentials()).extracting(PublicKeyCredentialDescriptor::getId)
|
||||
.containsExactly(credentialRecord.getCredentialId());
|
||||
}
|
||||
|
||||
private static AuthenticatorAttestationResponse setFlag(byte... flags) throws Exception {
|
||||
AuthenticatorAttestationResponseBuilder authAttResponseBldr = TestAuthenticatorAttestationResponse
|
||||
.createAuthenticatorAttestationResponse();
|
||||
|
||||
Reference in New Issue
Block a user