diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 000000000..1ea259456 --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "NuGetKeyVaultSignTool": { + "version": "3.2.3", + "commands": [ + "NuGetKeyVaultSignTool" + ] + } + } +} \ No newline at end of file diff --git a/.editorconfig b/.editorconfig index ad5924866..810297c27 100644 --- a/.editorconfig +++ b/.editorconfig @@ -20,6 +20,7 @@ csharp_style_expression_bodied_operators = true csharp_style_expression_bodied_properties = true csharp_style_namespace_declarations = file_scoped csharp_style_prefer_switch_expression = true +csharp_style_unused_value_expression_statement_preference = discard_variable csharp_style_var_elsewhere = true csharp_style_var_for_built_in_types = true csharp_style_var_when_type_is_apparent = true @@ -37,6 +38,7 @@ dotnet_diagnostic.IDE0027.severity = warning # Use expression body for accessors dotnet_diagnostic.IDE0046.severity = suggestion # Use conditional expression for return dotnet_diagnostic.IDE0049.severity = warning # Use language keywords instead of framework type names for type references dotnet_diagnostic.IDE0055.severity = warning # Formatting rule +dotnet_diagnostic.IDE0058.severity = warning # Remove unnecessary expression value dotnet_diagnostic.IDE0066.severity = warning # Use switch expressions dotnet_diagnostic.IDE0073.severity = warning # Require file header dotnet_diagnostic.IDE0161.severity = warning # Use file-scoped namespace diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md deleted file mode 100644 index 58627d211..000000000 --- a/.github/CONTRIBUTING.md +++ /dev/null @@ -1,33 +0,0 @@ -# Contributing to Duende Software Products - -Thank you for your interest in Duende Software. As this repository contains proprietary licensed software, we have a specific policy regarding contributions. - -**We do not generally accept unsolicited contributions to this repository.** - -## How to Report Issues or Suggest Improvements - -If you've identified an issue, have a suggestion, or want to discuss any aspect of our products: - -1. Please use the [GitHub Discussions](https://github.com/orgs/DuendeSoftware/discussions) for the Duende Software organization. -2. Provide a clear description of your observation, suggestion, or question. -3. Our team will review and respond to appropriate discussion threads. - -## Limited Contribution Scenarios - -In specific cases where a contribution might be considered: - -1. Only proceed after explicit invitation or approval from the Duende Software team. -2. Any contributed code must be compatible with our proprietary license. -3. You will be required to sign a Contributor License Agreement (CLA) before any contribution can be accepted. - -## Code of Conduct - -When participating in discussions related to Duende Software: - -- Be respectful and professional in all communications -- Focus on technical details and specific product functionality -- Understand that not all suggestions will be implemented - -## Thank You - -We appreciate your understanding of our contribution policy. Our team works diligently to ensure the quality and integrity of our products, and we value your interest and feedback through the appropriate channels. \ No newline at end of file diff --git a/.github/workflows/aspnetcore-authentication-jwtbearer-release.yml b/.github/workflows/aspnetcore-authentication-jwtbearer-release.yml deleted file mode 100644 index 95788b9da..000000000 --- a/.github/workflows/aspnetcore-authentication-jwtbearer-release.yml +++ /dev/null @@ -1,118 +0,0 @@ -# This was generated by tool. Edits will be overwritten. - -name: aspnetcore-authentication-jwtbearer/release -on: - workflow_dispatch: - inputs: - version: - description: 'Version in format X.Y.Z, X.Y.Z-preview.N, or X.Y.Z-rc.N' - type: string - required: true - default: '0.0.0' - branch: - description: '(Optional) the name of the branch to release from' - type: string - required: false - default: 'main' - remove-tag-if-exists: - description: 'If set, will remove the existing tag. Use this if you have issues with the previous release action' - type: boolean - required: false - default: false -env: - DOTNET_NOLOGO: true - DOTNET_CLI_TELEMETRY_OPTOUT: true -jobs: - tag: - name: Tag and Pack - runs-on: ubuntu-latest - permissions: - contents: write - packages: write - defaults: - run: - shell: bash - working-directory: aspnetcore-authentication-jwtbearer - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Validate Version Input - run: echo '${{ github.event.inputs.version }}' | grep -P '^\d+\.\d+\.\d+(-preview\.\d+|-rc\.\d+)?$' || (echo 'Invalid version format' && exit 1) - - name: Checkout target branch - if: github.event.inputs.branch != 'main' - run: git checkout ${{ github.event.inputs.branch }} - - name: Git Config - run: |- - git config --global user.email "github-bot@duendesoftware.com" - git config --global user.name "Duende Software GitHub Bot" - - name: Git Config - if: github.event.inputs['remove-tag-if-exists'] == 'true' - run: |- - if git rev-parse aaj-${{ github.event.inputs.version }} >/dev/null 2>&1; then - git tag -d aaj-${{ github.event.inputs.version }} - git push --delete origin aaj-${{ github.event.inputs.version }} - else - echo 'Tag aaj-${{ github.event.inputs.version }} does not exist.' - fi - - name: Git Config - run: |- - git tag -a aaj-${{ github.event.inputs.version }} -m "Release v${{ github.event.inputs.version }}" - git push origin aaj-${{ github.event.inputs.version }} - - name: List .net sdks - run: dotnet --list-sdks - - name: Setup Dotnet - uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25 - with: - dotnet-version: |- - 8.0.x - 9.0.203 - 10.0.200 - - name: Pack aspnetcore-authentication-jwtbearer.slnf - run: dotnet pack -c Release aspnetcore-authentication-jwtbearer.slnf -o artifacts - - name: Tool restore - run: dotnet tool restore - - name: Sign packages - run: |- - for file in artifacts/*.nupkg; do - dotnet NuGetKeyVaultSignTool sign "$file" --file-digest sha256 --timestamp-rfc3161 http://timestamp.digicert.com --azure-key-vault-url https://duendecodesigninghsm.vault.azure.net/ --azure-key-vault-client-id 18e3de68-2556-4345-8076-a46fad79e474 --azure-key-vault-tenant-id ed3089f0-5401-4758-90eb-066124e2d907 --azure-key-vault-client-secret ${{ secrets.SignClientSecret }} --azure-key-vault-certificate NuGetPackageSigning - done - - name: Push packages to GitHub - run: dotnet nuget push artifacts/*.nupkg --source https://nuget.pkg.github.com/DuendeSoftware/index.json --api-key ${{ secrets.GITHUB_TOKEN }} --skip-duplicate - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NUGET_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Upload Artifacts - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 - with: - name: artifacts - path: aspnetcore-authentication-jwtbearer/artifacts/*.nupkg - overwrite: true - retention-days: 15 - publish: - name: Publish to nuget.org - needs: - - tag - runs-on: ubuntu-latest - environment: - name: nuget.org - steps: - - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 - with: - name: artifacts - path: artifacts - - name: List .net sdks - run: dotnet --list-sdks - - name: Setup Dotnet - uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25 - with: - dotnet-version: |- - 8.0.x - 9.0.203 - 10.0.200 - - name: List files - run: tree - shell: bash - - name: Push packages to nuget.org - run: dotnet nuget push artifacts/*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_ORG_API_KEY }} --skip-duplicate diff --git a/.github/workflows/auto-close-external.yml b/.github/workflows/auto-close-external.yml deleted file mode 100644 index bc82e0dd8..000000000 --- a/.github/workflows/auto-close-external.yml +++ /dev/null @@ -1,69 +0,0 @@ -name: Auto-close external issues and PRs - -on: - issues: - types: [opened] - pull_request_target: - types: [opened] - -permissions: - issues: write - pull-requests: write - -jobs: - close-external: - runs-on: ubuntu-latest - steps: - - uses: actions/github-script@v7 - with: - script: | - const isIssue = context.eventName === 'issues'; - const item = isIssue ? context.payload.issue : context.payload.pull_request; - const association = item.author_association; - - const exempt = ['OWNER', 'MEMBER', 'COLLABORATOR']; - if (exempt.includes(association)) { - console.log(`Skipping — author_association is ${association}`); - return; - } - - const itemType = isIssue ? 'issue' : 'pull request'; - const number = item.number; - const { owner, repo } = context.repo; - - const body = [ - `Thank you for your interest in Duende Software!`, - ``, - `This repository contains proprietary licensed software and does not accept unsolicited issues or pull requests. This ${itemType} has been automatically closed.`, - ``, - `- Please review our [contributor guidelines](https://github.com/DuendeSoftware/products/blob/main/.github/CONTRIBUTING.md) for more details.`, - `- For questions, bug reports, or suggestions, please use [GitHub Discussions](https://github.com/orgs/DuendeSoftware/discussions).`, - ``, - `We appreciate your understanding!`, - ].join('\n'); - - await github.rest.issues.createComment({ - owner, - repo, - issue_number: number, - body, - }); - - if (isIssue) { - await github.rest.issues.update({ - owner, - repo, - issue_number: number, - state: 'closed', - state_reason: 'not_planned', - }); - } else { - await github.rest.pulls.update({ - owner, - repo, - pull_number: number, - state: 'closed', - }); - } - - console.log(`Closed ${itemType} #${number} (author_association: ${association})`); diff --git a/.github/workflows/bff-release.yml b/.github/workflows/bff-release.yml deleted file mode 100644 index d82bf3a36..000000000 --- a/.github/workflows/bff-release.yml +++ /dev/null @@ -1,118 +0,0 @@ -# This was generated by tool. Edits will be overwritten. - -name: bff/release -on: - workflow_dispatch: - inputs: - version: - description: 'Version in format X.Y.Z, X.Y.Z-preview.N, or X.Y.Z-rc.N' - type: string - required: true - default: '0.0.0' - branch: - description: '(Optional) the name of the branch to release from' - type: string - required: false - default: 'main' - remove-tag-if-exists: - description: 'If set, will remove the existing tag. Use this if you have issues with the previous release action' - type: boolean - required: false - default: false -env: - DOTNET_NOLOGO: true - DOTNET_CLI_TELEMETRY_OPTOUT: true -jobs: - tag: - name: Tag and Pack - runs-on: ubuntu-latest - permissions: - contents: write - packages: write - defaults: - run: - shell: bash - working-directory: bff - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Validate Version Input - run: echo '${{ github.event.inputs.version }}' | grep -P '^\d+\.\d+\.\d+(-preview\.\d+|-rc\.\d+)?$' || (echo 'Invalid version format' && exit 1) - - name: Checkout target branch - if: github.event.inputs.branch != 'main' - run: git checkout ${{ github.event.inputs.branch }} - - name: Git Config - run: |- - git config --global user.email "github-bot@duendesoftware.com" - git config --global user.name "Duende Software GitHub Bot" - - name: Git Config - if: github.event.inputs['remove-tag-if-exists'] == 'true' - run: |- - if git rev-parse bff-${{ github.event.inputs.version }} >/dev/null 2>&1; then - git tag -d bff-${{ github.event.inputs.version }} - git push --delete origin bff-${{ github.event.inputs.version }} - else - echo 'Tag bff-${{ github.event.inputs.version }} does not exist.' - fi - - name: Git Config - run: |- - git tag -a bff-${{ github.event.inputs.version }} -m "Release v${{ github.event.inputs.version }}" - git push origin bff-${{ github.event.inputs.version }} - - name: List .net sdks - run: dotnet --list-sdks - - name: Setup Dotnet - uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25 - with: - dotnet-version: |- - 8.0.x - 9.0.203 - 10.0.200 - - name: Pack bff.slnf - run: dotnet pack -c Release bff.slnf -o artifacts - - name: Tool restore - run: dotnet tool restore - - name: Sign packages - run: |- - for file in artifacts/*.nupkg; do - dotnet NuGetKeyVaultSignTool sign "$file" --file-digest sha256 --timestamp-rfc3161 http://timestamp.digicert.com --azure-key-vault-url https://duendecodesigninghsm.vault.azure.net/ --azure-key-vault-client-id 18e3de68-2556-4345-8076-a46fad79e474 --azure-key-vault-tenant-id ed3089f0-5401-4758-90eb-066124e2d907 --azure-key-vault-client-secret ${{ secrets.SignClientSecret }} --azure-key-vault-certificate NuGetPackageSigning - done - - name: Push packages to GitHub - run: dotnet nuget push artifacts/*.nupkg --source https://nuget.pkg.github.com/DuendeSoftware/index.json --api-key ${{ secrets.GITHUB_TOKEN }} --skip-duplicate - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NUGET_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Upload Artifacts - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 - with: - name: artifacts - path: bff/artifacts/*.nupkg - overwrite: true - retention-days: 15 - publish: - name: Publish to nuget.org - needs: - - tag - runs-on: ubuntu-latest - environment: - name: nuget.org - steps: - - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 - with: - name: artifacts - path: artifacts - - name: List .net sdks - run: dotnet --list-sdks - - name: Setup Dotnet - uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25 - with: - dotnet-version: |- - 8.0.x - 9.0.203 - 10.0.200 - - name: List files - run: tree - shell: bash - - name: Push packages to nuget.org - run: dotnet nuget push artifacts/*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_ORG_API_KEY }} --skip-duplicate diff --git a/.github/workflows/docs-mcp-release.yml b/.github/workflows/docs-mcp-release.yml deleted file mode 100644 index 5708fa0bf..000000000 --- a/.github/workflows/docs-mcp-release.yml +++ /dev/null @@ -1,118 +0,0 @@ -# This was generated by tool. Edits will be overwritten. - -name: docs-mcp/release -on: - workflow_dispatch: - inputs: - version: - description: 'Version in format X.Y.Z, X.Y.Z-preview.N, or X.Y.Z-rc.N' - type: string - required: true - default: '0.0.0' - branch: - description: '(Optional) the name of the branch to release from' - type: string - required: false - default: 'main' - remove-tag-if-exists: - description: 'If set, will remove the existing tag. Use this if you have issues with the previous release action' - type: boolean - required: false - default: false -env: - DOTNET_NOLOGO: true - DOTNET_CLI_TELEMETRY_OPTOUT: true -jobs: - tag: - name: Tag and Pack - runs-on: ubuntu-latest - permissions: - contents: write - packages: write - defaults: - run: - shell: bash - working-directory: docs-mcp - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Validate Version Input - run: echo '${{ github.event.inputs.version }}' | grep -P '^\d+\.\d+\.\d+(-preview\.\d+|-rc\.\d+)?$' || (echo 'Invalid version format' && exit 1) - - name: Checkout target branch - if: github.event.inputs.branch != 'main' - run: git checkout ${{ github.event.inputs.branch }} - - name: Git Config - run: |- - git config --global user.email "github-bot@duendesoftware.com" - git config --global user.name "Duende Software GitHub Bot" - - name: Git Config - if: github.event.inputs['remove-tag-if-exists'] == 'true' - run: |- - if git rev-parse dmcp-${{ github.event.inputs.version }} >/dev/null 2>&1; then - git tag -d dmcp-${{ github.event.inputs.version }} - git push --delete origin dmcp-${{ github.event.inputs.version }} - else - echo 'Tag dmcp-${{ github.event.inputs.version }} does not exist.' - fi - - name: Git Config - run: |- - git tag -a dmcp-${{ github.event.inputs.version }} -m "Release v${{ github.event.inputs.version }}" - git push origin dmcp-${{ github.event.inputs.version }} - - name: List .net sdks - run: dotnet --list-sdks - - name: Setup Dotnet - uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25 - with: - dotnet-version: |- - 8.0.x - 9.0.203 - 10.0.200 - - name: Pack docs-mcp.slnf - run: dotnet pack -c Release docs-mcp.slnf -o artifacts - - name: Tool restore - run: dotnet tool restore - - name: Sign packages - run: |- - for file in artifacts/*.nupkg; do - dotnet NuGetKeyVaultSignTool sign "$file" --file-digest sha256 --timestamp-rfc3161 http://timestamp.digicert.com --azure-key-vault-url https://duendecodesigninghsm.vault.azure.net/ --azure-key-vault-client-id 18e3de68-2556-4345-8076-a46fad79e474 --azure-key-vault-tenant-id ed3089f0-5401-4758-90eb-066124e2d907 --azure-key-vault-client-secret ${{ secrets.SignClientSecret }} --azure-key-vault-certificate NuGetPackageSigning - done - - name: Push packages to GitHub - run: dotnet nuget push artifacts/*.nupkg --source https://nuget.pkg.github.com/DuendeSoftware/index.json --api-key ${{ secrets.GITHUB_TOKEN }} --skip-duplicate - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NUGET_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Upload Artifacts - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 - with: - name: artifacts - path: docs-mcp/artifacts/*.nupkg - overwrite: true - retention-days: 15 - publish: - name: Publish to nuget.org - needs: - - tag - runs-on: ubuntu-latest - environment: - name: nuget.org - steps: - - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 - with: - name: artifacts - path: artifacts - - name: List .net sdks - run: dotnet --list-sdks - - name: Setup Dotnet - uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25 - with: - dotnet-version: |- - 8.0.x - 9.0.203 - 10.0.200 - - name: List files - run: tree - shell: bash - - name: Push packages to nuget.org - run: dotnet nuget push artifacts/*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_ORG_API_KEY }} --skip-duplicate diff --git a/.github/workflows/identity-server-release.yml b/.github/workflows/identity-server-release.yml deleted file mode 100644 index 44432620d..000000000 --- a/.github/workflows/identity-server-release.yml +++ /dev/null @@ -1,118 +0,0 @@ -# This was generated by tool. Edits will be overwritten. - -name: identity-server/release -on: - workflow_dispatch: - inputs: - version: - description: 'Version in format X.Y.Z, X.Y.Z-preview.N, or X.Y.Z-rc.N' - type: string - required: true - default: '0.0.0' - branch: - description: '(Optional) the name of the branch to release from' - type: string - required: false - default: 'main' - remove-tag-if-exists: - description: 'If set, will remove the existing tag. Use this if you have issues with the previous release action' - type: boolean - required: false - default: false -env: - DOTNET_NOLOGO: true - DOTNET_CLI_TELEMETRY_OPTOUT: true -jobs: - tag: - name: Tag and Pack - runs-on: ubuntu-latest - permissions: - contents: write - packages: write - defaults: - run: - shell: bash - working-directory: identity-server - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Validate Version Input - run: echo '${{ github.event.inputs.version }}' | grep -P '^\d+\.\d+\.\d+(-preview\.\d+|-rc\.\d+)?$' || (echo 'Invalid version format' && exit 1) - - name: Checkout target branch - if: github.event.inputs.branch != 'main' - run: git checkout ${{ github.event.inputs.branch }} - - name: Git Config - run: |- - git config --global user.email "github-bot@duendesoftware.com" - git config --global user.name "Duende Software GitHub Bot" - - name: Git Config - if: github.event.inputs['remove-tag-if-exists'] == 'true' - run: |- - if git rev-parse is-${{ github.event.inputs.version }} >/dev/null 2>&1; then - git tag -d is-${{ github.event.inputs.version }} - git push --delete origin is-${{ github.event.inputs.version }} - else - echo 'Tag is-${{ github.event.inputs.version }} does not exist.' - fi - - name: Git Config - run: |- - git tag -a is-${{ github.event.inputs.version }} -m "Release v${{ github.event.inputs.version }}" - git push origin is-${{ github.event.inputs.version }} - - name: List .net sdks - run: dotnet --list-sdks - - name: Setup Dotnet - uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25 - with: - dotnet-version: |- - 8.0.x - 9.0.203 - 10.0.200 - - name: Pack identity-server.slnf - run: dotnet pack -c Release identity-server.slnf -o artifacts - - name: Tool restore - run: dotnet tool restore - - name: Sign packages - run: |- - for file in artifacts/*.nupkg; do - dotnet NuGetKeyVaultSignTool sign "$file" --file-digest sha256 --timestamp-rfc3161 http://timestamp.digicert.com --azure-key-vault-url https://duendecodesigninghsm.vault.azure.net/ --azure-key-vault-client-id 18e3de68-2556-4345-8076-a46fad79e474 --azure-key-vault-tenant-id ed3089f0-5401-4758-90eb-066124e2d907 --azure-key-vault-client-secret ${{ secrets.SignClientSecret }} --azure-key-vault-certificate NuGetPackageSigning - done - - name: Push packages to GitHub - run: dotnet nuget push artifacts/*.nupkg --source https://nuget.pkg.github.com/DuendeSoftware/index.json --api-key ${{ secrets.GITHUB_TOKEN }} --skip-duplicate - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NUGET_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Upload Artifacts - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 - with: - name: artifacts - path: identity-server/artifacts/*.nupkg - overwrite: true - retention-days: 15 - publish: - name: Publish to nuget.org - needs: - - tag - runs-on: ubuntu-latest - environment: - name: nuget.org - steps: - - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 - with: - name: artifacts - path: artifacts - - name: List .net sdks - run: dotnet --list-sdks - - name: Setup Dotnet - uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25 - with: - dotnet-version: |- - 8.0.x - 9.0.203 - 10.0.200 - - name: List files - run: tree - shell: bash - - name: Push packages to nuget.org - run: dotnet nuget push artifacts/*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_ORG_API_KEY }} --skip-duplicate diff --git a/.github/workflows/templates-release.yml b/.github/workflows/templates-release.yml deleted file mode 100644 index 7a159d186..000000000 --- a/.github/workflows/templates-release.yml +++ /dev/null @@ -1,118 +0,0 @@ -# This was generated by tool. Edits will be overwritten. - -name: templates/release -on: - workflow_dispatch: - inputs: - version: - description: 'Version in format X.Y.Z, X.Y.Z-preview.N, or X.Y.Z-rc.N' - type: string - required: true - default: '0.0.0' - branch: - description: '(Optional) the name of the branch to release from' - type: string - required: false - default: 'main' - remove-tag-if-exists: - description: 'If set, will remove the existing tag. Use this if you have issues with the previous release action' - type: boolean - required: false - default: false -env: - DOTNET_NOLOGO: true - DOTNET_CLI_TELEMETRY_OPTOUT: true -jobs: - tag: - name: Tag and Pack - runs-on: ubuntu-latest - permissions: - contents: write - packages: write - defaults: - run: - shell: bash - working-directory: templates - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: List .net sdks - run: dotnet --list-sdks - - name: Setup Dotnet - uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25 - with: - dotnet-version: |- - 8.0.x - 9.0.203 - 10.0.200 - - name: Checkout target branch - if: github.event.inputs.branch != 'main' - run: git checkout ${{ github.event.inputs.branch }} - - name: Git Config - run: |- - git config --global user.email "github-bot@duendesoftware.com" - git config --global user.name "Duende Software GitHub Bot" - - name: Git Config - if: github.event.inputs['remove-tag-if-exists'] == 'true' - run: |- - if git rev-parse templates-${{ github.event.inputs.version }} >/dev/null 2>&1; then - git tag -d templates-${{ github.event.inputs.version }} - git push --delete origin templates-${{ github.event.inputs.version }} - else - echo 'Tag templates-${{ github.event.inputs.version }} does not exist.' - fi - - name: Git Config - run: |- - git tag -a templates-${{ github.event.inputs.version }} -m "Release v${{ github.event.inputs.version }}" - git push origin templates-${{ github.event.inputs.version }} - - name: Tool restore - run: dotnet tool restore - - name: build templates - run: dotnet run --project build - - name: Pack ../artifacts/templates.csproj - run: dotnet pack -c Release ../artifacts/templates.csproj -o artifacts - - name: Sign packages - run: |- - for file in artifacts/*.nupkg; do - dotnet NuGetKeyVaultSignTool sign "$file" --file-digest sha256 --timestamp-rfc3161 http://timestamp.digicert.com --azure-key-vault-url https://duendecodesigninghsm.vault.azure.net/ --azure-key-vault-client-id 18e3de68-2556-4345-8076-a46fad79e474 --azure-key-vault-tenant-id ed3089f0-5401-4758-90eb-066124e2d907 --azure-key-vault-client-secret ${{ secrets.SignClientSecret }} --azure-key-vault-certificate NuGetPackageSigning - done - - name: Push packages to GitHub - run: dotnet nuget push artifacts/*.nupkg --source https://nuget.pkg.github.com/DuendeSoftware/index.json --api-key ${{ secrets.GITHUB_TOKEN }} --skip-duplicate - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NUGET_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Upload Artifacts - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 - with: - name: artifacts - path: templates/artifacts/*.nupkg - overwrite: true - retention-days: 15 - publish: - name: Publish to nuget.org - needs: - - tag - runs-on: ubuntu-latest - environment: - name: nuget.org - steps: - - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 - with: - name: artifacts - path: artifacts - - name: List .net sdks - run: dotnet --list-sdks - - name: Setup Dotnet - uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25 - with: - dotnet-version: |- - 8.0.x - 9.0.203 - 10.0.200 - - name: List files - run: tree - shell: bash - - name: Push packages to nuget.org - run: dotnet nuget push artifacts/*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_ORG_API_KEY }} --skip-duplicate diff --git a/.gitignore b/.gitignore index 28e5cdc2c..4ef916bfa 100644 --- a/.gitignore +++ b/.gitignore @@ -130,6 +130,7 @@ DocProject/Help/html # Click-Once directory publish/ +!**/Commands/Publish/ # Publish Web Output *.[Pp]ublish.xml @@ -170,6 +171,13 @@ bower_components/ # RIA/Silverlight projects Generated_Code/ +# source generated files +Logging.g.cs +LoggerMessage.g.cs +PublicTopLevelProgram.Generated.g.cs +RegexGenerator.g.cs +**/Generated/ + # Backup & report files from converting an old project file # to a newer Visual Studio version. Backup files are not needed, # because we have git ;-) @@ -232,4 +240,5 @@ reports *.db *.db-shm *.db-wal +nul .weave diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 000000000..93fd03607 --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,43 @@ + + + Duende Software + + + All + $(Company) + True + $(Company) + embedded + true + + enable + false + true + + + net10.0 + + + + $(NoWarn);CA1034 + $(NoWarn);CA1040 + $(NoWarn);CA2007 + $(NoWarn);CS1591 + $(NoWarn);NU1507 + + + + + + true + true + + + + + + diff --git a/Directory.Build.targets b/Directory.Build.targets new file mode 100644 index 000000000..058246e40 --- /dev/null +++ b/Directory.Build.targets @@ -0,0 +1 @@ + diff --git a/Directory.Packages.props b/Directory.Packages.props index 3689dd29f..83921a2b4 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,79 +1,87 @@ - - - + + + - - - + + + + - + + + + + + + + - - - - - + + + + - + + - - + + - - - + + + - - - - + - - - + - + + + - + + + + @@ -81,33 +89,30 @@ - - - + + - - + + + + - - - - + + - - \ No newline at end of file diff --git a/aspnetcore-authentication-jwtbearer/aspnetcore-authentication-jwtbearer.slnf b/aspnetcore-authentication-jwtbearer/aspnetcore-authentication-jwtbearer.slnf index a1fbf4023..e06c303f3 100644 --- a/aspnetcore-authentication-jwtbearer/aspnetcore-authentication-jwtbearer.slnf +++ b/aspnetcore-authentication-jwtbearer/aspnetcore-authentication-jwtbearer.slnf @@ -2,7 +2,6 @@ "solution": { "path": "..\\products.slnx", "projects": [ - ".github\\workflow-gen\\workflow-gen.csproj", "aspnetcore-authentication-jwtbearer\\src\\AspNetCore.Authentication.JwtBearer\\AspNetCore.Authentication.JwtBearer.csproj", "aspnetcore-authentication-jwtbearer\\test\\AspNetCore.Authentication.JwtBearer.Tests\\AspNetCore.Authentication.JwtBearer.Tests.csproj" ] diff --git a/aspnetcore-authentication-jwtbearer/build.cs b/aspnetcore-authentication-jwtbearer/build.cs new file mode 100644 index 000000000..91d212dbe --- /dev/null +++ b/aspnetcore-authentication-jwtbearer/build.cs @@ -0,0 +1,25 @@ +#:project ../.github/build/BuildHelpers.csproj + +using BuildHelpers; +using static Bullseye.Targets; + +var repoRoot = Repo.FindRoot(); + +Targets.Shared(repoRoot, "aspnetcore-authentication-jwtbearer/aspnetcore-authentication-jwtbearer.slnf"); + +const string TestsAspNetCoreAuthenticationJwtBearerTests = "tests-asp-net-core-authentication-jwt-bearer-tests"; + +Targets.Test(TestsAspNetCoreAuthenticationJwtBearerTests, "aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests", repoRoot); + +Target(SharedTargets.Default, [ + SharedTargets.CheckSolutions, + SharedTargets.CheckUnusedPackages, + SharedTargets.CheckSortedRefs, + SharedTargets.VerifyFormatting, + SharedTargets.Clean, + SharedTargets.VerifyNoChanges, + SharedTargets.DotnetDevCerts, + TestsAspNetCoreAuthenticationJwtBearerTests +]); + +await RunTargetsAndExitAsync(args); diff --git a/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/AspNetCore.Authentication.JwtBearer.csproj b/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/AspNetCore.Authentication.JwtBearer.csproj index 47ece5695..6c03bc636 100644 --- a/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/AspNetCore.Authentication.JwtBearer.csproj +++ b/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/AspNetCore.Authentication.JwtBearer.csproj @@ -5,15 +5,12 @@ Duende.AspNetCore.Authentication.JwtBearer Duende.AspNetCore.Authentication.JwtBearer - - + - - diff --git a/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPExpirationValidator.cs b/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPExpirationValidator.cs index e2635ab38..17f50752c 100644 --- a/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPExpirationValidator.cs +++ b/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPExpirationValidator.cs @@ -30,7 +30,7 @@ internal class DPoPExpirationValidator if (start < time) { var diff = time - now; - Logger.LogDebug("Expiration check failed. Creation time was too far in the future. The time being checked was {iat}, and clock is now {now}. The time difference is {diff}.", time, now, diff); + Logger.LogDebug("Expiration check failed. Creation time was too far in the future. The time being checked was {Iat}, and clock is now {Now}. The time difference is {Diff}.", time, now, diff); return true; } @@ -39,7 +39,7 @@ internal class DPoPExpirationValidator if (expiration < end) { var diff = now - expiration; - Logger.LogDebug("Expiration check failed. Expiration has already happened. The expiration was at {exp}, and clock is now {now}. The time difference is {diff}.", expiration, now, diff); + Logger.LogDebug("Expiration check failed. Expiration has already happened. The expiration was at {Exp}, and clock is now {Now}. The time difference is {Diff}.", expiration, now, diff); return true; } diff --git a/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPJwtBearerEvents.cs b/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPJwtBearerEvents.cs index 241098f7a..7ea822fd3 100644 --- a/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPJwtBearerEvents.cs +++ b/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPJwtBearerEvents.cs @@ -100,7 +100,7 @@ internal class DPoPJwtBearerEvents if (result.IsError) { - context.Fail(result.ErrorDescription ?? result.Error ?? throw new Exception("No ErrorDescription or Error set.")); + context.Fail(result.ErrorDescription ?? result.Error ?? throw new InvalidOperationException("No ErrorDescription or Error set.")); // we need to stash these values away, so they are available later when the Challenge method is called if (!string.IsNullOrWhiteSpace(result.Error)) @@ -202,19 +202,19 @@ internal class DPoPJwtBearerEvents // For example: // WWW-Authenticate: DPoP error="invalid_dpop_proof", error_description="Invalid 'iat' value." var sb = new StringBuilder(); - sb.Append(OidcConstants.AuthenticationSchemes.AuthorizationHeaderDPoP); + _ = sb.Append(OidcConstants.AuthenticationSchemes.AuthorizationHeaderDPoP); if (context.HttpContext.Items.TryGetValue("DPoP-Error", out var dpopErrorObj) && dpopErrorObj is string error) { - sb.Append(" error=\""); - sb.Append(error); - sb.Append('\"'); + _ = sb.Append(" error=\""); + _ = sb.Append(error); + _ = sb.Append('\"'); if (context.HttpContext.Items.TryGetValue("DPoP-ErrorDescription", out var dpopErrorDescObj) && dpopErrorDescObj is string description) { - sb.Append(", error_description=\""); - sb.Append(description); - sb.Append('\"'); + _ = sb.Append(", error_description=\""); + _ = sb.Append(description); + _ = sb.Append('\"'); } } diff --git a/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPOptions.cs b/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPOptions.cs index 2390247cc..eefe5696f 100644 --- a/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPOptions.cs +++ b/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPOptions.cs @@ -61,7 +61,7 @@ public sealed class DPoPOptions /// Signatures are allowed from RSA, PSA, or ECDSA algorithms with key sizes of 256, 384, or 512 bits. /// /// - public TokenValidationParameters ProofTokenValidationParameters = new() + public TokenValidationParameters ProofTokenValidationParameters { get; set; } = new() { ValidateAudience = false, ValidateIssuer = false, diff --git a/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPProofValidator.cs b/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPProofValidator.cs index d00a03f73..579f9850c 100644 --- a/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPProofValidator.cs +++ b/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPProofValidator.cs @@ -178,7 +178,7 @@ internal class DPoPProofValidator : IDPoPProofValidator } catch (Exception ex) { - Logger.LogDebug("Error parsing DPoP proof token: {error}", ex.Message); + Logger.LogDebug("Error parsing DPoP proof token: {Error}", ex.Message); result.SetError("Malformed DPoP proof token."); return; } @@ -199,7 +199,7 @@ internal class DPoPProofValidator : IDPoPProofValidator } catch (Exception ex) { - Logger.LogDebug("Error parsing DPoP jwk value: {error}", ex.Message); + Logger.LogDebug("Error parsing DPoP jwk value: {Error}", ex.Message); result.SetError("Invalid 'jwk' value."); return; } @@ -234,13 +234,13 @@ internal class DPoPProofValidator : IDPoPProofValidator } catch (Exception ex) { - Logger.LogDebug("Error parsing DPoP proof token: {error}", ex.Message); + Logger.LogDebug("Error parsing DPoP proof token: {Error}", ex.Message); result.SetError("Invalid DPoP proof token."); } if (tokenValidationResult?.Exception != null) { - Logger.LogDebug("Error validating DPoP proof token: {error}", tokenValidationResult.Exception.Message); + Logger.LogDebug("Error validating DPoP proof token: {Error}", tokenValidationResult.Exception.Message); result.SetError("Invalid DPoP proof token."); } @@ -337,7 +337,7 @@ internal class DPoPProofValidator : IDPoPProofValidator } } - private bool HtuValueIsValid(string requestedUri, string? htuValue) + private static bool HtuValueIsValid(string requestedUri, string? htuValue) { if (string.IsNullOrEmpty(requestedUri) || string.IsNullOrEmpty(htuValue)) { diff --git a/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPServiceCollectionExtensions.cs b/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPServiceCollectionExtensions.cs index 24197d9b4..d2bd370c7 100644 --- a/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPServiceCollectionExtensions.cs +++ b/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPServiceCollectionExtensions.cs @@ -20,18 +20,18 @@ public static class DPoPServiceCollectionExtensions /// public IServiceCollection ConfigureDPoPTokensForScheme(string scheme) { - services.AddOptions(); + _ = services.AddOptions(); - services.AddSingleton(); + _ = services.AddSingleton(); services.TryAddTransient(); services.TryAddTransient(); - services.AddTransient(); + _ = services.AddTransient(); services.TryAddTransient(); services.TryAddTransient(); services.TryAddTransient(); - services.AddSingleton>(sp => + _ = services.AddSingleton>(sp => { var events = sp.GetRequiredService(); return new ConfigureJwtBearerOptions(events) @@ -48,7 +48,7 @@ public static class DPoPServiceCollectionExtensions /// public IServiceCollection ConfigureDPoPTokensForScheme(string scheme, Action configure) { - services.Configure(scheme, configure); + _ = services.Configure(scheme, configure); return services.ConfigureDPoPTokensForScheme(scheme); } } diff --git a/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DefaultDPoPNonceValidator.cs b/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DefaultDPoPNonceValidator.cs index bd5674eb9..c744ac821 100644 --- a/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DefaultDPoPNonceValidator.cs +++ b/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DefaultDPoPNonceValidator.cs @@ -1,6 +1,7 @@ // Copyright (c) Duende Software. All rights reserved. // See LICENSE in the project root for license information. +using System.Globalization; using Microsoft.AspNetCore.DataProtection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -38,7 +39,7 @@ internal class DefaultDPoPNonceValidator : IDPoPNonceValidator public string CreateNonce(DPoPProofValidationContext context) { var now = TimeProvider.GetUtcNow().ToUnixTimeSeconds(); - return DataProtector.Protect(now.ToString()); + return DataProtector.Protect(now.ToString(CultureInfo.InvariantCulture)); } public NonceValidationResult ValidateNonce(DPoPProofValidationContext context, string? nonce) @@ -75,7 +76,7 @@ internal class DefaultDPoPNonceValidator : IDPoPNonceValidator } catch (Exception ex) { - Logger.LogDebug("Error parsing DPoP 'nonce' value: {error}", ex.ToString()); + Logger.LogDebug("Error parsing DPoP 'nonce' value: {Error}", ex.ToString()); } time = 0; diff --git a/aspnetcore-authentication-jwtbearer/src/Directory.Build.props b/aspnetcore-authentication-jwtbearer/src/Directory.Build.props index 1a482d53c..63eb9849e 100644 --- a/aspnetcore-authentication-jwtbearer/src/Directory.Build.props +++ b/aspnetcore-authentication-jwtbearer/src/Directory.Build.props @@ -1,6 +1,7 @@ + @@ -9,6 +10,11 @@ aaj- 0.2 Duende.$(MSBuildProjectName) + + + + + $(NoWarn);CA1848;CA1873;CA1031;CA5404;CA1056 diff --git a/aspnetcore-authentication-jwtbearer/src/Directory.Build.targets b/aspnetcore-authentication-jwtbearer/src/Directory.Build.targets new file mode 100644 index 000000000..acbac1881 --- /dev/null +++ b/aspnetcore-authentication-jwtbearer/src/Directory.Build.targets @@ -0,0 +1,4 @@ + + + + diff --git a/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/AspNetCore.Authentication.JwtBearer.Tests.csproj b/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/AspNetCore.Authentication.JwtBearer.Tests.csproj index 16147c0db..2753d17bc 100644 --- a/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/AspNetCore.Authentication.JwtBearer.Tests.csproj +++ b/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/AspNetCore.Authentication.JwtBearer.Tests.csproj @@ -1,5 +1,4 @@ - net10.0 enable @@ -7,7 +6,6 @@ Duende.AspNetCore.Authentication.JwtBearer true - @@ -16,13 +14,9 @@ - - - - + diff --git a/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/DPoP/DPoPIntegrationTests.cs b/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/DPoP/DPoPIntegrationTests.cs index 5f7d6188b..cac08c1dc 100644 --- a/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/DPoP/DPoPIntegrationTests.cs +++ b/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/DPoP/DPoPIntegrationTests.cs @@ -174,18 +174,18 @@ public class DPoPIntegrationTests // Verify that a nonce was issued in the response result.Headers.TryGetValues("DPoP-Nonce", out var nonceValues).ShouldBeTrue(); var serverNonce = nonceValues?.FirstOrDefault(); - serverNonce.ShouldNotBeNull(); + _ = serverNonce.ShouldNotBeNull(); serverNonce.ShouldNotBeEmpty(); // Verify the WWW-Authenticate header contains the use_dpop_nonce error var wwwAuthValues = result.Headers.GetValues(HeaderNames.WWWAuthenticate).FirstOrDefault(); - wwwAuthValues.ShouldNotBeNull(); + _ = wwwAuthValues.ShouldNotBeNull(); wwwAuthValues.ShouldContain("use_dpop_nonce"); // Make a new request with the server issued nonce var proofWithNonce = await CreateProofToken(token, Jwk, HttpMethod.Get, new Uri("http://localhost/"), nonce: DPoPNonce.Parse(serverNonce)); - Api.HttpClient.DefaultRequestHeaders.Remove(OidcConstants.HttpHeaders.DPoP); + _ = Api.HttpClient.DefaultRequestHeaders.Remove(OidcConstants.HttpHeaders.DPoP); Api.HttpClient.DefaultRequestHeaders.Add(OidcConstants.HttpHeaders.DPoP, proofWithNonce); var secondResult = await Api.HttpClient.GetAsync("/"); secondResult.StatusCode.ShouldBe(HttpStatusCode.OK); @@ -202,7 +202,7 @@ public class DPoPIntegrationTests }; Api.OnConfigureServices += services => { - services.AddSingleton(customValidator); + _ = services.AddSingleton(customValidator); }; await Initialize(); @@ -220,13 +220,13 @@ public class DPoPIntegrationTests // Verify that a custom nonce was issued in the response result.Headers.TryGetValues("DPoP-Nonce", out var nonceValues).ShouldBeTrue(); var serverNonce = nonceValues?.FirstOrDefault(); - serverNonce.ShouldNotBeNull(); + _ = serverNonce.ShouldNotBeNull(); serverNonce.ShouldStartWith("custom-nonce-"); // Make a new request with the custom server issued nonce var proofWithNonce = await CreateProofToken(token, Jwk, HttpMethod.Get, new Uri("http://localhost/"), nonce: DPoPNonce.Parse(serverNonce)); - Api.HttpClient.DefaultRequestHeaders.Remove(OidcConstants.HttpHeaders.DPoP); + _ = Api.HttpClient.DefaultRequestHeaders.Remove(OidcConstants.HttpHeaders.DPoP); Api.HttpClient.DefaultRequestHeaders.Add(OidcConstants.HttpHeaders.DPoP, proofWithNonce); var secondResult = await Api.HttpClient.GetAsync("/"); secondResult.StatusCode.ShouldBe(HttpStatusCode.OK); @@ -238,7 +238,7 @@ public class DPoPIntegrationTests var cache = new TestHybridCache(); Api.OnConfigureServices += services => { - services.AddKeyedSingleton(ServiceProviderKeys.ProofTokenReplayHybridCache, cache); + _ = services.AddKeyedSingleton(ServiceProviderKeys.ProofTokenReplayHybridCache, cache); }; await Initialize(); @@ -270,12 +270,12 @@ public class DPoPIntegrationTests /// private async Task LoginAndGetToken() { - await App.LoginAsync("sub"); + _ = await App.LoginAsync("sub"); var response = await App.BrowserClient.GetAsync(App.Url("/user_token")); var token = await response.Content.ReadFromJsonAsync(); - token.ShouldNotBeNull(); - token.AccessToken.ToString().ShouldNotBeNull(); - token.DPoPJsonWebKey.ShouldNotBeNull(); + _ = token.ShouldNotBeNull(); + _ = token.AccessToken.ToString().ShouldNotBeNull(); + _ = token.DPoPJsonWebKey.ShouldNotBeNull(); return token; } @@ -301,7 +301,7 @@ public class DPoPIntegrationTests }; var proof = await dpopService.CreateProofTokenAsync(proofRequest); - proof.ShouldNotBeNull(); + _ = proof.ShouldNotBeNull(); return proof.Value; } @@ -329,10 +329,10 @@ public class DPoPIntegrationTests var api = new ApiHost(IdentityServer, baseAddress); api.OnConfigureServices += services => { - services.ConfigureDPoPTokensForScheme(ApiHost.AuthenticationScheme, + _ = services.ConfigureDPoPTokensForScheme(ApiHost.AuthenticationScheme, opt => ApiOptions?.Invoke(opt)); - services.AddKeyedHybridCache(ServiceProviderKeys.ProofTokenReplayHybridCache); + _ = services.AddKeyedHybridCache(ServiceProviderKeys.ProofTokenReplayHybridCache); }; api.OnConfigure += app => diff --git a/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/DPoP/DPoPProofValidatorTestBase.cs b/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/DPoP/DPoPProofValidatorTestBase.cs index cf5967c79..c31880cfb 100644 --- a/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/DPoP/DPoPProofValidatorTestBase.cs +++ b/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/DPoP/DPoPProofValidatorTestBase.cs @@ -10,7 +10,6 @@ using Duende.AspNetCore.Authentication.JwtBearer.TestFramework; using Duende.IdentityModel; using Microsoft.AspNetCore.DataProtection; using Microsoft.Extensions.Logging.Testing; -using Microsoft.Extensions.Time.Testing; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; diff --git a/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/DPoP/FreshnessTests.cs b/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/DPoP/FreshnessTests.cs index c60df80a7..e7bffe15a 100644 --- a/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/DPoP/FreshnessTests.cs +++ b/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/DPoP/FreshnessTests.cs @@ -12,7 +12,7 @@ public class FreshnessTests : DPoPProofValidatorTestBase { var nonce = DataProtector.Protect(IssuedAt.ToString()); - NonceValidator.TryGetUnixTimeFromNonce(nonce, out var actual); + _ = NonceValidator.TryGetUnixTimeFromNonce(nonce, out var actual); actual.ShouldBe(IssuedAt); } @@ -22,7 +22,7 @@ public class FreshnessTests : DPoPProofValidatorTestBase { var nonce = DataProtector.Protect("garbage that isn't a long"); - NonceValidator.TryGetUnixTimeFromNonce(nonce, out var actual); + _ = NonceValidator.TryGetUnixTimeFromNonce(nonce, out var actual); actual.ShouldBe(0); } diff --git a/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/TestFramework/ApiHost.cs b/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/TestFramework/ApiHost.cs index 49d31aed7..f58756cbb 100644 --- a/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/TestFramework/ApiHost.cs +++ b/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/TestFramework/ApiHost.cs @@ -26,11 +26,11 @@ public class ApiHost : GenericHost private void ConfigureServices(IServiceCollection services) { - services.AddHybridCache(); - services.AddRouting(); - services.AddAuthorization(); + _ = services.AddHybridCache(); + _ = services.AddRouting(); + _ = services.AddAuthorization(); - services.AddAuthentication(AuthenticationScheme) + _ = services.AddAuthentication(AuthenticationScheme) .AddJwtBearer(AuthenticationScheme, options => { options.Authority = _identityServerHost.Url(); @@ -42,7 +42,7 @@ public class ApiHost : GenericHost private void Configure(IApplicationBuilder app) { - app.Use(async (context, next) => + _ = app.Use(async (context, next) => { ApiInvoked.Invoke(context); if (ApiStatusCodeToReturn != null) @@ -55,9 +55,9 @@ public class ApiHost : GenericHost await next(); }); - app.UseRouting(); + _ = app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); + _ = app.UseAuthentication(); + _ = app.UseAuthorization(); } } diff --git a/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/TestFramework/AppHost.cs b/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/TestFramework/AppHost.cs index f35484908..19d7404d9 100644 --- a/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/TestFramework/AppHost.cs +++ b/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/TestFramework/AppHost.cs @@ -40,10 +40,10 @@ public class AppHost : GenericHost private void ConfigureServices(IServiceCollection services) { - services.AddRouting(); - services.AddAuthorization(); + _ = services.AddRouting(); + _ = services.AddAuthorization(); - services.AddAuthentication(options => + _ = services.AddAuthentication(options => { options.DefaultScheme = "cookie"; options.DefaultChallengeScheme = "oidc"; @@ -80,7 +80,7 @@ public class AppHost : GenericHost if (IdentityServerHttpHandler != null) { // allow discovery document - IdentityServerHttpHandler.When("/.well-known/*") + _ = IdentityServerHttpHandler.When("/.well-known/*") .Respond(identityServerHandler); options.BackchannelHttpHandler = IdentityServerHttpHandler; @@ -93,8 +93,8 @@ public class AppHost : GenericHost options.ProtocolValidator.RequireNonce = false; }); - services.AddDistributedMemoryCache(); - services.AddOpenIdConnectAccessTokenManagement(opt => + _ = services.AddDistributedMemoryCache(); + _ = services.AddOpenIdConnectAccessTokenManagement(opt => { _configureUserTokenManagementOptions?.Invoke(opt); }); @@ -103,13 +103,13 @@ public class AppHost : GenericHost private void Configure(IApplicationBuilder app) { - app.UseAuthentication(); - app.UseRouting(); - app.UseAuthorization(); + _ = app.UseAuthentication(); + _ = app.UseRouting(); + _ = app.UseAuthorization(); - app.UseEndpoints(endpoints => + _ = app.UseEndpoints(endpoints => { - endpoints.MapGet("/login", async context => + _ = endpoints.MapGet("/login", async context => { await context.ChallengeAsync(new AuthenticationProperties { @@ -117,18 +117,18 @@ public class AppHost : GenericHost }); }); - endpoints.MapGet("/logout", async context => + _ = endpoints.MapGet("/logout", async context => { await context.SignOutAsync(); }); - endpoints.MapGet("/user_token", async context => + _ = endpoints.MapGet("/user_token", async context => { var tokenResult = await context.GetUserAccessTokenAsync(); await context.Response.WriteAsJsonAsync(tokenResult.Token); }); - endpoints.MapGet("/user_token_with_resource/{resource}", async (string resource, HttpContext context) => + _ = endpoints.MapGet("/user_token_with_resource/{resource}", async (string resource, HttpContext context) => { var token = await context.GetUserAccessTokenAsync(new UserTokenRequestParameters { @@ -137,7 +137,7 @@ public class AppHost : GenericHost await context.Response.WriteAsJsonAsync(token); }); - endpoints.MapGet("/client_token", async context => + _ = endpoints.MapGet("/client_token", async context => { var token = await context.GetClientAccessTokenAsync(); await context.Response.WriteAsJsonAsync(token); diff --git a/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/TestFramework/GenericHost.cs b/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/TestFramework/GenericHost.cs index 311aef350..8a40efdaf 100644 --- a/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/TestFramework/GenericHost.cs +++ b/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/TestFramework/GenericHost.cs @@ -35,7 +35,7 @@ public class GenericHost public TestServer Server { get => _server ?? throw new InvalidOperationException( - $"Attempt to use {nameof(Server)} before it was initialized. Did you forget to call ${Initialize}?"); + $"Attempt to use {nameof(Server)} before it was initialized. Did you forget to call {nameof(Initialize)}?"); private set => _server = value; } @@ -81,7 +81,7 @@ public class GenericHost EnvironmentName = IsDevelopment ? "Development" : "Production", ApplicationName = HostAssembly?.GetName()?.Name }); - builder.WebHost + _ = builder.WebHost .UseTestServer(); ConfigureServices(builder.Services); @@ -101,15 +101,15 @@ public class GenericHost private void ConfigureServices(IServiceCollection services) { // This adds log messages to the output of our tests when they fail. - services.AddLogging(options => + _ = services.AddLogging(options => { // If you need different log output to understand a test failure, configure it here - options.SetMinimumLevel(LogLevel.Error); - options.AddFilter("Duende", LogLevel.Information); - options.AddFilter("Duende.IdentityServer.License", LogLevel.Error); - options.AddFilter("Duende.IdentityServer.Startup", LogLevel.Error); + _ = options.SetMinimumLevel(LogLevel.Error); + _ = options.AddFilter("Duende", LogLevel.Information); + _ = options.AddFilter("Duende.IdentityServer.License", LogLevel.Error); + _ = options.AddFilter("Duende.IdentityServer.Startup", LogLevel.Error); - options.AddXUnit(_testOutputHelper); + _ = options.AddXUnit(_testOutputHelper); }); OnConfigureServices(services); diff --git a/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/TestFramework/IdentityServerHost.cs b/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/TestFramework/IdentityServerHost.cs index fe06c7b4e..8cca5f3d2 100644 --- a/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/TestFramework/IdentityServerHost.cs +++ b/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/TestFramework/IdentityServerHost.cs @@ -39,10 +39,10 @@ public class IdentityServerHost : GenericHost private void ConfigureServices(IServiceCollection services) { - services.AddRouting(); - services.AddAuthorization(); + _ = services.AddRouting(); + _ = services.AddAuthorization(); - services.AddIdentityServer(options => + _ = services.AddIdentityServer(options => { options.EmitStaticAudienceClaim = true; @@ -58,19 +58,19 @@ public class IdentityServerHost : GenericHost private void Configure(IApplicationBuilder app) { - app.UseRouting(); + _ = app.UseRouting(); - app.UseIdentityServer(); - app.UseAuthorization(); + _ = app.UseIdentityServer(); + _ = app.UseAuthorization(); - app.UseEndpoints(endpoints => + _ = app.UseEndpoints(endpoints => { - endpoints.MapGet("/account/login", context => + _ = endpoints.MapGet("/account/login", context => { return Task.CompletedTask; }); - endpoints.MapGet("/account/logout", async context => + _ = endpoints.MapGet("/account/logout", async context => { // signout as if the user were prompted await context.SignOutAsync(); diff --git a/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/TestFramework/TestBrowserClient.cs b/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/TestFramework/TestBrowserClient.cs index b4a5b65c2..4c3465ee5 100644 --- a/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/TestFramework/TestBrowserClient.cs +++ b/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/TestFramework/TestBrowserClient.cs @@ -71,7 +71,7 @@ public class TestBrowserClient : HttpClient { LastResponse.StatusCode.ShouldBe((HttpStatusCode)302); var location = LastResponse.Headers.Location!.ToString(); - await GetAsync(location); + _ = await GetAsync(location); } // TODO - Finish conversion from CSQuery to AngleSharp (CSQuery is unmaintained) diff --git a/aspnetcore-authentication-jwtbearer/test/Directory.Build.props b/aspnetcore-authentication-jwtbearer/test/Directory.Build.props index e1c6ae89d..8178f7eeb 100644 --- a/aspnetcore-authentication-jwtbearer/test/Directory.Build.props +++ b/aspnetcore-authentication-jwtbearer/test/Directory.Build.props @@ -1,4 +1,5 @@ + diff --git a/bff/bff.slnf b/bff/bff.slnf index b9b3f5e13..74a486961 100644 --- a/bff/bff.slnf +++ b/bff/bff.slnf @@ -2,7 +2,6 @@ "solution": { "path": "..\\products.slnx", "projects": [ - ".github\\workflow-gen\\workflow-gen.csproj", "bff\\hosts\\Blazor\\PerComponent\\Hosts.Bff.Blazor.PerComponent.Client\\Hosts.Bff.Blazor.PerComponent.Client.csproj", "bff\\hosts\\Blazor\\PerComponent\\Hosts.Bff.Blazor.PerComponent\\Hosts.Bff.Blazor.PerComponent.csproj", "bff\\hosts\\Blazor\\WebAssembly\\Hosts.Bff.Blazor.WebAssembly.Client\\Hosts.Bff.Blazor.WebAssembly.Client.csproj", diff --git a/bff/bff.v3.ncrunchsolution b/bff/bff.v3.ncrunchsolution deleted file mode 100644 index fe9b0700d..000000000 --- a/bff/bff.v3.ncrunchsolution +++ /dev/null @@ -1,8 +0,0 @@ - - - True - False - True - True - - \ No newline at end of file diff --git a/bff/build.cs b/bff/build.cs new file mode 100644 index 000000000..d2de68578 --- /dev/null +++ b/bff/build.cs @@ -0,0 +1,28 @@ +#:project ../.github/build/BuildHelpers.csproj + +using BuildHelpers; +using static Bullseye.Targets; + +var repoRoot = Repo.FindRoot(); + +Targets.Shared(repoRoot, "bff/bff.slnf"); + +const string TestsBffTests = "tests-bff-tests"; +const string TestsHostsTests = "tests-hosts-tests"; + +Targets.Test(TestsBffTests, "bff/test/Bff.Tests", repoRoot); +Targets.Test(TestsHostsTests, "bff/test/Hosts.Tests", repoRoot); + +Target(SharedTargets.Default, [ + SharedTargets.CheckSolutions, + SharedTargets.CheckUnusedPackages, + SharedTargets.CheckSortedRefs, + SharedTargets.VerifyFormatting, + SharedTargets.Clean, + SharedTargets.VerifyNoChanges, + SharedTargets.DotnetDevCerts, + TestsBffTests, + TestsHostsTests +]); + +await RunTargetsAndExitAsync(args); diff --git a/bff/hosts/Blazor/PerComponent/Hosts.Bff.Blazor.PerComponent/Program.cs b/bff/hosts/Blazor/PerComponent/Hosts.Bff.Blazor.PerComponent/Program.cs index 14314fc20..53a89a072 100644 --- a/bff/hosts/Blazor/PerComponent/Hosts.Bff.Blazor.PerComponent/Program.cs +++ b/bff/hosts/Blazor/PerComponent/Hosts.Bff.Blazor.PerComponent/Program.cs @@ -15,26 +15,26 @@ var builder = WebApplication.CreateBuilder(args); builder.AddServiceDefaults(); // BFF setup for blazor -builder.Services.AddBff() +_ = builder.Services.AddBff() .AddServerSideSessions() .AddBlazorServer() .AddRemoteApis(); -builder.Services.AddUserAccessTokenHttpClient("callApi", +_ = builder.Services.AddUserAccessTokenHttpClient("callApi", configureClient: client => client.BaseAddress = new Uri("https://localhost:5010/")); // General blazor services -builder.Services.AddRazorComponents() +_ = builder.Services.AddRazorComponents() .AddInteractiveServerComponents() .AddInteractiveWebAssemblyComponents(); -builder.Services.AddCascadingAuthenticationState(); +_ = builder.Services.AddCascadingAuthenticationState(); // Service used by the sample to describe where code is running -builder.Services.AddScoped(); +_ = builder.Services.AddScoped(); -builder.Services.AddAuthentication(options => +_ = builder.Services.AddAuthentication(options => { options.DefaultScheme = "cookie"; options.DefaultChallengeScheme = "oidc"; @@ -72,7 +72,7 @@ builder.Services.AddAuthentication(options => var app = builder.Build(); -app.UseHttpLogging(); +_ = app.UseHttpLogging(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) @@ -81,25 +81,25 @@ if (app.Environment.IsDevelopment()) } else { - app.UseExceptionHandler("/Error", createScopeForErrors: true); + _ = app.UseExceptionHandler("/Error", createScopeForErrors: true); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. - app.UseHsts(); + _ = app.UseHsts(); } -app.UseHttpsRedirection(); +_ = app.UseHttpsRedirection(); -app.UseStaticFiles(); +_ = app.UseStaticFiles(); -app.UseRouting(); -app.UseAuthentication(); -app.UseBff(); -app.UseAuthorization(); -app.UseAntiforgery(); +_ = app.UseRouting(); +_ = app.UseAuthentication(); +_ = app.UseBff(); +_ = app.UseAuthorization(); +_ = app.UseAntiforgery(); -app.MapRemoteBffApiEndpoint("/remote-apis/user-token", new Uri("https://localhost:5010")) +_ = app.MapRemoteBffApiEndpoint("/remote-apis/user-token", new Uri("https://localhost:5010")) .WithAccessToken(RequiredTokenType.User); -app.MapRazorComponents() +_ = app.MapRazorComponents() .AddInteractiveServerRenderMode() .AddInteractiveWebAssemblyRenderMode() .AddAdditionalAssemblies(typeof(Hosts.Bff.Blazor.PerComponent.Client._Imports).Assembly); diff --git a/bff/hosts/Blazor/WebAssembly/Hosts.Bff.Blazor.WebAssembly/Program.cs b/bff/hosts/Blazor/WebAssembly/Hosts.Bff.Blazor.WebAssembly/Program.cs index 2f1e8fcb3..57097227d 100644 --- a/bff/hosts/Blazor/WebAssembly/Hosts.Bff.Blazor.WebAssembly/Program.cs +++ b/bff/hosts/Blazor/WebAssembly/Hosts.Bff.Blazor.WebAssembly/Program.cs @@ -11,12 +11,12 @@ var builder = WebApplication.CreateBuilder(args); builder.AddServiceDefaults(); -builder.Services.AddRazorComponents() +_ = builder.Services.AddRazorComponents() .AddInteractiveWebAssemblyComponents(); -builder.Services.AddBff(); +_ = builder.Services.AddBff(); -builder.Services.AddAuthentication(options => +_ = builder.Services.AddAuthentication(options => { options.DefaultScheme = "cookie"; options.DefaultChallengeScheme = "oidc"; @@ -48,10 +48,10 @@ builder.Services.AddAuthentication(options => options.Scope.Add("api"); options.Scope.Add("offline_access"); }); -builder.Services.AddCascadingAuthenticationState(); -builder.Services.AddScoped(); +_ = builder.Services.AddCascadingAuthenticationState(); +_ = builder.Services.AddScoped(); -builder.Services.AddAuthorization(); +_ = builder.Services.AddAuthorization(); var app = builder.Build(); @@ -62,24 +62,24 @@ if (app.Environment.IsDevelopment()) } else { - app.UseExceptionHandler("/Error", createScopeForErrors: true); + _ = app.UseExceptionHandler("/Error", createScopeForErrors: true); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. - app.UseHsts(); + _ = app.UseHsts(); } -app.UseHttpLogging(); +_ = app.UseHttpLogging(); -app.UseHttpsRedirection(); +_ = app.UseHttpsRedirection(); -app.UseStaticFiles(); +_ = app.UseStaticFiles(); -app.UseRouting(); -app.UseAuthentication(); -app.UseBff(); -app.UseAuthorization(); -app.UseAntiforgery(); +_ = app.UseRouting(); +_ = app.UseAuthentication(); +_ = app.UseBff(); +_ = app.UseAuthorization(); +_ = app.UseAntiforgery(); -app.MapRazorComponents() +_ = app.MapRazorComponents() .AddInteractiveWebAssemblyRenderMode() .AddAdditionalAssemblies(typeof(Hosts.Bff.Blazor.WebAssembly.Client._Imports).Assembly); diff --git a/bff/hosts/Directory.Build.props b/bff/hosts/Directory.Build.props index 80ed9fbe9..9bcc652e2 100644 --- a/bff/hosts/Directory.Build.props +++ b/bff/hosts/Directory.Build.props @@ -1,5 +1,6 @@ + + None net10.0 - + false - - diff --git a/bff/hosts/Hosts.AppHost/Hosts.AppHost.csproj b/bff/hosts/Hosts.AppHost/Hosts.AppHost.csproj index 81d97bba9..04d9dbdcd 100644 --- a/bff/hosts/Hosts.AppHost/Hosts.AppHost.csproj +++ b/bff/hosts/Hosts.AppHost/Hosts.AppHost.csproj @@ -5,6 +5,7 @@ enable true 616547e2-3a28-4c9d-8685-f4ac02581162 + diff --git a/bff/hosts/Hosts.Bff.DPoP/Extensions.cs b/bff/hosts/Hosts.Bff.DPoP/Extensions.cs index 083ba573c..bf6a7a5c5 100644 --- a/bff/hosts/Hosts.Bff.DPoP/Extensions.cs +++ b/bff/hosts/Hosts.Bff.DPoP/Extensions.cs @@ -20,7 +20,7 @@ internal static class Extensions var yarpBuilder = services.AddReverseProxy() .AddBffExtensions(); - yarpBuilder.LoadFromMemory( + _ = yarpBuilder.LoadFromMemory( new[] { new RouteConfig() @@ -79,7 +79,7 @@ internal static class Extensions }); // Add BFF services to DI - also add server-side session management - services.AddBff(options => + _ = services.AddBff(options => { var rsaKey = new RsaSecurityKey(RSA.Create(2048)); var jwkKey = JsonWebKeyConverter.ConvertFromSecurityKey(rsaKey); @@ -91,10 +91,10 @@ internal static class Extensions .AddServerSideSessions(); // local APIs - services.AddControllers(); + _ = services.AddControllers(); // cookie options - services.AddAuthentication(options => + _ = services.AddAuthentication(options => { options.DefaultScheme = "cookie"; options.DefaultChallengeScheme = "oidc"; @@ -136,7 +136,7 @@ internal static class Extensions options.Scope.Add("offline_access"); }); - services.AddUserAccessTokenHttpClient("api", + _ = services.AddUserAccessTokenHttpClient("api", configureClient: client => { client.BaseAddress = new Uri("https://localhost:5011/api"); @@ -147,23 +147,23 @@ internal static class Extensions public static WebApplication ConfigurePipeline(this WebApplication app) { - app.UseHttpLogging(); - app.UseDeveloperExceptionPage(); + _ = app.UseHttpLogging(); + _ = app.UseDeveloperExceptionPage(); - app.UseDefaultFiles(); - app.UseStaticFiles(); + _ = app.UseDefaultFiles(); + _ = app.UseStaticFiles(); - app.UseAuthentication(); - app.UseRouting(); + _ = app.UseAuthentication(); + _ = app.UseRouting(); // adds antiforgery protection for local APIs - app.UseBff(); + _ = app.UseBff(); // adds authorization for local and remote API endpoints - app.UseAuthorization(); + _ = app.UseAuthorization(); // local APIs - app.MapControllers() + _ = app.MapControllers() .RequireAuthorization() .AsBffApiEndpoint(); @@ -171,9 +171,9 @@ internal static class Extensions app.MapBffManagementEndpoints(); // proxy endpoints using yarp - app.MapReverseProxy(proxyApp => + _ = app.MapReverseProxy(proxyApp => { - proxyApp.UseAntiforgeryCheck(); + _ = proxyApp.UseAntiforgeryCheck(); }); // proxy endpoints using BFF's simplified wrapper @@ -184,22 +184,22 @@ internal static class Extensions private static void MapRemoteUrls(IEndpointRouteBuilder app) { // On this path, we use a client credentials token - app.MapRemoteBffApiEndpoint("/api/client-token", new Uri("https://localhost:5011")) + _ = app.MapRemoteBffApiEndpoint("/api/client-token", new Uri("https://localhost:5011")) .WithAccessToken(RequiredTokenType.Client); // On this path, we use a user token if logged in, and fall back to a client credentials token if not - app.MapRemoteBffApiEndpoint("/api/user-or-client-token", new Uri("https://localhost:5011")) + _ = app.MapRemoteBffApiEndpoint("/api/user-or-client-token", new Uri("https://localhost:5011")) .WithAccessToken(RequiredTokenType.UserOrClient); // On this path, we make anonymous requests - app.MapRemoteBffApiEndpoint("/api/anonymous", new Uri("https://localhost:5011")); + _ = app.MapRemoteBffApiEndpoint("/api/anonymous", new Uri("https://localhost:5011")); // On this path, we use the client token only if the user is logged in - app.MapRemoteBffApiEndpoint("/api/optional-user-token", new Uri("https://localhost:5011")) + _ = app.MapRemoteBffApiEndpoint("/api/optional-user-token", new Uri("https://localhost:5011")) .WithAccessToken(RequiredTokenType.UserOrNone); // On this path, we require the user token - app.MapRemoteBffApiEndpoint("/api/user-token", new Uri("https://localhost:5011")) + _ = app.MapRemoteBffApiEndpoint("/api/user-token", new Uri("https://localhost:5011")) .WithAccessToken(); } } diff --git a/bff/hosts/Hosts.Bff.EF/Extensions.cs b/bff/hosts/Hosts.Bff.EF/Extensions.cs index ff2dc1b8e..efff327d9 100644 --- a/bff/hosts/Hosts.Bff.EF/Extensions.cs +++ b/bff/hosts/Hosts.Bff.EF/Extensions.cs @@ -17,12 +17,12 @@ internal static class Extensions { var services = builder.Services; var configuration = builder.Configuration; - services.AddDataProtection() + _ = services.AddDataProtection() .SetApplicationName("JS-EF-Sample"); // Add BFF services to DI - also add server-side session management var cn = configuration.GetConnectionString("db"); - services.AddBff(options => + _ = services.AddBff(options => { options.BackchannelLogoutAllUserSessions = true; }) @@ -30,15 +30,15 @@ internal static class Extensions .AddEntityFrameworkServerSideSessions(options => { //options.UseSqlServer(cn); - options.UseSqlite(cn, opt => opt.MigrationsAssembly(typeof(UserSessions).Assembly.FullName)); + _ = options.UseSqlite(cn, opt => opt.MigrationsAssembly(typeof(UserSessions).Assembly.FullName)); }) .AddSessionCleanupBackgroundProcess(); // local APIs - services.AddControllers(); + _ = services.AddControllers(); // cookie options - services.AddAuthentication(options => + _ = services.AddAuthentication(options => { options.DefaultScheme = "cookie"; options.DefaultChallengeScheme = "oidc"; @@ -79,24 +79,24 @@ internal static class Extensions public static WebApplication ConfigurePipeline(this WebApplication app) { - app.UseHttpLogging(); - app.UseDeveloperExceptionPage(); + _ = app.UseHttpLogging(); + _ = app.UseDeveloperExceptionPage(); - app.UseDefaultFiles(); - app.UseStaticFiles(); + _ = app.UseDefaultFiles(); + _ = app.UseStaticFiles(); - app.UseAuthentication(); - app.UseRouting(); + _ = app.UseAuthentication(); + _ = app.UseRouting(); // adds antiforgery protection for local APIs - app.UseBff(); + _ = app.UseBff(); // adds authorization for local and remote API endpoints - app.UseAuthorization(); + _ = app.UseAuthorization(); // local APIs - app.MapControllers() + _ = app.MapControllers() .RequireAuthorization() .AsBffApiEndpoint(); @@ -104,7 +104,7 @@ internal static class Extensions // all calls to /api/* will be forwarded to the remote API // user or client access token will be attached in API call // user access token will be managed automatically using the refresh token - app.MapRemoteBffApiEndpoint("/api", new Uri("https://localhost:5010")) + _ = app.MapRemoteBffApiEndpoint("/api", new Uri("https://localhost:5010")) .WithAccessToken(RequiredTokenType.UserOrClient); return app; diff --git a/bff/hosts/Hosts.Bff.EF/Hosts.Bff.EF.csproj b/bff/hosts/Hosts.Bff.EF/Hosts.Bff.EF.csproj index d83e84e70..95671fede 100644 --- a/bff/hosts/Hosts.Bff.EF/Hosts.Bff.EF.csproj +++ b/bff/hosts/Hosts.Bff.EF/Hosts.Bff.EF.csproj @@ -1,16 +1,13 @@ - net10.0 Bff.EF - - + - @@ -19,5 +16,4 @@ - diff --git a/bff/hosts/Hosts.Bff.Performance/Hosts.Bff.Performance.csproj b/bff/hosts/Hosts.Bff.Performance/Hosts.Bff.Performance.csproj index 40c5a2d69..da2ec451d 100644 --- a/bff/hosts/Hosts.Bff.Performance/Hosts.Bff.Performance.csproj +++ b/bff/hosts/Hosts.Bff.Performance/Hosts.Bff.Performance.csproj @@ -1,19 +1,15 @@ - net10.0 enable enable - - + - - diff --git a/bff/hosts/Hosts.Bff.Performance/Program.cs b/bff/hosts/Hosts.Bff.Performance/Program.cs index 8b1c506d1..8899a4e88 100644 --- a/bff/hosts/Hosts.Bff.Performance/Program.cs +++ b/bff/hosts/Hosts.Bff.Performance/Program.cs @@ -16,21 +16,21 @@ var builder = Host.CreateApplicationBuilder(); if (startupConfiguration.IsServiceEnabled("api")) { - builder.Services.Configure(builder.Configuration); - builder.Services.AddHostedService(); + _ = builder.Services.Configure(builder.Configuration); + _ = builder.Services.AddHostedService(); } if (startupConfiguration.IsServiceEnabled("idsrv")) { - builder.Services.Configure(builder.Configuration); - builder.Services.AddHostedService(); + _ = builder.Services.Configure(builder.Configuration); + _ = builder.Services.AddHostedService(); } if (startupConfiguration.IsServiceEnabled("bff")) { - builder.Services.Configure(builder.Configuration); - builder.Services.AddHostedService(); - builder.Services.AddHostedService(); + _ = builder.Services.Configure(builder.Configuration); + _ = builder.Services.AddHostedService(); + _ = builder.Services.AddHostedService(); } // Add services to the container. diff --git a/bff/hosts/Hosts.Bff.Performance/Services/ApiHostedService.cs b/bff/hosts/Hosts.Bff.Performance/Services/ApiHostedService.cs index d3c31553c..dbf7b20ab 100644 --- a/bff/hosts/Hosts.Bff.Performance/Services/ApiHostedService.cs +++ b/bff/hosts/Hosts.Bff.Performance/Services/ApiHostedService.cs @@ -12,16 +12,16 @@ public class ApiHostedService(IOptions apiSettings) : BackgroundSer protected override Task ExecuteAsync(Ct stoppingToken) { var builder = WebApplication.CreateBuilder(); - builder.AddServiceDefaults(); + _ = builder.AddServiceDefaults(); // Configure Kestrel to listen on the specified Uri - builder.WebHost.UseUrls(Settings.ApiUrl.ToString()); + _ = builder.WebHost.UseUrls(Settings.ApiUrl.ToString()); var app = builder.Build(); - app.UseRouting(); + _ = app.UseRouting(); - app.MapGet("/", () => "ok"); + _ = app.MapGet("/", () => "ok"); return app.RunAsync(stoppingToken); } diff --git a/bff/hosts/Hosts.Bff.Performance/Services/BffService.cs b/bff/hosts/Hosts.Bff.Performance/Services/BffService.cs index 730540d7c..de7379c12 100644 --- a/bff/hosts/Hosts.Bff.Performance/Services/BffService.cs +++ b/bff/hosts/Hosts.Bff.Performance/Services/BffService.cs @@ -23,18 +23,18 @@ public abstract class BffService(string[] urlConfigKeys, IConfiguration config, .ToArray(); var builder = WebApplication.CreateBuilder(); - builder.AddServiceDefaults(); + _ = builder.AddServiceDefaults(); // Configure Kestrel to listen on the specified Uri - builder.WebHost.UseUrls(urls); + _ = builder.WebHost.UseUrls(urls); - builder.Services.Configure(options => + _ = builder.Services.Configure(options => { options.ForwardedHeaders = ForwardedHeaders.All; options.KnownProxies.Clear(); options.KnownIPNetworks.Clear(); }); - builder.Services.AddAuthorization(); + _ = builder.Services.AddAuthorization(); ConfigureServices(builder.Services); var bffBuilder = builder.Services.AddBff() @@ -44,35 +44,35 @@ public abstract class BffService(string[] urlConfigKeys, IConfiguration config, // Build and run the web app var app = builder.Build(); - app.UseForwardedHeaders(); + _ = app.UseForwardedHeaders(); - app.UseHttpsRedirection(); + _ = app.UseHttpsRedirection(); - app.UseRouting(); + _ = app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); + _ = app.UseAuthentication(); + _ = app.UseAuthorization(); - app.UseBff(); + _ = app.UseBff(); ConfigureApp(app); - app.MapGet("/local_anon", () => DateTime.Now.ToString("s")) + _ = app.MapGet("/local_anon", () => DateTime.Now.ToString("s")) .AsBffApiEndpoint() .AllowAnonymous(); - app.MapGet("/local", () => DateTime.Now.ToString("s")) + _ = app.MapGet("/local", () => DateTime.Now.ToString("s")) .RequireAuthorization() .AsBffApiEndpoint(); - app.MapRemoteBffApiEndpoint("/remote_anon", Settings.ApiUrl) + _ = app.MapRemoteBffApiEndpoint("/remote_anon", Settings.ApiUrl) .WithAccessToken(RequiredTokenType.None); - app.MapRemoteBffApiEndpoint("/remote_user", Settings.ApiUrl) + _ = app.MapRemoteBffApiEndpoint("/remote_user", Settings.ApiUrl) .WithAccessToken(); - app.MapRemoteBffApiEndpoint("/remote_client", Settings.ApiUrl) + _ = app.MapRemoteBffApiEndpoint("/remote_client", Settings.ApiUrl) .WithAccessToken(RequiredTokenType.Client); // Todo: Make sure this is mapped implicitly diff --git a/bff/hosts/Hosts.Bff.Performance/Services/IdentityServerService.cs b/bff/hosts/Hosts.Bff.Performance/Services/IdentityServerService.cs index 96be741ad..039b6439d 100644 --- a/bff/hosts/Hosts.Bff.Performance/Services/IdentityServerService.cs +++ b/bff/hosts/Hosts.Bff.Performance/Services/IdentityServerService.cs @@ -20,19 +20,19 @@ public class IdentityServerService(IOptions settings, IC protected override Task ExecuteAsync(Ct stoppingToken) { var builder = WebApplication.CreateBuilder(); - builder.AddServiceDefaults(); + _ = builder.AddServiceDefaults(); // Configure Kestrel to listen on the specified Uri - builder.WebHost.UseUrls(Settings.IdentityServerUrl); + _ = builder.WebHost.UseUrls(Settings.IdentityServerUrl); - builder.Services.Configure(options => + _ = builder.Services.Configure(options => { options.ForwardedHeaders = ForwardedHeaders.All; options.KnownProxies.Clear(); options.KnownIPNetworks.Clear(); }); - builder.Services.AddAuthorization(); - builder.Services.AddHttpLogging(); + _ = builder.Services.AddAuthorization(); + _ = builder.Services.AddHttpLogging(); var isBuilder = builder.Services.AddIdentityServer(options => { @@ -61,8 +61,8 @@ public class IdentityServerService(IOptions settings, IC ; // in-memory, code config - isBuilder.AddInMemoryIdentityResources(Config.IdentityResources); - isBuilder.AddInMemoryApiScopes(Config.ApiScopes); + _ = isBuilder.AddInMemoryIdentityResources(Config.IdentityResources); + _ = isBuilder.AddInMemoryApiScopes(Config.ApiScopes); var bffUrls = config.AsEnumerable() .Where(x => x.Key.StartsWith("BFFURL")) @@ -77,7 +77,7 @@ public class IdentityServerService(IOptions settings, IC bffUrls.Add(bffUrl2 + "/path" + i); } - isBuilder.AddInMemoryClients([new Client + _ = isBuilder.AddInMemoryClients([new Client { ClientId = "bff.perf", ClientSecrets = [new Secret("secret".Sha256())], @@ -96,22 +96,22 @@ public class IdentityServerService(IOptions settings, IC AccessTokenLifetime = 15 // Force refresh }]); - isBuilder.AddInMemoryApiResources(Config.ApiResources); + _ = isBuilder.AddInMemoryApiResources(Config.ApiResources); var app = builder.Build(); - app.UseForwardedHeaders(); + _ = app.UseForwardedHeaders(); - app.UseHttpLogging(); - app.UseDeveloperExceptionPage(); - app.UseStaticFiles(); + _ = app.UseHttpLogging(); + _ = app.UseDeveloperExceptionPage(); + _ = app.UseStaticFiles(); - app.UseRouting(); - app.UseIdentityServer(); - app.UseAuthorization(); + _ = app.UseRouting(); + _ = app.UseIdentityServer(); + _ = app.UseAuthorization(); - app.MapGet("/", () => "identity server"); + _ = app.MapGet("/", () => "identity server"); - app.MapGet("/account/login", async ctx => + _ = app.MapGet("/account/login", async ctx => { var props = new AuthenticationProperties(); await ctx.SignInAsync(new ClaimsPrincipal(new ClaimsIdentity( @@ -122,7 +122,7 @@ public class IdentityServerService(IOptions settings, IC "login", "name", "role")), props); }); - app.MapGet("/account/logout", async ctx => + _ = app.MapGet("/account/logout", async ctx => { // signout as if the user were prompted await ctx.SignOutAsync(); diff --git a/bff/hosts/Hosts.Bff.Performance/Services/MultiFrontendBffService.cs b/bff/hosts/Hosts.Bff.Performance/Services/MultiFrontendBffService.cs index ebc535890..44152871a 100644 --- a/bff/hosts/Hosts.Bff.Performance/Services/MultiFrontendBffService.cs +++ b/bff/hosts/Hosts.Bff.Performance/Services/MultiFrontendBffService.cs @@ -16,7 +16,7 @@ public class MultiFrontendBffService(IConfiguration config, IOptions DefaultOpenIdConfiguration.Apply(o, Settings)) + _ = bff.ConfigureOpenIdConnect(o => DefaultOpenIdConfiguration.Apply(o, Settings)) .AddFrontends(new BffFrontend(BffFrontendName.Parse("default"))) // Note, in order for this to work, we'll need to inject this as config @@ -26,7 +26,7 @@ public class MultiFrontendBffService(IConfiguration config, IOptions app.MapGet("/", (CurrentFrontendAccessor currentFrontendAccessor) => "multi - " + currentFrontendAccessor.Get().Name); } - diff --git a/bff/hosts/Hosts.IdentityServer/Extensions.cs b/bff/hosts/Hosts.IdentityServer/Extensions.cs index c5fb12df4..ff52791f7 100644 --- a/bff/hosts/Hosts.IdentityServer/Extensions.cs +++ b/bff/hosts/Hosts.IdentityServer/Extensions.cs @@ -8,7 +8,7 @@ internal static class Extensions { public static WebApplication ConfigureServices(this WebApplicationBuilder builder) { - builder.Services.AddRazorPages(); + _ = builder.Services.AddRazorPages(); var isBuilder = builder.Services.AddIdentityServer(options => { @@ -22,25 +22,25 @@ internal static class Extensions .AddTestUsers(TestUsers.Users); // in-memory, code config - isBuilder.AddInMemoryIdentityResources(Config.IdentityResources); - isBuilder.AddInMemoryApiScopes(Config.ApiScopes); - isBuilder.AddInMemoryClients(Config.Clients); - isBuilder.AddInMemoryApiResources(Config.ApiResources); - isBuilder.AddExtensionGrantValidator(); + _ = isBuilder.AddInMemoryIdentityResources(Config.IdentityResources); + _ = isBuilder.AddInMemoryApiScopes(Config.ApiScopes); + _ = isBuilder.AddInMemoryClients(Config.Clients); + _ = isBuilder.AddInMemoryApiResources(Config.ApiResources); + _ = isBuilder.AddExtensionGrantValidator(); return builder.Build(); } public static WebApplication ConfigurePipeline(this WebApplication app) { - app.UseHttpLogging(); - app.UseDeveloperExceptionPage(); - app.UseStaticFiles(); + _ = app.UseHttpLogging(); + _ = app.UseDeveloperExceptionPage(); + _ = app.UseStaticFiles(); - app.UseRouting(); - app.UseIdentityServer(); - app.UseAuthorization(); - app.MapRazorPages() + _ = app.UseRouting(); + _ = app.UseIdentityServer(); + _ = app.UseAuthorization(); + _ = app.MapRazorPages() .RequireAuthorization(); return app; diff --git a/bff/hosts/Hosts.IdentityServer/Hosts.IdentityServer.csproj b/bff/hosts/Hosts.IdentityServer/Hosts.IdentityServer.csproj index 0cdb9fde5..20c8f6294 100644 --- a/bff/hosts/Hosts.IdentityServer/Hosts.IdentityServer.csproj +++ b/bff/hosts/Hosts.IdentityServer/Hosts.IdentityServer.csproj @@ -1,17 +1,13 @@ - net10.0 - true + enable - - + - - diff --git a/bff/hosts/Hosts.IdentityServer/Pages/Device/Index.cshtml.cs b/bff/hosts/Hosts.IdentityServer/Pages/Device/Index.cshtml.cs index f4537325e..f8fdce149 100644 --- a/bff/hosts/Hosts.IdentityServer/Pages/Device/Index.cshtml.cs +++ b/bff/hosts/Hosts.IdentityServer/Pages/Device/Index.cshtml.cs @@ -123,7 +123,7 @@ public class Index : PageModel if (grantedConsent != null) { // communicate outcome of consent back to identityserver - await _interaction.HandleRequestAsync(Input.UserCode, grantedConsent); + _ = await _interaction.HandleRequestAsync(Input.UserCode, grantedConsent); // indicate that's it ok to redirect back to authorization endpoint return RedirectToPage("/Device/Success"); diff --git a/bff/hosts/Hosts.IdentityServer/Pages/ExternalLogin/Callback.cshtml.cs b/bff/hosts/Hosts.IdentityServer/Pages/ExternalLogin/Callback.cshtml.cs index 4329a5265..d4e8926cd 100644 --- a/bff/hosts/Hosts.IdentityServer/Pages/ExternalLogin/Callback.cshtml.cs +++ b/bff/hosts/Hosts.IdentityServer/Pages/ExternalLogin/Callback.cshtml.cs @@ -75,7 +75,7 @@ public class Callback : PageModel // // remove the user id claim so we don't include it as an extra claim if/when we provision the user var claims = externalUser.Claims.ToList(); - claims.Remove(userIdClaim); + _ = claims.Remove(userIdClaim); user = _users.AutoProvisionUser(provider, providerUserId, claims.ToList()); } diff --git a/bff/hosts/Hosts.ServiceDefaults/Extensions.cs b/bff/hosts/Hosts.ServiceDefaults/Extensions.cs index 4ca3dcf60..a7a1d6d55 100644 --- a/bff/hosts/Hosts.ServiceDefaults/Extensions.cs +++ b/bff/hosts/Hosts.ServiceDefaults/Extensions.cs @@ -23,25 +23,25 @@ public static class Extensions { public static TBuilder AddServiceDefaults(this TBuilder builder) where TBuilder : IHostApplicationBuilder { - builder.ConfigureOpenTelemetry(); + _ = builder.ConfigureOpenTelemetry(); - builder.AddDefaultHealthChecks(); + _ = builder.AddDefaultHealthChecks(); - builder.Services.AddHttpLogging(); + _ = builder.Services.AddHttpLogging(); - builder.Services.AddServiceDiscovery(); + _ = builder.Services.AddServiceDiscovery(); - builder.Services.ConfigureHttpClientDefaults(http => + _ = builder.Services.ConfigureHttpClientDefaults(http => { // Turn on resilience by default - http.AddStandardResilienceHandler(); + _ = http.AddStandardResilienceHandler(); // Turn on service discovery by default - http.AddServiceDiscovery(); + _ = http.AddServiceDiscovery(); }); // Uncomment the following to restrict the allowed schemes for service discovery. - builder.Services.Configure(options => + _ = builder.Services.Configure(options => { options.AllowedSchemes = ["https"]; }); @@ -51,23 +51,23 @@ public static class Extensions public static TBuilder ConfigureOpenTelemetry(this TBuilder builder) where TBuilder : IHostApplicationBuilder { - builder.Logging.AddOpenTelemetry(logging => + _ = builder.Logging.AddOpenTelemetry(logging => { logging.IncludeFormattedMessage = true; logging.IncludeScopes = true; }); - builder.Services.AddOpenTelemetry() + _ = builder.Services.AddOpenTelemetry() .WithMetrics(metrics => { - metrics.AddAspNetCoreInstrumentation() + _ = metrics.AddAspNetCoreInstrumentation() .AddHttpClientInstrumentation() .AddRuntimeInstrumentation() .AddMeter(BffMetrics.MeterName); }) .WithTracing(tracing => { - tracing.AddSource(builder.Environment.ApplicationName) + _ = tracing.AddSource(builder.Environment.ApplicationName) .AddAspNetCoreInstrumentation() .AddHttpClientInstrumentation(); }); @@ -81,7 +81,7 @@ public static class Extensions if (useOtlpExporter) { - builder.Services.AddOpenTelemetry().UseOtlpExporter(); + _ = builder.Services.AddOpenTelemetry().UseOtlpExporter(); } // Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package) @@ -97,7 +97,7 @@ public static class Extensions public static TBuilder AddDefaultHealthChecks(this TBuilder builder) where TBuilder : IHostApplicationBuilder { // Add a default liveness check to ensure app is responsive - builder.Services.AddHealthChecks() + _ = builder.Services.AddHealthChecks() .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]); return builder; @@ -110,10 +110,10 @@ public static class Extensions if (app.Environment.IsDevelopment()) { // All health checks must pass for app to be considered ready to accept traffic after starting - app.MapHealthChecks("/health"); + _ = app.MapHealthChecks("/health"); // Only health checks tagged with the "live" tag must pass for app to be considered alive - app.MapHealthChecks("/alive", new HealthCheckOptions + _ = app.MapHealthChecks("/alive", new HealthCheckOptions { Predicate = r => r.Tags.Contains("live") }); diff --git a/bff/hosts/RemoteApis/Hosts.RemoteApi.DPoP/Extensions.cs b/bff/hosts/RemoteApis/Hosts.RemoteApi.DPoP/Extensions.cs index 171e5476d..d6c88bb8d 100644 --- a/bff/hosts/RemoteApis/Hosts.RemoteApi.DPoP/Extensions.cs +++ b/bff/hosts/RemoteApis/Hosts.RemoteApi.DPoP/Extensions.cs @@ -12,9 +12,9 @@ internal static class Extensions { var services = builder.Services; - services.AddControllers(); + _ = services.AddControllers(); - services.AddAuthentication("token") + _ = services.AddAuthentication("token") .AddJwtBearer("token", options => { options.Authority = "https://localhost:5001"; @@ -31,18 +31,18 @@ internal static class Extensions }); // layers DPoP onto the "token" scheme above - services.ConfigureDPoPTokensForScheme("token"); + _ = services.ConfigureDPoPTokensForScheme("token"); - services.AddAuthorization(options => + _ = services.AddAuthorization(options => { options.AddPolicy("ApiCaller", policy => { - policy.RequireClaim("scope", "api"); + _ = policy.RequireClaim("scope", "api"); }); options.AddPolicy("RequireInteractiveUser", policy => { - policy.RequireClaim("sub"); + _ = policy.RequireClaim("sub"); }); }); return builder.Build(); @@ -64,21 +64,20 @@ internal static class Extensions // ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost, // }); - app.UseHttpLogging(); + _ = app.UseHttpLogging(); if (app.Environment.IsDevelopment()) { - app.UseDeveloperExceptionPage(); + _ = app.UseDeveloperExceptionPage(); } - app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); + _ = app.UseRouting(); + _ = app.UseAuthentication(); + _ = app.UseAuthorization(); - app.MapControllers() + _ = app.MapControllers() .RequireAuthorization("ApiCaller"); return app; } } - diff --git a/bff/hosts/RemoteApis/Hosts.RemoteApi.DPoP/Hosts.RemoteApi.DPoP.csproj b/bff/hosts/RemoteApis/Hosts.RemoteApi.DPoP/Hosts.RemoteApi.DPoP.csproj index 670e8704a..596ffe9fd 100644 --- a/bff/hosts/RemoteApis/Hosts.RemoteApi.DPoP/Hosts.RemoteApi.DPoP.csproj +++ b/bff/hosts/RemoteApis/Hosts.RemoteApi.DPoP/Hosts.RemoteApi.DPoP.csproj @@ -1,13 +1,11 @@ - net10.0 - + - diff --git a/bff/hosts/RemoteApis/Hosts.RemoteApi.DPoP/ToDoController.cs b/bff/hosts/RemoteApis/Hosts.RemoteApi.DPoP/ToDoController.cs index b4466e5f3..e06d5b1b3 100644 --- a/bff/hosts/RemoteApis/Hosts.RemoteApi.DPoP/ToDoController.cs +++ b/bff/hosts/RemoteApis/Hosts.RemoteApi.DPoP/ToDoController.cs @@ -79,7 +79,7 @@ public class ToDoController : ControllerBase return NotFound(); } - Data.Remove(item); + _ = Data.Remove(item); _logger.LogInformation("Delete {id}", id); return NoContent(); diff --git a/bff/hosts/RemoteApis/Hosts.RemoteApi.Isolated/Extensions.cs b/bff/hosts/RemoteApis/Hosts.RemoteApi.Isolated/Extensions.cs index a503d98a9..605217c74 100644 --- a/bff/hosts/RemoteApis/Hosts.RemoteApi.Isolated/Extensions.cs +++ b/bff/hosts/RemoteApis/Hosts.RemoteApi.Isolated/Extensions.cs @@ -11,9 +11,9 @@ internal static class Extensions public static WebApplication ConfigureServices(this WebApplicationBuilder builder) { var services = builder.Services; - services.AddControllers(); + _ = services.AddControllers(); - services.AddAuthentication("token") + _ = services.AddAuthentication("token") .AddJwtBearer("token", options => { options.Authority = "https://localhost:5001"; @@ -30,16 +30,16 @@ internal static class Extensions }; }); - services.AddAuthorization(options => + _ = services.AddAuthorization(options => { options.AddPolicy("ApiCaller", policy => { - policy.RequireClaim("scope", "scope-for-isolated-api"); + _ = policy.RequireClaim("scope", "scope-for-isolated-api"); }); options.AddPolicy("RequireInteractiveUser", policy => { - policy.RequireClaim("sub"); + _ = policy.RequireClaim("sub"); }); }); return builder.Build(); @@ -47,23 +47,23 @@ internal static class Extensions public static WebApplication ConfigurePipeline(this WebApplication app) { - app.UseForwardedHeaders(new ForwardedHeadersOptions + _ = app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost, }); - app.UseHttpLogging(); + _ = app.UseHttpLogging(); if (app.Environment.IsDevelopment()) { - app.UseDeveloperExceptionPage(); + _ = app.UseDeveloperExceptionPage(); } - app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); + _ = app.UseRouting(); + _ = app.UseAuthentication(); + _ = app.UseAuthorization(); - app.MapControllers() + _ = app.MapControllers() .RequireAuthorization("ApiCaller"); return app; } diff --git a/bff/hosts/RemoteApis/Hosts.RemoteApi.Isolated/ToDoController.cs b/bff/hosts/RemoteApis/Hosts.RemoteApi.Isolated/ToDoController.cs index e93a4f251..ab511475f 100644 --- a/bff/hosts/RemoteApis/Hosts.RemoteApi.Isolated/ToDoController.cs +++ b/bff/hosts/RemoteApis/Hosts.RemoteApi.Isolated/ToDoController.cs @@ -79,7 +79,7 @@ public class ToDoController : ControllerBase return NotFound(); } - Data.Remove(item); + _ = Data.Remove(item); _logger.LogInformation("Delete {id}", id); return NoContent(); diff --git a/bff/hosts/RemoteApis/Hosts.RemoteApi/Extensions.cs b/bff/hosts/RemoteApis/Hosts.RemoteApi/Extensions.cs index afb472f6f..a321c127b 100644 --- a/bff/hosts/RemoteApis/Hosts.RemoteApi/Extensions.cs +++ b/bff/hosts/RemoteApis/Hosts.RemoteApi/Extensions.cs @@ -12,9 +12,9 @@ internal static class Extensions { var services = builder.Services; - services.AddControllers(); + _ = services.AddControllers(); - services.AddAuthentication("token") + _ = services.AddAuthentication("token") .AddJwtBearer("token", options => { options.Authority = "https://localhost:5001"; @@ -30,16 +30,16 @@ internal static class Extensions }; }); - services.AddAuthorization(options => + _ = services.AddAuthorization(options => { options.AddPolicy("ApiCaller", policy => { - policy.RequireClaim("scope", "api"); + _ = policy.RequireClaim("scope", "api"); }); options.AddPolicy("RequireInteractiveUser", policy => { - policy.RequireClaim("sub"); + _ = policy.RequireClaim("sub"); }); }); @@ -48,33 +48,32 @@ internal static class Extensions public static WebApplication ConfigurePipeline(this WebApplication app) { - app.UseForwardedHeaders(new ForwardedHeadersOptions + _ = app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost, }); - app.UseHttpLogging(); + _ = app.UseHttpLogging(); if (app.Environment.IsDevelopment()) { - app.UseDeveloperExceptionPage(); + _ = app.UseDeveloperExceptionPage(); } - app.Map("/static", inner => + _ = app.Map("/static", inner => { - inner.UseDefaultFiles(); - inner.UseStaticFiles(); + _ = inner.UseDefaultFiles(); + _ = inner.UseStaticFiles(); }); - app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); + _ = app.UseRouting(); + _ = app.UseAuthentication(); + _ = app.UseAuthorization(); - app.MapControllers() + _ = app.MapControllers() .RequireAuthorization("ApiCaller"); return app; } } - diff --git a/bff/hosts/RemoteApis/Hosts.RemoteApi/ToDoController.cs b/bff/hosts/RemoteApis/Hosts.RemoteApi/ToDoController.cs index 0b6a11810..d7fa1953f 100644 --- a/bff/hosts/RemoteApis/Hosts.RemoteApi/ToDoController.cs +++ b/bff/hosts/RemoteApis/Hosts.RemoteApi/ToDoController.cs @@ -79,7 +79,7 @@ public class ToDoController : ControllerBase return NotFound(); } - Data.Remove(item); + _ = Data.Remove(item); _logger.LogInformation("Delete {id}", id); return NoContent(); diff --git a/bff/migrations/Directory.Build.props b/bff/migrations/Directory.Build.props index 7778a8249..388739594 100644 --- a/bff/migrations/Directory.Build.props +++ b/bff/migrations/Directory.Build.props @@ -1,11 +1,9 @@ - + + None $(AssemblyName) Duende.$(MSBuildProjectName) - - net10.0 - + false - - \ No newline at end of file + diff --git a/bff/migrations/UserSessionDb/Migrations/.editorconfig b/bff/migrations/UserSessionDb/Migrations/.editorconfig new file mode 100644 index 000000000..98e806338 --- /dev/null +++ b/bff/migrations/UserSessionDb/Migrations/.editorconfig @@ -0,0 +1,2 @@ +[*.cs] +dotnet_diagnostic.IDE0058.severity = none diff --git a/bff/migrations/UserSessionDb/Program.cs b/bff/migrations/UserSessionDb/Program.cs index c83aeb301..3573ce359 100644 --- a/bff/migrations/UserSessionDb/Program.cs +++ b/bff/migrations/UserSessionDb/Program.cs @@ -25,6 +25,6 @@ public class Program Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { - webBuilder.UseStartup(); + _ = webBuilder.UseStartup(); }); } diff --git a/bff/migrations/UserSessionDb/Startup.cs b/bff/migrations/UserSessionDb/Startup.cs index 067aeb757..39eac7bd5 100644 --- a/bff/migrations/UserSessionDb/Startup.cs +++ b/bff/migrations/UserSessionDb/Startup.cs @@ -16,10 +16,10 @@ public class Startup { var cn = Configuration.GetConnectionString("db"); - services.AddDbContext(options => + _ = services.AddDbContext(options => { //options.UseSqlServer(cn, dbOpts => dbOpts.MigrationsAssembly(typeof(Startup).Assembly.FullName)); - options.UseSqlite(cn, dbOpts => dbOpts.MigrationsAssembly(typeof(Startup).Assembly.FullName)); + _ = options.UseSqlite(cn, dbOpts => dbOpts.MigrationsAssembly(typeof(Startup).Assembly.FullName)); }); } diff --git a/bff/migrations/UserSessionDb/UserSessionDb.csproj b/bff/migrations/UserSessionDb/UserSessionDb.csproj index de5b67821..3744ae418 100644 --- a/bff/migrations/UserSessionDb/UserSessionDb.csproj +++ b/bff/migrations/UserSessionDb/UserSessionDb.csproj @@ -1,20 +1,16 @@ - net10.0 - all runtime; build; native; contentfiles; analyzers; buildtransitive - + - - diff --git a/bff/performance/Bff.Benchmarks/BenchmarkBase.cs b/bff/performance/Bff.Benchmarks/BenchmarkBase.cs index 66bedd94d..c898c49bf 100644 --- a/bff/performance/Bff.Benchmarks/BenchmarkBase.cs +++ b/bff/performance/Bff.Benchmarks/BenchmarkBase.cs @@ -116,10 +116,10 @@ public class BenchmarkConfig : ManualConfig sizeUnit: SizeUnit.KB )); - AddJob(Job.LongRun); - AddColumnProvider(DefaultColumnProviders.Instance); - AddExporter(exporter); - AddLogger(new ConsoleLogger()); // Add a minimal logger back if you want basic running info + _ = AddJob(Job.LongRun); + _ = AddColumnProvider(DefaultColumnProviders.Instance); + _ = AddExporter(exporter); + _ = AddLogger(new ConsoleLogger()); // Add a minimal logger back if you want basic running info } } diff --git a/bff/performance/Bff.Benchmarks/Bff.Benchmarks.csproj b/bff/performance/Bff.Benchmarks/Bff.Benchmarks.csproj index a7ddc8026..e17ae92cc 100644 --- a/bff/performance/Bff.Benchmarks/Bff.Benchmarks.csproj +++ b/bff/performance/Bff.Benchmarks/Bff.Benchmarks.csproj @@ -1,5 +1,4 @@ - - + net10.0 Exe @@ -7,24 +6,20 @@ enable false - - - - + + - - diff --git a/bff/performance/Bff.Benchmarks/Hosts/ApiHost.cs b/bff/performance/Bff.Benchmarks/Hosts/ApiHost.cs index d546df4ac..bf09a0685 100644 --- a/bff/performance/Bff.Benchmarks/Hosts/ApiHost.cs +++ b/bff/performance/Bff.Benchmarks/Hosts/ApiHost.cs @@ -12,7 +12,7 @@ public class ApiHost : Host { OnConfigureServices += services => { - services.AddAuthentication("token") + _ = services.AddAuthentication("token") .AddJwtBearer("token", options => { options.Authority = identityServerUri.ToString(); @@ -23,17 +23,17 @@ public class ApiHost : Host OnConfigure += app => { - app.Use(async (c, n) => + _ = app.Use(async (c, n) => { await n(); }); - app.UseRouting(); + _ = app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); + _ = app.UseAuthentication(); + _ = app.UseAuthorization(); - app.MapGet("{**catch-all}", () => "ok"); + _ = app.MapGet("{**catch-all}", () => "ok"); }; diff --git a/bff/performance/Bff.Benchmarks/Hosts/BffHost.cs b/bff/performance/Bff.Benchmarks/Hosts/BffHost.cs index f8322f9c6..ba7b0fbbb 100644 --- a/bff/performance/Bff.Benchmarks/Hosts/BffHost.cs +++ b/bff/performance/Bff.Benchmarks/Hosts/BffHost.cs @@ -53,27 +53,27 @@ public class BffHost : Host .AddRemoteApis(); if (!Internet.UseKestrel) { - services.AddSingleton(new SimulatedInternetYarpForwarderFactory(Internet)); + _ = services.AddSingleton(new SimulatedInternetYarpForwarderFactory(Internet)); } OnConfigureBff(bff); }; OnConfigure += app => { - app.UseRouting(); + _ = app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); + _ = app.UseAuthentication(); + _ = app.UseAuthorization(); - app.UseBff(); - app.MapGet("/", () => "bff"); - app.MapGet("/anon", () => "bff") + _ = app.UseBff(); + _ = app.MapGet("/", () => "bff"); + _ = app.MapGet("/anon", () => "bff") .AllowAnonymous(); - app.MapRemoteBffApiEndpoint("/allow_anon", apiUri); - app.MapRemoteBffApiEndpoint("/client_token", apiUri) + _ = app.MapRemoteBffApiEndpoint("/allow_anon", apiUri); + _ = app.MapRemoteBffApiEndpoint("/client_token", apiUri) .WithAccessToken(RequiredTokenType.Client); - app.MapRemoteBffApiEndpoint("/user_token", apiUri) + _ = app.MapRemoteBffApiEndpoint("/user_token", apiUri) .WithAccessToken(RequiredTokenType.User); }; } diff --git a/bff/performance/Bff.Benchmarks/Hosts/Host.cs b/bff/performance/Bff.Benchmarks/Hosts/Host.cs index 1b68601b9..d3243aedf 100644 --- a/bff/performance/Bff.Benchmarks/Hosts/Host.cs +++ b/bff/performance/Bff.Benchmarks/Hosts/Host.cs @@ -30,24 +30,24 @@ public abstract class Host : IAsyncDisposable Internet = simulatedInternet; _builder = WebApplication.CreateBuilder(); // Logs interfere with the benchmarks, so we clear them - _builder.Logging.ClearProviders(); + _ = _builder.Logging.ClearProviders(); // Ensure dev certificate is used for SSL if (Internet.UseKestrel) { - _builder.WebHost.UseUrls("https://*:0"); + _ = _builder.WebHost.UseUrls("https://*:0"); } else { - _builder.Logging.AddConsole(); - _builder.WebHost + _ = _builder.Logging.AddConsole(); + _ = _builder.WebHost .UseTestServer(); } - _builder.Services.AddAuthentication(); - _builder.Services.AddAuthorization(); - _builder.Services.AddRouting(); + _ = _builder.Services.AddAuthentication(); + _ = _builder.Services.AddAuthorization(); + _ = _builder.Services.AddRouting(); } public T GetService() where T : notnull => _app.Services.GetRequiredService(); diff --git a/bff/performance/Bff.Benchmarks/Hosts/IdentityServerHost.cs b/bff/performance/Bff.Benchmarks/Hosts/IdentityServerHost.cs index 3664b5123..3762ef77d 100644 --- a/bff/performance/Bff.Benchmarks/Hosts/IdentityServerHost.cs +++ b/bff/performance/Bff.Benchmarks/Hosts/IdentityServerHost.cs @@ -28,17 +28,17 @@ public class IdentityServerHost : Host .AddInMemoryIdentityResources(IdentityResources) .AddInMemoryApiScopes(ApiScopes); - identityServer.AddBackChannelLogoutHttpClient(); + _ = identityServer.AddBackChannelLogoutHttpClient(); }; OnConfigure += app => { - app.UseRouting(); + _ = app.UseRouting(); - app.UseIdentityServer(); - app.UseAuthorization(); + _ = app.UseIdentityServer(); + _ = app.UseAuthorization(); - app.MapGet("/account/login", async ctx => + _ = app.MapGet("/account/login", async ctx => { await ctx.SignInAsync(UserToSignIn); }); diff --git a/bff/performance/Bff.Benchmarks/Hosts/PlainYarpProxy.cs b/bff/performance/Bff.Benchmarks/Hosts/PlainYarpProxy.cs index 0672b6bf3..7d80301d1 100644 --- a/bff/performance/Bff.Benchmarks/Hosts/PlainYarpProxy.cs +++ b/bff/performance/Bff.Benchmarks/Hosts/PlainYarpProxy.cs @@ -14,8 +14,8 @@ public class PlainYarpProxy : Host { OnConfigureServices += services => { - services.AddSingleton(new SimulatedInternetYarpForwarderFactory(Internet)); - services.AddReverseProxy() + _ = services.AddSingleton(new SimulatedInternetYarpForwarderFactory(Internet)); + _ = services.AddReverseProxy() .LoadFromMemory( [ new RouteConfig() @@ -42,8 +42,8 @@ public class PlainYarpProxy : Host }; OnConfigure += app => { - app.UseRouting(); - app.MapReverseProxy(); + _ = app.UseRouting(); + _ = app.MapReverseProxy(); }; } } diff --git a/bff/performance/Bff.Benchmarks/Hosts/RoutingMessageHandler.cs b/bff/performance/Bff.Benchmarks/Hosts/RoutingMessageHandler.cs index c0222cf7c..f06ea895e 100644 --- a/bff/performance/Bff.Benchmarks/Hosts/RoutingMessageHandler.cs +++ b/bff/performance/Bff.Benchmarks/Hosts/RoutingMessageHandler.cs @@ -22,7 +22,7 @@ internal class RoutingMessageHandler : HttpMessageHandler { var endpoint = new HostHandler(handler); var host = $"{hostHeaderValue.Host}:{hostHeaderValue.Port}"; - _hosts.TryAdd(host, endpoint); + _ = _hosts.TryAdd(host, endpoint); } protected override Task SendAsync( diff --git a/bff/performance/Bff.Benchmarks/MultiFrontendBenchmarks.cs b/bff/performance/Bff.Benchmarks/MultiFrontendBenchmarks.cs index bdc45fdbf..349cdf81e 100644 --- a/bff/performance/Bff.Benchmarks/MultiFrontendBenchmarks.cs +++ b/bff/performance/Bff.Benchmarks/MultiFrontendBenchmarks.cs @@ -18,7 +18,7 @@ public class MultiFrontendBenchmarks : BenchmarkBase _authenticatedBffClient = _fixture.Internet.BuildHttpClient(_fixture.Bff.Url()); // Warm up the BFF Login - await _authenticatedBffClient.GetAsync("/bff/login") + _ = await _authenticatedBffClient.GetAsync("/bff/login") .EnsureStatusCode(); _anonBffClient = _fixture.Internet.BuildHttpClient(_fixture.Bff.Url()); @@ -28,7 +28,7 @@ public class MultiFrontendBenchmarks : BenchmarkBase public async Task MultiFrontend_login_to_default() { var client = _fixture.Internet.BuildHttpClient(_fixture.Bff.Url()); - await client.GetAsync("/bff/login") + _ = await client.GetAsync("/bff/login") .EnsureStatusCode(); } @@ -36,7 +36,7 @@ public class MultiFrontendBenchmarks : BenchmarkBase public async Task MultiFrontend_login_to_frontend_3() { var client = _fixture.Internet.BuildHttpClient(_fixture.Bff.Url()); - await client.GetAsync($"{GetPath(3)}/bff/login") + _ = await client.GetAsync($"{GetPath(3)}/bff/login") .EnsureStatusCode(); } diff --git a/bff/performance/Bff.Benchmarks/MultiFrontendWarmedUpLoginBenchmarks.cs b/bff/performance/Bff.Benchmarks/MultiFrontendWarmedUpLoginBenchmarks.cs index 157ebb9e7..e3ddc4202 100644 --- a/bff/performance/Bff.Benchmarks/MultiFrontendWarmedUpLoginBenchmarks.cs +++ b/bff/performance/Bff.Benchmarks/MultiFrontendWarmedUpLoginBenchmarks.cs @@ -25,7 +25,7 @@ public class MultiFrontendWarmedUpLoginBenchmarks : BenchmarkBase { var c = _fixture.Internet.BuildHttpClient(_fixture.Bff.Url()); var path = GetPath(i); - await c.GetAsync(path + "/bff/login") + _ = await c.GetAsync(path + "/bff/login") .EnsureStatusCode(); } @@ -39,10 +39,10 @@ public class MultiFrontendWarmedUpLoginBenchmarks : BenchmarkBase var path = GetPath(_random.Next(0, PathsToTest - 1)); - await client.GetAsync(path + "/bff/login") + _ = await client.GetAsync(path + "/bff/login") .EnsureStatusCode(); - await client.GetWithCSRF(path + "/user_token") + _ = await client.GetWithCSRF(path + "/user_token") .EnsureStatusCode(); } diff --git a/bff/performance/Bff.Benchmarks/SingleFrontendBenchmarks.cs b/bff/performance/Bff.Benchmarks/SingleFrontendBenchmarks.cs index ec74220d1..52764cbb8 100644 --- a/bff/performance/Bff.Benchmarks/SingleFrontendBenchmarks.cs +++ b/bff/performance/Bff.Benchmarks/SingleFrontendBenchmarks.cs @@ -20,14 +20,14 @@ public class SingleFrontendBenchmarks : BenchmarkBase _fixture = new SingleFrontendFixture(); _authenticatedBffClient = _fixture.Internet.BuildHttpClient(_fixture.Bff.Url()); - await _authenticatedBffClient.GetAsync("/bff/login") + _ = await _authenticatedBffClient.GetAsync("/bff/login") .EnsureStatusCode(); _anonBffClient = _fixture.Internet.BuildHttpClient(_fixture.Bff.Url()); _bffServerSideSessionsClient = _fixture.Internet.BuildHttpClient(_fixture.Bff.Url()); - await _bffServerSideSessionsClient.GetAsync("/bff/login") + _ = await _bffServerSideSessionsClient.GetAsync("/bff/login") .EnsureStatusCode(); } @@ -56,7 +56,7 @@ public class SingleFrontendBenchmarks : BenchmarkBase public async Task SingleFrontend_Login() { var client = _fixture.Internet.BuildHttpClient(_fixture.Bff.Url()); - await client.GetAsync("/bff/login") + _ = await client.GetAsync("/bff/login") .EnsureStatusCode(); } diff --git a/bff/performance/Bff.Performance/Scenarios/Bff/CallAnonymousLocalApi.cs b/bff/performance/Bff.Performance/Scenarios/Bff/CallAnonymousLocalApi.cs index 521433594..b8a270028 100644 --- a/bff/performance/Bff.Performance/Scenarios/Bff/CallAnonymousLocalApi.cs +++ b/bff/performance/Bff.Performance/Scenarios/Bff/CallAnonymousLocalApi.cs @@ -21,7 +21,7 @@ public class CallAuthorizedLocalApi(Uri baseUri) : BaseScenario(baseUri.ToString public override async Task Init(IScenarioInitContext c) { Client = TestClient.Create(baseUri); - await Client.TriggerLogin(); + _ = await Client.TriggerLogin(); } public override async Task RunScenario(IScenarioContext context) diff --git a/bff/performance/Directory.Build.props b/bff/performance/Directory.Build.props index 4ab5ab16f..ed36ab0c7 100644 --- a/bff/performance/Directory.Build.props +++ b/bff/performance/Directory.Build.props @@ -1,11 +1,17 @@ + + None false - true + + $(NoWarn);RS0026 + + $(NoWarn);RS0027 + diff --git a/bff/src/Bff.Blazor.Client/Bff.Blazor.Client.csproj b/bff/src/Bff.Blazor.Client/Bff.Blazor.Client.csproj index 2aa2adbac..47efa59f7 100644 --- a/bff/src/Bff.Blazor.Client/Bff.Blazor.Client.csproj +++ b/bff/src/Bff.Blazor.Client/Bff.Blazor.Client.csproj @@ -1,23 +1,18 @@ - net10.0 enable true Duende.BFF.Blazor.Client - - - - + + + - - - diff --git a/bff/src/Bff.Blazor.Client/Internals/BffClientAuthenticationStateProvider.cs b/bff/src/Bff.Blazor.Client/Internals/BffClientAuthenticationStateProvider.cs index 70ca9b6bc..e4584fa3e 100644 --- a/bff/src/Bff.Blazor.Client/Internals/BffClientAuthenticationStateProvider.cs +++ b/bff/src/Bff.Blazor.Client/Internals/BffClientAuthenticationStateProvider.cs @@ -30,7 +30,7 @@ internal class BffClientAuthenticationStateProvider : AuthenticationStateProvide ILogger logger) { _fetchUserService = fetchUserService; - persistentUserService.GetPersistedUser(out var user); + _ = persistentUserService.GetPersistedUser(out var user); _user = user; _timer = timeProvider.CreateTimer(TimerCallback, null, @@ -48,7 +48,7 @@ internal class BffClientAuthenticationStateProvider : AuthenticationStateProvide } finally { - _semaphore.Release(); + _ = _semaphore.Release(); } } @@ -99,7 +99,7 @@ internal class BffClientAuthenticationStateProvider : AuthenticationStateProvide } finally { - _semaphore.Release(); + _ = _semaphore.Release(); } } diff --git a/bff/src/Bff.Blazor.Client/ServiceCollectionExtensions.cs b/bff/src/Bff.Blazor.Client/ServiceCollectionExtensions.cs index b8d16b15b..5e9a0ffdf 100644 --- a/bff/src/Bff.Blazor.Client/ServiceCollectionExtensions.cs +++ b/bff/src/Bff.Blazor.Client/ServiceCollectionExtensions.cs @@ -21,10 +21,10 @@ public static class ServiceCollectionExtensions { if (configureAction != null) { - services.Configure(configureAction); + _ = services.Configure(configureAction); } - services + _ = services .AddAuthorizationCore() // Most services for wasm are singletons, because DI scope doesn't exist in wasm .AddSingleton() diff --git a/bff/src/Bff.Blazor/BffBuilderExtensions.cs b/bff/src/Bff.Blazor/BffBuilderExtensions.cs index 182f1686d..beeb7d01c 100644 --- a/bff/src/Bff.Blazor/BffBuilderExtensions.cs +++ b/bff/src/Bff.Blazor/BffBuilderExtensions.cs @@ -17,9 +17,9 @@ public static class { ArgumentNullException.ThrowIfNull(builder); - builder.Services.AddActivatedSingleton(); + _ = builder.Services.AddActivatedSingleton(); - builder.Services + _ = builder.Services .AddOpenIdConnectAccessTokenManagement() .AddBlazorServerAccessTokenManagement() .AddSingleton() @@ -28,7 +28,7 @@ public static class if (configureOptions != null) { - builder.Services.Configure(configureOptions); + _ = builder.Services.Configure(configureOptions); } return builder; diff --git a/bff/src/Bff.Blazor/BffServerAuthenticationStateProvider.cs b/bff/src/Bff.Blazor/BffServerAuthenticationStateProvider.cs index c5a22d567..9cf3e6a01 100644 --- a/bff/src/Bff.Blazor/BffServerAuthenticationStateProvider.cs +++ b/bff/src/Bff.Blazor/BffServerAuthenticationStateProvider.cs @@ -68,7 +68,7 @@ internal sealed class BffServerAuthenticationStateProvider : RevalidatingServerA AuthenticationStateChanged += OnAuthenticationStateChanged; _subscription = _state.RegisterOnPersisting(OnPersistingAsync, RenderMode.InteractiveWebAssembly); - licenseValidator.CheckLicense(); + _ = licenseValidator.CheckLicense(); } private void OnAuthenticationStateChanged(Task task) => _authenticationStateTask = task; diff --git a/bff/src/Bff.EntityFramework/BffBuilderExtensions.cs b/bff/src/Bff.EntityFramework/BffBuilderExtensions.cs index 11cf57a4a..17bf28b5c 100644 --- a/bff/src/Bff.EntityFramework/BffBuilderExtensions.cs +++ b/bff/src/Bff.EntityFramework/BffBuilderExtensions.cs @@ -46,7 +46,7 @@ public static class BffBuilderExtensions where T : IBffServicesBuilder { ArgumentNullException.ThrowIfNull(bffBuilder); - bffBuilder.Services.AddDbContext(action); + _ = bffBuilder.Services.AddDbContext(action); return bffBuilder.AddEntityFrameworkServerSideSessionsServices(); } @@ -61,7 +61,7 @@ public static class BffBuilderExtensions where T : IBffServicesBuilder { ArgumentNullException.ThrowIfNull(bffBuilder); - bffBuilder.Services.AddDbContext(action); + _ = bffBuilder.Services.AddDbContext(action); return bffBuilder.AddEntityFrameworkServerSideSessionsServices(); } @@ -76,9 +76,9 @@ public static class BffBuilderExtensions where T : IBffServicesBuilder { ArgumentNullException.ThrowIfNull(bffBuilder); - bffBuilder.Services.AddTransient(); - bffBuilder.Services.AddTransient(svcs => svcs.GetRequiredService()); - bffBuilder.AddServerSideSessions(); + _ = bffBuilder.Services.AddTransient(); + _ = bffBuilder.Services.AddTransient(svcs => svcs.GetRequiredService()); + _ = bffBuilder.AddServerSideSessions(); return bffBuilder; } @@ -90,7 +90,7 @@ public static class BffBuilderExtensions where T : IBffServicesBuilder { ArgumentNullException.ThrowIfNull(bffBuilder); - bffBuilder.Services.Configure(action); + _ = bffBuilder.Services.Configure(action); return bffBuilder; } @@ -98,8 +98,8 @@ public static class BffBuilderExtensions where T : IBffServicesBuilder { ArgumentNullException.ThrowIfNull(bffBuilder); - bffBuilder.Services.AddSingleton(); - bffBuilder.Services.AddSingleton(sp => sp.GetRequiredService()); + _ = bffBuilder.Services.AddSingleton(); + _ = bffBuilder.Services.AddSingleton(sp => sp.GetRequiredService()); return bffBuilder; } diff --git a/bff/src/Bff.EntityFramework/Internal/UserSessionStore.cs b/bff/src/Bff.EntityFramework/Internal/UserSessionStore.cs index 831e00983..38531248a 100644 --- a/bff/src/Bff.EntityFramework/Internal/UserSessionStore.cs +++ b/bff/src/Bff.EntityFramework/Internal/UserSessionStore.cs @@ -34,11 +34,11 @@ internal sealed class UserSessionStore( var item = new UserSessionEntity(); session.CopyTo(item); - sessionDbContext.UserSessions.Add(item); + _ = sessionDbContext.UserSessions.Add(item); try { - await sessionDbContext.SaveChangesAsync(ct); + _ = await sessionDbContext.SaveChangesAsync(ct); } catch (DbUpdateException ex) { @@ -84,10 +84,10 @@ internal sealed class UserSessionStore( logger.DeletingUserSession(LogLevel.Debug, item.SubjectId, item.SessionId); - sessionDbContext.UserSessions.Remove(item); + _ = sessionDbContext.UserSessions.Remove(item); try { - await sessionDbContext.SaveChangesAsync(ct); + _ = await sessionDbContext.SaveChangesAsync(ct); } catch (DbUpdateConcurrencyException ex) { @@ -135,7 +135,7 @@ internal sealed class UserSessionStore( try { - await sessionDbContext.SaveChangesAsync(ct); + _ = await sessionDbContext.SaveChangesAsync(ct); } catch (DbUpdateConcurrencyException ex) { @@ -231,7 +231,7 @@ internal sealed class UserSessionStore( logger.UpdatingUserSession(LogLevel.Debug, item.SubjectId, item.SessionId); session.CopyTo(item); - await sessionDbContext.SaveChangesAsync(ct); + _ = await sessionDbContext.SaveChangesAsync(ct); } /// @@ -263,7 +263,7 @@ internal sealed class UserSessionStore( removed += found; try { - await sessionDbContext.SaveChangesAsync(ct); + _ = await sessionDbContext.SaveChangesAsync(ct); } catch (DbUpdateConcurrencyException ex) { diff --git a/bff/src/Bff.EntityFramework/ModelBuilderExtensions.cs b/bff/src/Bff.EntityFramework/ModelBuilderExtensions.cs index e7e98f5e2..78b2f45fb 100644 --- a/bff/src/Bff.EntityFramework/ModelBuilderExtensions.cs +++ b/bff/src/Bff.EntityFramework/ModelBuilderExtensions.cs @@ -30,24 +30,24 @@ public static class ModelBuilderExtensions ArgumentNullException.ThrowIfNull(storeOptions); if (!string.IsNullOrWhiteSpace(storeOptions.DefaultSchema)) { - modelBuilder.HasDefaultSchema(storeOptions.DefaultSchema); + _ = modelBuilder.HasDefaultSchema(storeOptions.DefaultSchema); } - modelBuilder.Entity(entity => + _ = modelBuilder.Entity(entity => { - entity.ToTable(storeOptions.UserSessions); + _ = entity.ToTable(storeOptions.UserSessions); - entity.HasKey(x => x.Id); + _ = entity.HasKey(x => x.Id); - entity.Property(x => x.PartitionKey).HasConversion().HasMaxLength(200); - entity.Property(x => x.Key).HasConversion().IsRequired().HasMaxLength(200); - entity.Property(x => x.SubjectId).IsRequired().HasMaxLength(200); - entity.Property(x => x.Ticket).IsRequired(); + _ = entity.Property(x => x.PartitionKey).HasConversion().HasMaxLength(200); + _ = entity.Property(x => x.Key).HasConversion().IsRequired().HasMaxLength(200); + _ = entity.Property(x => x.SubjectId).IsRequired().HasMaxLength(200); + _ = entity.Property(x => x.Ticket).IsRequired(); - entity.HasIndex(x => new { ApplicationName = x.PartitionKey, x.Key }).IsUnique(); - entity.HasIndex(x => new { ApplicationName = x.PartitionKey, x.SubjectId, x.SessionId }).IsUnique(); - entity.HasIndex(x => new { ApplicationName = x.PartitionKey, x.SessionId }).IsUnique(); - entity.HasIndex(x => x.Expires); + _ = entity.HasIndex(x => new { ApplicationName = x.PartitionKey, x.Key }).IsUnique(); + _ = entity.HasIndex(x => new { ApplicationName = x.PartitionKey, x.SubjectId, x.SessionId }).IsUnique(); + _ = entity.HasIndex(x => new { ApplicationName = x.PartitionKey, x.SessionId }).IsUnique(); + _ = entity.HasIndex(x => x.Expires); }); } diff --git a/bff/src/Bff.Yarp/BffBuilderExtensions.cs b/bff/src/Bff.Yarp/BffBuilderExtensions.cs index 4df8b65f3..a2980d65b 100644 --- a/bff/src/Bff.Yarp/BffBuilderExtensions.cs +++ b/bff/src/Bff.Yarp/BffBuilderExtensions.cs @@ -38,21 +38,21 @@ public static class BffBuilderExtensions // As a workaround, we're registering the config as a singleton // then loading the singleton when the config reloads. - services.AddKeyedSingleton(ServiceProviderKeys.ProxyConfigurationKey, config); + _ = services.AddKeyedSingleton(ServiceProviderKeys.ProxyConfigurationKey, config); }); - builder.Services.Configure(opt => + _ = builder.Services.Configure(opt => { opt.MiddlewareLoaders.Add(app => { - app.UseBffRemoteRoutes(); + _ = app.UseBffRemoteRoutes(); }); }); - builder.Services.AddHttpForwarder(); - builder.Services.AddSingleton(); + _ = builder.Services.AddHttpForwarder(); + _ = builder.Services.AddSingleton(); - builder.Services.AddSingleton(); + _ = builder.Services.AddSingleton(); return builder; } @@ -65,7 +65,7 @@ public static class BffBuilderExtensions var yarpBuilder = builder.Services.AddReverseProxy() .AddBffExtensions(); - yarpBuilder.LoadFromMemory(routes, clusters); + _ = yarpBuilder.LoadFromMemory(routes, clusters); return yarpBuilder; } @@ -77,7 +77,7 @@ public static class BffBuilderExtensions var yarpBuilder = builder.Services.AddReverseProxy() .AddBffExtensions(); - yarpBuilder.LoadFromConfig(config); + _ = yarpBuilder.LoadFromConfig(config); return yarpBuilder; } diff --git a/bff/src/Bff.Yarp/DefaultBffYarpTransformerBuilders.cs b/bff/src/Bff.Yarp/DefaultBffYarpTransformerBuilders.cs index 4aa56b7ce..dccfcebbd 100644 --- a/bff/src/Bff.Yarp/DefaultBffYarpTransformerBuilders.cs +++ b/bff/src/Bff.Yarp/DefaultBffYarpTransformerBuilders.cs @@ -18,8 +18,8 @@ public static class DefaultBffYarpTransformerBuilders public static readonly BffYarpTransformBuilder DirectProxyWithAccessToken = (pathMatch, context) => { - context.AddRequestHeaderRemove("Cookie"); - context.AddPathRemovePrefix(pathMatch); - context.AddBffAccessToken(pathMatch); + _ = context.AddRequestHeaderRemove("Cookie"); + _ = context.AddPathRemovePrefix(pathMatch); + _ = context.AddBffAccessToken(pathMatch); }; } diff --git a/bff/src/Bff.Yarp/Internal/AccessTokenRequestTransform.cs b/bff/src/Bff.Yarp/Internal/AccessTokenRequestTransform.cs index 64c5fd719..42af12e44 100644 --- a/bff/src/Bff.Yarp/Internal/AccessTokenRequestTransform.cs +++ b/bff/src/Bff.Yarp/Internal/AccessTokenRequestTransform.cs @@ -171,7 +171,7 @@ internal class AccessTokenRequestTransform( }); if (proofToken != null) { - context.ProxyRequest.Headers.Remove(OidcConstants.HttpHeaders.DPoP); + _ = context.ProxyRequest.Headers.Remove(OidcConstants.HttpHeaders.DPoP); context.ProxyRequest.Headers.Add(OidcConstants.HttpHeaders.DPoP, proofToken.Value); context.ProxyRequest.Headers.Authorization = new AuthenticationHeaderValue(OidcConstants.AuthenticationSchemes.AuthorizationHeaderDPoP, token.AccessToken); diff --git a/bff/src/Bff.Yarp/Internal/AccessTokenTransformProvider.cs b/bff/src/Bff.Yarp/Internal/AccessTokenTransformProvider.cs index f51fa74ba..9afd2ce87 100644 --- a/bff/src/Bff.Yarp/Internal/AccessTokenTransformProvider.cs +++ b/bff/src/Bff.Yarp/Internal/AccessTokenTransformProvider.cs @@ -45,12 +45,12 @@ internal class AccessTokenTransformProvider(IOptions options, ILogge var values = new HashSet(); if (!string.IsNullOrEmpty(routeValue)) { - values.Add(routeValue); + _ = values.Add(routeValue); } if (!string.IsNullOrEmpty(clusterValue)) { - values.Add(clusterValue); + _ = values.Add(clusterValue); } if (values.Count > 1) @@ -78,7 +78,7 @@ internal class AccessTokenTransformProvider(IOptions options, ILogge return; } - transformBuildContext.AddRequestTransform(async transformContext => + _ = transformBuildContext.AddRequestTransform(async transformContext => { transformContext.HttpContext.CheckForBffMiddleware(_options); diff --git a/bff/src/Bff.Yarp/Internal/RemoteRouteHandler.cs b/bff/src/Bff.Yarp/Internal/RemoteRouteHandler.cs index d8f6ab937..b70bae3f1 100644 --- a/bff/src/Bff.Yarp/Internal/RemoteRouteHandler.cs +++ b/bff/src/Bff.Yarp/Internal/RemoteRouteHandler.cs @@ -103,7 +103,7 @@ internal class RemoteRouteHandler : IDisposable var destinationPrefix = remoteApi.TargetUri.ToString(); - await _httpForwarder.SendAsync(context, destinationPrefix, _invoker, requestConfig, + _ = await _httpForwarder.SendAsync(context, destinationPrefix, _invoker, requestConfig, httpTransformer, ct); return true; diff --git a/bff/src/Bff.Yarp/ProxyConfigExtensions.cs b/bff/src/Bff.Yarp/ProxyConfigExtensions.cs index b05c89714..6c09d68b8 100644 --- a/bff/src/Bff.Yarp/ProxyConfigExtensions.cs +++ b/bff/src/Bff.Yarp/ProxyConfigExtensions.cs @@ -63,7 +63,7 @@ public static class ProxyConfigExtensions metadata = new(); } - metadata.TryAdd(key, value); + _ = metadata.TryAdd(key, value); return config with { Metadata = metadata }; } @@ -89,7 +89,7 @@ public static class ProxyConfigExtensions metadata = new(); } - metadata.TryAdd(Constants.Yarp.TokenTypeMetadata, requiredTokenType.ToString()); + _ = metadata.TryAdd(Constants.Yarp.TokenTypeMetadata, requiredTokenType.ToString()); return config with { Metadata = metadata }; } diff --git a/bff/src/Bff.Yarp/ReverseProxyBuilderExtensions.cs b/bff/src/Bff.Yarp/ReverseProxyBuilderExtensions.cs index 2a8d598d4..92c804268 100644 --- a/bff/src/Bff.Yarp/ReverseProxyBuilderExtensions.cs +++ b/bff/src/Bff.Yarp/ReverseProxyBuilderExtensions.cs @@ -18,7 +18,7 @@ public static class ReverseProxyBuilderExtensions /// public static IReverseProxyBuilder AddBffExtensions(this IReverseProxyBuilder builder) { - builder.AddTransforms(); + _ = builder.AddTransforms(); return builder; } diff --git a/bff/src/Bff/AccessTokenManagement/DPoPProofKey.cs b/bff/src/Bff/AccessTokenManagement/DPoPProofKey.cs index 02d23f342..f7dcabc7a 100644 --- a/bff/src/Bff/AccessTokenManagement/DPoPProofKey.cs +++ b/bff/src/Bff/AccessTokenManagement/DPoPProofKey.cs @@ -50,7 +50,7 @@ public readonly record struct DPoPProofKey : IStronglyTypedValue message = string.Empty; try { - JsonWebKey.Create(value); + _ = JsonWebKey.Create(value); return true; } catch (JsonException e) diff --git a/bff/src/Bff/Bff.csproj b/bff/src/Bff/Bff.csproj index 2681315d9..12a73d7c0 100644 --- a/bff/src/Bff/Bff.csproj +++ b/bff/src/Bff/Bff.csproj @@ -4,9 +4,6 @@ net10.0 Duende.BFF Backend for frontend (BFF) host for ASP.NET Core - - - diff --git a/bff/src/Bff/BffApplicationBuilderExtensions.cs b/bff/src/Bff/BffApplicationBuilderExtensions.cs index 8733bebcb..ffa47eea0 100644 --- a/bff/src/Bff/BffApplicationBuilderExtensions.cs +++ b/bff/src/Bff/BffApplicationBuilderExtensions.cs @@ -49,9 +49,9 @@ public static class BffApplicationBuilderExtensions public static IApplicationBuilder UseBffPreProcessing(this IApplicationBuilder app) { ArgumentNullException.ThrowIfNull(app); - app.UseBffFrontendSelection(); - app.UseBffPathMapping(); - app.UseBffOpenIdCallbacks(); + _ = app.UseBffFrontendSelection(); + _ = app.UseBffPathMapping(); + _ = app.UseBffOpenIdCallbacks(); return app; } @@ -72,7 +72,7 @@ public static class BffApplicationBuilderExtensions { loader(app); } - app.UseEndpoints(endpoints => + _ = app.UseEndpoints(endpoints => { // Mapping the management endpoints. endpoints.MapBffManagementLoginEndpoint(); @@ -84,7 +84,7 @@ public static class BffApplicationBuilderExtensions endpoints.MapBffManagementBackchannelEndpoint(); endpoints.MapBffDiagnosticsEndpoint(); }); - app.UseBffStaticFileProxying(); + _ = app.UseBffStaticFileProxying(); return app; } diff --git a/bff/src/Bff/BffBuilderExtensions.cs b/bff/src/Bff/BffBuilderExtensions.cs index b9a33621f..9a8564c98 100644 --- a/bff/src/Bff/BffBuilderExtensions.cs +++ b/bff/src/Bff/BffBuilderExtensions.cs @@ -34,103 +34,103 @@ public static class BffBuilderExtensions public static T ConfigureOpenIdConnect(this T builder, Action oidc) where T : IBffBuilder { - builder.Services.Configure(bffOptions => bffOptions.ConfigureOpenIdConnectDefaults += oidc); + _ = builder.Services.Configure(bffOptions => bffOptions.ConfigureOpenIdConnectDefaults += oidc); return builder; } public static T ConfigureCookies(this T builder, Action oidc) where T : IBffBuilder { - builder.Services.Configure(bffOptions => bffOptions.ConfigureCookieDefaults += oidc); + _ = builder.Services.Configure(bffOptions => bffOptions.ConfigureCookieDefaults += oidc); return builder; } internal static T AddBaseBffServices(this T builder) where T : IBffServicesBuilder { - builder.Services.AddSingleton(sp => + _ = builder.Services.AddSingleton(sp => () => sp.GetRequiredService>().Value.LicenseKey); - builder.Services.AddSingleton(sp => + _ = builder.Services.AddSingleton(sp => { var accessor = sp.GetRequiredService(); return accessor.Current; }); - builder.Services.AddSingleton(); + _ = builder.Services.AddSingleton(); builder.Services.TryAddSingleton(); - builder.Services.AddDistributedMemoryCache(); + _ = builder.Services.AddDistributedMemoryCache(); // IMPORTANT: The BffConfigureOpenIdConnectOptions MUST be called before calling // AddOpenIdConnectAccessTokenManagement because both configure the same options // The AddOpenIdConnectAccessTokenManagement adds OR wraps the BackchannelHttpHandler // to add DPoP support. However, our code can also add a backchannel handler. - builder.Services.AddSingleton, BffConfigureOpenIdConnectOptions>(); - builder.Services.AddOpenIdConnectAccessTokenManagement(); + _ = builder.Services.AddSingleton, BffConfigureOpenIdConnectOptions>(); + _ = builder.Services.AddOpenIdConnectAccessTokenManagement(); - builder.Services + _ = builder.Services .AddSingleton, ConfigureUserTokenManagementOptions>(); - builder.Services.AddTransient(); + _ = builder.Services.AddTransient(); builder.Services.TryAddSingleton(); // management endpoints - builder.Services.AddTransient(); + _ = builder.Services.AddTransient(); #pragma warning disable CS0618 // Type or member is obsolete - builder.Services.AddTransient(); + _ = builder.Services.AddTransient(); #pragma warning restore CS0618 // Type or member is obsolete - builder.Services.AddTransient(); - builder.Services.AddTransient(); - builder.Services.AddTransient(); - builder.Services.AddTransient(); - builder.Services.AddTransient(); + _ = builder.Services.AddTransient(); + _ = builder.Services.AddTransient(); + _ = builder.Services.AddTransient(); + _ = builder.Services.AddTransient(); + _ = builder.Services.AddTransient(); // session management builder.Services.TryAddTransient(); // cookie configuration - builder.Services + _ = builder.Services .AddSingleton, PostConfigureSlidingExpirationCheck>(); - builder.Services + _ = builder.Services .AddSingleton, PostConfigureApplicationCookieRevokeRefreshToken>(); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); + _ = builder.Services.AddSingleton(); + _ = builder.Services.AddSingleton(); - builder.Services + _ = builder.Services .AddSingleton, PostConfigureOidcOptionsForSilentLogin>(); - builder.Services.AddSingleton(); - builder.Services + _ = builder.Services.AddSingleton(); + _ = builder.Services .AddSingleton, PostConfigureApplicationCookieTrialModeCheck>(); AddBffMetrics(builder); // wrap ASP.NET Core - builder.Services.AddAuthentication(); + _ = builder.Services.AddAuthentication(); builder.Services.AddTransientDecorator(); // Make sure the session partitioning is registered. There are a few codepaths that require this injected // even if you are not using session management. - builder.Services.AddSingleton(sp => + _ = builder.Services.AddSingleton(sp => sp.GetRequiredService().BuildPartitionKey); - builder.Services.AddSingleton(); + _ = builder.Services.AddSingleton(); return builder; } internal static void AddBffMetrics(T builder) where T : IBffBuilder => - builder.Services.AddSingleton(); + _ = builder.Services.AddSingleton(); internal static T AddDiagnostics(this T builder) where T : IBffServicesBuilder { - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(serviceProvider => new DiagnosticDataService( + _ = builder.Services.AddSingleton(); + _ = builder.Services.AddSingleton(); + _ = builder.Services.AddSingleton(); + _ = builder.Services.AddSingleton(); + _ = builder.Services.AddSingleton(serviceProvider => new DiagnosticDataService( serviceProvider.GetRequiredService().GetUtcNow().UtcDateTime, serviceProvider.GetServices())); - builder.Services.AddHostedService(); + _ = builder.Services.AddHostedService(); return builder; } @@ -138,31 +138,31 @@ public static class BffBuilderExtensions internal static T AddDynamicFrontends(this T builder) where T : IBffServicesBuilder { - builder.Services.AddHybridCache(); + _ = builder.Services.AddHybridCache(); - builder.Services.AddHostedService(); + _ = builder.Services.AddHostedService(); - builder.Services.AddTransient(); + _ = builder.Services.AddTransient(); // Register the frontend collection, which will be used to store and retrieve frontends - builder.Services.AddSingleton(); + _ = builder.Services.AddSingleton(); // Add a public accessible interface to the frontend collection, so our users can access it - builder.Services.AddSingleton((sp) => sp.GetRequiredService()); + _ = builder.Services.AddSingleton((sp) => sp.GetRequiredService()); - builder.Services.AddTransient(); - builder.Services.AddSingleton(); + _ = builder.Services.AddTransient(); + _ = builder.Services.AddSingleton(); // Add a scheme provider that will inject authentication schemes that are needed for the BFF - builder.Services.AddTransient(); + _ = builder.Services.AddTransient(); // Configure the AspNet Core Authentication settings if no // .AddAuthentication().AddCookie().AddOpenIdConnect() was added - builder.Services + _ = builder.Services .AddSingleton, BffConfigureAuthenticationOptions>(); - builder.Services.AddSingleton, BffConfigureCookieOptions>(); + _ = builder.Services.AddSingleton, BffConfigureCookieOptions>(); - builder.Services.AddHttpContextAccessor(); + _ = builder.Services.AddHttpContextAccessor(); // Add 'default' configure methods that would have been added by // .AddAuthentication().AddCookie().AddOpenIdConnect() @@ -186,7 +186,7 @@ public static class BffBuilderExtensions { var indexHtmlClientBuilder = services.AddHttpClient(Constants.HttpClientNames.StaticAssetsClientName); - services.Configure(indexHtmlClientBuilder.Name, options => + _ = services.Configure(indexHtmlClientBuilder.Name, options => { options.HttpMessageHandlerBuilderActions.Add(httpMessageHandlerBuilder => { @@ -215,16 +215,16 @@ public static class BffBuilderExtensions internal static void AddServerSideSessionsSupportingServices(this IServiceCollection services) { - services.AddSingleton(sp => + _ = services.AddSingleton(sp => sp.GetRequiredService().BuildPartitionKey); - services.AddSingleton(); + _ = services.AddSingleton(); - services.AddSingleton(); - services + _ = services.AddSingleton(); + _ = services .AddSingleton, PostConfigureApplicationCookieTicketStore>(); - services.AddTransient(); - services.AddTransient(); + _ = services.AddTransient(); + _ = services.AddTransient(); // only add if not already in DI } @@ -237,8 +237,8 @@ public static class BffBuilderExtensions where T : class, IUserSessionStore { ArgumentNullException.ThrowIfNull(builder); - builder.Services.AddTransient(); - builder.AddServerSideSessions(); + _ = builder.Services.AddTransient(); + _ = builder.AddServerSideSessions(); return builder; } diff --git a/bff/src/Bff/BffEndpointRouteBuilderExtensions.cs b/bff/src/Bff/BffEndpointRouteBuilderExtensions.cs index feab6dd34..c734962ea 100644 --- a/bff/src/Bff/BffEndpointRouteBuilderExtensions.cs +++ b/bff/src/Bff/BffEndpointRouteBuilderExtensions.cs @@ -71,7 +71,7 @@ public static class BffEndpointRouteBuilderExtensions return; } - endpoints.Map(options.LoginPath.Value!, ProcessWith) + _ = endpoints.Map(options.LoginPath.Value!, ProcessWith) .WithMetadata(new BffUiEndpointAttribute()) .AllowAnonymous(); } @@ -91,7 +91,7 @@ public static class BffEndpointRouteBuilderExtensions if (!endpoints.AlreadyMappedManagementEndpoint(options.SilentLoginPath)) { - endpoints.MapGet(options.SilentLoginPath.Value!, ProcessWith) + _ = endpoints.MapGet(options.SilentLoginPath.Value!, ProcessWith) .WithName("SilentLogin") .WithMetadata(new BffUiEndpointAttribute()) .AllowAnonymous(); @@ -99,7 +99,7 @@ public static class BffEndpointRouteBuilderExtensions if (!endpoints.AlreadyMappedManagementEndpoint(options.SilentLoginCallbackPath)) { - endpoints.MapGet(options.SilentLoginCallbackPath.Value!, ProcessWith) + _ = endpoints.MapGet(options.SilentLoginCallbackPath.Value!, ProcessWith) .WithMetadata(new BffUiEndpointAttribute()) .AllowAnonymous(); } @@ -121,7 +121,7 @@ public static class BffEndpointRouteBuilderExtensions return; } - endpoints.MapGet(options.LogoutPath.Value!, ProcessWith) + _ = endpoints.MapGet(options.LogoutPath.Value!, ProcessWith) .WithName("Logout") .WithMetadata(new BffUiEndpointAttribute()) .AllowAnonymous(); @@ -143,7 +143,7 @@ public static class BffEndpointRouteBuilderExtensions return; } - endpoints.MapGet(options.UserPath.Value!, ProcessWith) + _ = endpoints.MapGet(options.UserPath.Value!, ProcessWith) .AllowAnonymous() .AsBffApiEndpoint(); } @@ -164,7 +164,7 @@ public static class BffEndpointRouteBuilderExtensions return; } - endpoints.MapPost(options.BackChannelLogoutPath.Value!, ProcessWith) + _ = endpoints.MapPost(options.BackChannelLogoutPath.Value!, ProcessWith) .AllowAnonymous(); } @@ -184,7 +184,7 @@ public static class BffEndpointRouteBuilderExtensions return; } - endpoints.MapGet(options.DiagnosticsPath.Value!, ProcessWith) + _ = endpoints.MapGet(options.DiagnosticsPath.Value!, ProcessWith) .AllowAnonymous(); } @@ -201,6 +201,6 @@ public static class BffEndpointRouteBuilderExtensions internal static void CheckLicense(this IServiceProvider serviceProvider) { var license = serviceProvider.GetRequiredService(); - license.CheckLicense(); + _ = license.CheckLicense(); } } diff --git a/bff/src/Bff/DynamicFrontends/CurrentFrontendAccessor.cs b/bff/src/Bff/DynamicFrontends/CurrentFrontendAccessor.cs index e8005c37a..297679dde 100644 --- a/bff/src/Bff/DynamicFrontends/CurrentFrontendAccessor.cs +++ b/bff/src/Bff/DynamicFrontends/CurrentFrontendAccessor.cs @@ -16,7 +16,7 @@ public sealed class CurrentFrontendAccessor(IHttpContextAccessor contextAccessor public bool TryGet([NotNullWhen(true)] out BffFrontend? frontend) { - Context.Items.TryGetValue(HttpItemName, out var value); + _ = Context.Items.TryGetValue(HttpItemName, out var value); frontend = value as BffFrontend; return frontend != null; } diff --git a/bff/src/Bff/DynamicFrontends/Internal/BffAuthenticationSchemeProvider.cs b/bff/src/Bff/DynamicFrontends/Internal/BffAuthenticationSchemeProvider.cs index 352179151..f6ce08fab 100644 --- a/bff/src/Bff/DynamicFrontends/Internal/BffAuthenticationSchemeProvider.cs +++ b/bff/src/Bff/DynamicFrontends/Internal/BffAuthenticationSchemeProvider.cs @@ -45,7 +45,7 @@ internal class BffAuthenticationSchemeProvider( BffFrontend? frontend = null; if (httpContextAccessor.HttpContext != null) { - currentFrontendAccessor.TryGet(out frontend); + _ = currentFrontendAccessor.TryGet(out frontend); } if (name == frontend?.CookieSchemeName || name == BffAuthenticationSchemes.BffCookie) diff --git a/bff/src/Bff/DynamicFrontends/Internal/BffCacheClearingHostedService.cs b/bff/src/Bff/DynamicFrontends/Internal/BffCacheClearingHostedService.cs index bac8ecae1..ee59eccbe 100644 --- a/bff/src/Bff/DynamicFrontends/Internal/BffCacheClearingHostedService.cs +++ b/bff/src/Bff/DynamicFrontends/Internal/BffCacheClearingHostedService.cs @@ -38,12 +38,12 @@ internal class BffCacheClearingHostedService( // When the frontend changes, we need to clear the cached options // This makes sure the (potentially) new OpenID Connect configuration // and cookie config is loaded - cookieOptionsMonitor.TryRemove(changedFrontend.CookieSchemeName); - oidcOptionsMonitor.TryRemove(changedFrontend.OidcSchemeName); + _ = cookieOptionsMonitor.TryRemove(changedFrontend.CookieSchemeName); + _ = oidcOptionsMonitor.TryRemove(changedFrontend.OidcSchemeName); // Duende.AccessTokenManagement also stores options. It's stored under the client name. var clientCredentialsClientName = OpenIdConnectTokenManagementDefaults.ToClientName(changedFrontend.OidcSchemeName); - clientCredentialsCache.TryRemove(clientCredentialsClientName); + _ = clientCredentialsCache.TryRemove(clientCredentialsClientName); if (!Writer.TryWrite(changedFrontend)) { diff --git a/bff/src/Bff/DynamicFrontends/Internal/BffIndex.cs b/bff/src/Bff/DynamicFrontends/Internal/BffIndex.cs index 9470a477f..16753ed9b 100644 --- a/bff/src/Bff/DynamicFrontends/Internal/BffIndex.cs +++ b/bff/src/Bff/DynamicFrontends/Internal/BffIndex.cs @@ -55,7 +55,7 @@ internal class BffIndex if (!_registeredCriteria.TryAdd(frontendMatchingCriteria, frontend.Name)) { - _registeredCriteria.TryGetValue(frontendMatchingCriteria, out var collidesWith); + _ = _registeredCriteria.TryGetValue(frontendMatchingCriteria, out var collidesWith); _logger.FrontendWithSimilarMatchingCriteriaAlreadyRegistered(LogLevel.Warning, frontend.Name, collidesWith diff --git a/bff/src/Bff/DynamicFrontends/Internal/ConfigureBffStartupFilter.cs b/bff/src/Bff/DynamicFrontends/Internal/ConfigureBffStartupFilter.cs index a16b90fd8..9ead8ee67 100644 --- a/bff/src/Bff/DynamicFrontends/Internal/ConfigureBffStartupFilter.cs +++ b/bff/src/Bff/DynamicFrontends/Internal/ConfigureBffStartupFilter.cs @@ -19,15 +19,15 @@ internal class ConfigureBffStartupFilter : IStartupFilter if (bffOptions.AutomaticallyRegisterBffMiddleware) { - app.UseForwardedHeaders(); - app.UseBffPreProcessing(); + _ = app.UseForwardedHeaders(); + _ = app.UseBffPreProcessing(); } next(app); if (bffOptions.AutomaticallyRegisterBffMiddleware) { - app.UseBffPostProcessing(); + _ = app.UseBffPostProcessing(); } }; diff --git a/bff/src/Bff/DynamicFrontends/Internal/FrontendCollection.cs b/bff/src/Bff/DynamicFrontends/Internal/FrontendCollection.cs index abc43cd46..0aea57fb9 100644 --- a/bff/src/Bff/DynamicFrontends/Internal/FrontendCollection.cs +++ b/bff/src/Bff/DynamicFrontends/Internal/FrontendCollection.cs @@ -61,7 +61,7 @@ internal class FrontendCollection : IDisposable, IFrontendCollection .Where(frontend => oldFrontends.All(x => x.Name != frontend.Name)) .ToArray(); - Interlocked.Exchange(ref _frontends, newFrontends); + _ = Interlocked.Exchange(ref _frontends, newFrontends); } @@ -169,7 +169,7 @@ internal class FrontendCollection : IDisposable, IFrontendCollection } // By replacing the array, we avoid locking the entire list for read operations. - Interlocked.Exchange(ref _frontends, _frontends + _ = Interlocked.Exchange(ref _frontends, _frontends .Where(x => x.Name != frontend.Name) .Append(frontend) .ToArray()); @@ -199,7 +199,7 @@ internal class FrontendCollection : IDisposable, IFrontendCollection } // By replacing the array, we avoid locking the entire list for read operations. - Interlocked.Exchange(ref _frontends, _frontends + _ = Interlocked.Exchange(ref _frontends, _frontends .Where(x => x.Name != frontendName) .ToArray()); } diff --git a/bff/src/Bff/DynamicFrontends/Internal/OpenIdConnectCallbackMiddleware.cs b/bff/src/Bff/DynamicFrontends/Internal/OpenIdConnectCallbackMiddleware.cs index 0045613bb..ece6516a6 100644 --- a/bff/src/Bff/DynamicFrontends/Internal/OpenIdConnectCallbackMiddleware.cs +++ b/bff/src/Bff/DynamicFrontends/Internal/OpenIdConnectCallbackMiddleware.cs @@ -64,7 +64,7 @@ internal class OpenIdConnectCallbackMiddleware( var handlers = context.RequestServices.GetRequiredService(); if (await handlers.GetHandlerAsync(context, scheme) is IAuthenticationRequestHandler handler) { - await handler.HandleRequestAsync(); + _ = await handler.HandleRequestAsync(); return; } } diff --git a/bff/src/Bff/Endpoints/Internal/BffAuthenticationService.cs b/bff/src/Bff/Endpoints/Internal/BffAuthenticationService.cs index 35599c65f..e65075051 100644 --- a/bff/src/Bff/Endpoints/Internal/BffAuthenticationService.cs +++ b/bff/src/Bff/Endpoints/Internal/BffAuthenticationService.cs @@ -78,8 +78,8 @@ internal class BffAuthenticationService(Decorator decora { logger.ChallengeForBffApiEndpoint(LogLevel.Debug); context.Response.StatusCode = 401; - context.Response.Headers.Remove("Location"); - context.Response.Headers.Remove("Set-Cookie"); + _ = context.Response.Headers.Remove("Location"); + _ = context.Response.Headers.Remove("Set-Cookie"); } } @@ -105,8 +105,8 @@ internal class BffAuthenticationService(Decorator decora { logger.ForbidForBffApiEndpoint(LogLevel.Debug); context.Response.StatusCode = 403; - context.Response.Headers.Remove("Location"); - context.Response.Headers.Remove("Set-Cookie"); + _ = context.Response.Headers.Remove("Location"); + _ = context.Response.Headers.Remove("Set-Cookie"); } } } diff --git a/bff/src/Bff/HttpContextExtensions.cs b/bff/src/Bff/HttpContextExtensions.cs index f995a975c..60b8e1d3f 100644 --- a/bff/src/Bff/HttpContextExtensions.cs +++ b/bff/src/Bff/HttpContextExtensions.cs @@ -24,7 +24,7 @@ internal static class HttpContextExtensions }; context.Response.StatusCode = problem.Status.Value; context.Response.ContentType = "application/problem+json"; - context.Response.WriteAsJsonAsync(problem); + _ = context.Response.WriteAsJsonAsync(problem); } diff --git a/bff/src/Bff/Internal/DecoratorServiceCollectionExtensions.cs b/bff/src/Bff/Internal/DecoratorServiceCollectionExtensions.cs index e0bcf8bb7..c22e6dd56 100644 --- a/bff/src/Bff/Internal/DecoratorServiceCollectionExtensions.cs +++ b/bff/src/Bff/Internal/DecoratorServiceCollectionExtensions.cs @@ -16,7 +16,7 @@ internal static class DecoratorServiceCollectionExtensions where TImplementation : class, TService { services.AddDecorator(); - services.AddSingleton(); + _ = services.AddSingleton(); } internal static void AddTransientDecorator(this IServiceCollection services) @@ -24,7 +24,7 @@ internal static class DecoratorServiceCollectionExtensions where TImplementation : class, TService { services.AddDecorator(); - services.AddTransient(); + _ = services.AddTransient(); } internal static void AddDecorator(this IServiceCollection services) @@ -40,7 +40,7 @@ internal static class DecoratorServiceCollectionExtensions throw new InvalidOperationException("Decorator already registered for type: " + typeof(TService).Name + "."); } - services.Remove(registration); + _ = services.Remove(registration); if (registration.ImplementationInstance != null) { diff --git a/bff/src/Bff/Licensing/TrialModeAuthenticatedSessionTracker.cs b/bff/src/Bff/Licensing/TrialModeAuthenticatedSessionTracker.cs index 8de94f481..4272462f6 100644 --- a/bff/src/Bff/Licensing/TrialModeAuthenticatedSessionTracker.cs +++ b/bff/src/Bff/Licensing/TrialModeAuthenticatedSessionTracker.cs @@ -15,7 +15,7 @@ internal class TrialModeAuthenticatedSessionTracker { if (_authenticatedSessions.Count <= LicenseValidator.MaximumAllowedSessionsInTrialMode) { - _authenticatedSessions.TryAdd(subjectId, 0); + _ = _authenticatedSessions.TryAdd(subjectId, 0); } } } diff --git a/bff/src/Bff/ServiceCollectionExtensions.cs b/bff/src/Bff/ServiceCollectionExtensions.cs index 610033051..c771aa385 100644 --- a/bff/src/Bff/ServiceCollectionExtensions.cs +++ b/bff/src/Bff/ServiceCollectionExtensions.cs @@ -23,7 +23,7 @@ public static class ServiceCollectionExtensions if (configureAction != null) { - builder.Services.Configure(configureAction); + _ = builder.Services.Configure(configureAction); } return builder @@ -79,7 +79,7 @@ internal class BffBuilder : IBffServicesBuilder _loadedConfiguration = section; - Services.Configure(section); + _ = Services.Configure(section); // Trigger all configuration loaders from plugins foreach (var configLoader in _pluginConfigurationLoaders) diff --git a/bff/src/Bff/SessionManagement/SessionStore/InMemoryUserSessionStore.cs b/bff/src/Bff/SessionManagement/SessionStore/InMemoryUserSessionStore.cs index f02d0f91b..e097804f6 100644 --- a/bff/src/Bff/SessionManagement/SessionStore/InMemoryUserSessionStore.cs +++ b/bff/src/Bff/SessionManagement/SessionStore/InMemoryUserSessionStore.cs @@ -50,7 +50,7 @@ internal class InMemoryUserSessionStore( public Task GetUserSessionAsync(UserSessionKey key, Ct ct = default) { var partition = GetPartition(key.PartitionKey); - partition.TryGetValue(key.UserKey, out var item); + _ = partition.TryGetValue(key.UserKey, out var item); return Task.FromResult(item?.Clone()); } @@ -73,7 +73,7 @@ internal class InMemoryUserSessionStore( public Task DeleteUserSessionAsync(UserSessionKey key, Ct ct = default) { var partition = GetPartition(key.PartitionKey); - partition.TryRemove(key.UserKey, out _); + _ = partition.TryRemove(key.UserKey, out _); return Task.CompletedTask; } @@ -117,7 +117,7 @@ internal class InMemoryUserSessionStore( .ToArray(); foreach (var key in keys) { - partition.TryRemove(key, out _); + _ = partition.TryRemove(key, out _); } return Task.CompletedTask; diff --git a/bff/src/Directory.Build.props b/bff/src/Directory.Build.props index 3945e60f8..1fa333316 100644 --- a/bff/src/Directory.Build.props +++ b/bff/src/Directory.Build.props @@ -1,10 +1,10 @@ + - All enable OAuth 2.0;OpenID Connect;Security;BFF;IdentityServer;ASP.NET Core;SPA;Blazor Duende BFF @@ -12,14 +12,12 @@ 2.3 Duende.$(MSBuildProjectName) $(AssemblyName) - - - - $(NoWarn);CA1034;CA2007 + + $(NoWarn);RS0026 + + + $(NoWarn);RS0027 diff --git a/bff/src/Directory.Build.targets b/bff/src/Directory.Build.targets new file mode 100644 index 000000000..acbac1881 --- /dev/null +++ b/bff/src/Directory.Build.targets @@ -0,0 +1,4 @@ + + + + diff --git a/bff/templates/src/BffBlazorAutoRenderMode/BffBlazorAutoRenderMode.Client/BffBlazorAutoRenderMode.Client.csproj b/bff/templates/src/BffBlazorAutoRenderMode/BffBlazorAutoRenderMode.Client/BffBlazorAutoRenderMode.Client.csproj index 93d18f9e8..2efe466a9 100644 --- a/bff/templates/src/BffBlazorAutoRenderMode/BffBlazorAutoRenderMode.Client/BffBlazorAutoRenderMode.Client.csproj +++ b/bff/templates/src/BffBlazorAutoRenderMode/BffBlazorAutoRenderMode.Client/BffBlazorAutoRenderMode.Client.csproj @@ -1,5 +1,4 @@ - net10.0 enable @@ -8,16 +7,13 @@ Default BffBlazorAutoRenderMode.Client - $(TargetFramework) - + - - diff --git a/bff/templates/src/BffBlazorAutoRenderMode/BffBlazorAutoRenderMode.Client/WeatherClient.cs b/bff/templates/src/BffBlazorAutoRenderMode/BffBlazorAutoRenderMode.Client/WeatherClient.cs index 739cafffe..afb1d081f 100644 --- a/bff/templates/src/BffBlazorAutoRenderMode/BffBlazorAutoRenderMode.Client/WeatherClient.cs +++ b/bff/templates/src/BffBlazorAutoRenderMode/BffBlazorAutoRenderMode.Client/WeatherClient.cs @@ -4,7 +4,7 @@ using System.Text.Json; /// /// this is an example of a class that would access the data via a web service. This is typically /// what you'd do in webassembly. -/// Note that it implements the same interface as the +/// Note that it implements the same interface as the ServerWeatherClient /// when it's rendering on the server. /// /// diff --git a/bff/templates/src/BffBlazorAutoRenderMode/BffBlazorAutoRenderMode/BffBlazorAutoRenderMode.csproj b/bff/templates/src/BffBlazorAutoRenderMode/BffBlazorAutoRenderMode/BffBlazorAutoRenderMode.csproj index aea2f1aae..ebb5a2753 100644 --- a/bff/templates/src/BffBlazorAutoRenderMode/BffBlazorAutoRenderMode/BffBlazorAutoRenderMode.csproj +++ b/bff/templates/src/BffBlazorAutoRenderMode/BffBlazorAutoRenderMode/BffBlazorAutoRenderMode.csproj @@ -1,22 +1,18 @@ - net10.0 enable enable - $(TargetFramework) UseMapStaticAssets - - + - diff --git a/bff/templates/src/BffLocalApi/BffLocalApi.csproj b/bff/templates/src/BffLocalApi/BffLocalApi.csproj index f4120d7eb..aa6757fb4 100644 --- a/bff/templates/src/BffLocalApi/BffLocalApi.csproj +++ b/bff/templates/src/BffLocalApi/BffLocalApi.csproj @@ -1,15 +1,11 @@ - net10.0 enable - - - + - diff --git a/bff/templates/src/BffLocalApi/HostingExtensions.cs b/bff/templates/src/BffLocalApi/HostingExtensions.cs index d986d952e..d3decc007 100644 --- a/bff/templates/src/BffLocalApi/HostingExtensions.cs +++ b/bff/templates/src/BffLocalApi/HostingExtensions.cs @@ -6,17 +6,17 @@ internal static class HostingExtensions { public static WebApplication ConfigureServices(this WebApplicationBuilder builder) { - builder.Services.AddRazorPages(); + _ = builder.Services.AddRazorPages(); - builder.Services.AddControllers(); + _ = builder.Services.AddControllers(); // add BFF services and server-side session management - builder.Services.AddBff() + _ = builder.Services.AddBff() // if you wanted to enable a remote API (in addition or instead of the local API), then you could uncomment this line //.AddRemoteApis() .AddServerSideSessions(); - builder.Services.AddAuthentication(options => + _ = builder.Services.AddAuthentication(options => { options.DefaultScheme = "cookie"; options.DefaultChallengeScheme = "oidc"; @@ -54,24 +54,24 @@ internal static class HostingExtensions public static WebApplication ConfigurePipeline(this WebApplication app) { - app.UseSerilogRequestLogging(); + _ = app.UseSerilogRequestLogging(); if (app.Environment.IsDevelopment()) { - app.UseDeveloperExceptionPage(); + _ = app.UseDeveloperExceptionPage(); } - app.UseDefaultFiles(); - app.UseStaticFiles(); - app.UseAuthentication(); - app.UseRouting(); + _ = app.UseDefaultFiles(); + _ = app.UseStaticFiles(); + _ = app.UseAuthentication(); + _ = app.UseRouting(); // add CSRF protection and status code handling for API endpoints - app.UseBff(); - app.UseAuthorization(); + _ = app.UseBff(); + _ = app.UseAuthorization(); // local API endpoints - app.MapControllers() + _ = app.MapControllers() .RequireAuthorization() .AsBffApiEndpoint(); diff --git a/bff/templates/src/BffLocalApi/Program.cs b/bff/templates/src/BffLocalApi/Program.cs index 8ee9c7548..cc8141c10 100644 --- a/bff/templates/src/BffLocalApi/Program.cs +++ b/bff/templates/src/BffLocalApi/Program.cs @@ -11,7 +11,7 @@ try { var builder = WebApplication.CreateBuilder(args); - builder.Services.AddSerilog(lc => lc + _ = builder.Services.AddSerilog(lc => lc .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}") .Enrich.FromLogContext() .ReadFrom.Configuration(builder.Configuration)); diff --git a/bff/templates/src/BffLocalApi/ToDoController.cs b/bff/templates/src/BffLocalApi/ToDoController.cs index 93e074c53..b42e3695e 100644 --- a/bff/templates/src/BffLocalApi/ToDoController.cs +++ b/bff/templates/src/BffLocalApi/ToDoController.cs @@ -74,7 +74,7 @@ public class ToDoController : ControllerBase return NotFound(); } - __data.Remove(item); + _ = __data.Remove(item); _logger.LogInformation("Delete {id}", id); return NoContent(); diff --git a/bff/templates/src/BffRemoteApi/Program.cs b/bff/templates/src/BffRemoteApi/Program.cs index 00f2f06cd..c34700d0d 100644 --- a/bff/templates/src/BffRemoteApi/Program.cs +++ b/bff/templates/src/BffRemoteApi/Program.cs @@ -61,7 +61,7 @@ if (config.Apis.Any()) { foreach (var api in config.Apis) { - app.MapRemoteBffApiEndpoint(api.PathMatch, api.RemoteUrl!) + _ = app.MapRemoteBffApiEndpoint(api.PathMatch, api.RemoteUrl!) .RequireAccessToken(api.RequiredToken); } } diff --git a/bff/templates/src/Directory.Build.props b/bff/templates/src/Directory.Build.props index 5f301425b..5f00c8296 100644 --- a/bff/templates/src/Directory.Build.props +++ b/bff/templates/src/Directory.Build.props @@ -1,7 +1,10 @@ + false + false + None true diff --git a/bff/test/Bff.Tests/Bff.Tests.csproj b/bff/test/Bff.Tests/Bff.Tests.csproj index c883aa828..9865a8887 100644 --- a/bff/test/Bff.Tests/Bff.Tests.csproj +++ b/bff/test/Bff.Tests/Bff.Tests.csproj @@ -1,26 +1,22 @@ - net10.0 enable True - - - - + + - + - @@ -29,5 +25,4 @@ - diff --git a/bff/test/Bff.Tests/BffFrontendIndexTests.cs b/bff/test/Bff.Tests/BffFrontendIndexTests.cs index b90097a52..cd163826d 100644 --- a/bff/test/Bff.Tests/BffFrontendIndexTests.cs +++ b/bff/test/Bff.Tests/BffFrontendIndexTests.cs @@ -12,9 +12,8 @@ namespace Duende.Bff.Tests; public class BffFrontendIndexTests : BffTestBase { - public BffFrontendIndexTests() : base() => - // Disable the map to '/' for the test - Bff.MapGetForRoot = false; + // Disable the map to '/' for the test + public BffFrontendIndexTests() : base() => Bff.MapGetForRoot = false; [Fact] public async Task After_login_index_document_is_returned() @@ -26,16 +25,16 @@ public class BffFrontendIndexTests : BffTestBase CdnIndexHtmlUrl = Cdn.Url("index.html") }); - await Bff.BrowserClient.Login() + _ = await Bff.BrowserClient.Login() .CheckResponseContent(Cdn.IndexHtml); // A non-existing page should also return the index.html - await Bff.BrowserClient.GetAsync("/not-found") + _ = await Bff.BrowserClient.GetAsync("/not-found") .CheckResponseContent(Cdn.IndexHtml); // The existing image.png should also return index html, because // we're not doing proxying of static assets here. - await Bff.BrowserClient.GetAsync("/image.png") + _ = await Bff.BrowserClient.GetAsync("/image.png") .CheckResponseContent(Cdn.IndexHtml); } @@ -44,7 +43,7 @@ public class BffFrontendIndexTests : BffTestBase { Bff.OnConfigureBff += opt => { - opt.AddRemoteApis(); + _ = opt.AddRemoteApis(); }; await InitializeAsync(); @@ -59,7 +58,7 @@ public class BffFrontendIndexTests : BffTestBase }) ); - await Bff.BrowserClient.Login() + _ = await Bff.BrowserClient.Login() .CheckResponseContent(Cdn.IndexHtml); var result = await Bff.BrowserClient.CallBffHostApi(The.PathAndSubPath); @@ -69,7 +68,7 @@ public class BffFrontendIndexTests : BffTestBase { Bff.OnConfigureApp += app => { - app.MapGet("/local", () => "ok"); + _ = app.MapGet("/local", () => "ok"); }; await InitializeAsync(); @@ -79,7 +78,7 @@ public class BffFrontendIndexTests : BffTestBase CdnIndexHtmlUrl = Cdn.Url("index.html") }); - await Bff.BrowserClient.Login() + _ = await Bff.BrowserClient.Login() .CheckResponseContent(Cdn.IndexHtml); var result = await Bff.BrowserClient.GetAsync("/local") @@ -97,7 +96,7 @@ public class BffFrontendIndexTests : BffTestBase }); // get a random path. The index.html should be registered as fallback route - await Bff.BrowserClient.GetAsync("/random-path") + _ = await Bff.BrowserClient.GetAsync("/random-path") .CheckHttpStatusCode() .CheckResponseContent(Cdn.IndexHtml); } @@ -107,7 +106,7 @@ public class BffFrontendIndexTests : BffTestBase { Bff.OnConfigureServices += services => { - services.AddSingleton(); + _ = services.AddSingleton(); }; await InitializeAsync(); @@ -137,8 +136,8 @@ public class BffFrontendIndexTests : BffTestBase { Bff.OnConfigureServices += services => { - services.AddSingleton(); - services.AddSingleton(); + _ = services.AddSingleton(); + _ = services.AddSingleton(); }; await InitializeAsync(); @@ -179,7 +178,7 @@ public class BffFrontendIndexTests : BffTestBase { Bff.OnConfigureServices += services => { - services.AddSingleton(); + _ = services.AddSingleton(); }; await InitializeAsync(); @@ -188,20 +187,20 @@ public class BffFrontendIndexTests : BffTestBase StaticAssetsUrl = Cdn.Url("/") }); - await Bff.BrowserClient.GetAsync("/") + _ = await Bff.BrowserClient.GetAsync("/") .CheckResponseContent(Cdn.IndexHtml + " - transformed 1"); // When you get an explicit HTML file, it's not the index.html file, so we're // not transforming it - await Bff.BrowserClient.GetAsync("/index2.html") + _ = await Bff.BrowserClient.GetAsync("/index2.html") .CheckResponseContent(Cdn.IndexHtml); // A non-existing page should also return the index.html and it should go through the transformer - await Bff.BrowserClient.GetAsync("/not-found") + _ = await Bff.BrowserClient.GetAsync("/not-found") .CheckResponseContent(Cdn.IndexHtml + " - transformed 2"); // The existing image.png should be proxied through the BFF. and should not be transformed - await Bff.BrowserClient.GetAsync("/image.png") + _ = await Bff.BrowserClient.GetAsync("/image.png") .CheckResponseContent(Cdn.ImageBytes); } @@ -216,18 +215,18 @@ public class BffFrontendIndexTests : BffTestBase StaticAssetsUrl = Cdn.Url("/") }); - await Bff.BrowserClient.Login() + _ = await Bff.BrowserClient.Login() .CheckResponseContent(Cdn.IndexHtml); - await Bff.BrowserClient.GetAsync("/test") + _ = await Bff.BrowserClient.GetAsync("/test") .CheckResponseContent("test"); // A non-existing page should also return the index.html - await Bff.BrowserClient.GetAsync("/not-found") + _ = await Bff.BrowserClient.GetAsync("/not-found") .CheckResponseContent(Cdn.IndexHtml); // The existing image.png should be proxied through the BFF. - await Bff.BrowserClient.GetAsync("/image.png") + _ = await Bff.BrowserClient.GetAsync("/image.png") .CheckResponseContent(Cdn.ImageBytes); } @@ -247,11 +246,11 @@ public class BffFrontendIndexTests : BffTestBase // Verifying that querystring parameters are passed correctly to the proxied endpoint // This is important, because vite dev server adds a querystring parameters to get // partial files - await Bff.BrowserClient.GetAsync("/withQuery?q=abc") + _ = await Bff.BrowserClient.GetAsync("/withQuery?q=abc") .CheckResponseContent("abc"); // Just a quick check to verify encoding works as expected - await Bff.BrowserClient.GetAsync("/withQuery?q=" + UrlEncoder.Default.Encode("?@%^&*()")) + _ = await Bff.BrowserClient.GetAsync("/withQuery?q=" + UrlEncoder.Default.Encode("?@%^&*()")) .CheckResponseContent("?@%^&*()"); } @@ -274,25 +273,25 @@ public class BffFrontendIndexTests : BffTestBase // When getting the root of the path-mapped frontend, then we should get the static content // from the cdn - await Bff.BrowserClient.GetAsync(The.Path) + _ = await Bff.BrowserClient.GetAsync(The.Path) .CheckResponseContent(Cdn.IndexHtml); // It should also work for sub-paths and client side routing (The /test path doesn't exist on the cdn) // so the index.html should be returned - await Bff.BrowserClient.GetAsync(The.Path + "/test") + _ = await Bff.BrowserClient.GetAsync(The.Path + "/test") .CheckResponseContent(Cdn.IndexHtml); // It should also work for static assets that exist on the cdn, such as the image. - await Bff.BrowserClient.GetAsync(The.Path + "/image.png") + _ = await Bff.BrowserClient.GetAsync(The.Path + "/image.png") .CheckResponseContent(Cdn.ImageBytes); // Now, if you go to the default frontend, it should return // the different static content that's only registered for the default frontend - await Bff.BrowserClient.GetAsync("/") + _ = await Bff.BrowserClient.GetAsync("/") .CheckResponseContent("default_frontend"); // The image should not be registered (we only proxy the index.html for the default frontend) - await Bff.BrowserClient.GetAsync("/image.png") + _ = await Bff.BrowserClient.GetAsync("/image.png") .CheckResponseContent("default_frontend"); } @@ -306,20 +305,20 @@ public class BffFrontendIndexTests : BffTestBase AddOrUpdateFrontend(Some.BffFrontend().WithBffStaticAssets(Cdn.Url("/"), () => indexHtmlOnly)); - await Bff.BrowserClient.Login() + _ = await Bff.BrowserClient.Login() .CheckResponseContent(Cdn.IndexHtml); if (indexHtmlOnly) { // If we only proxy the index html, then any unmatched route (including the image.png) // should return the index.html content (for client side routing purposes) - await Bff.BrowserClient.GetAsync("/image.png") + _ = await Bff.BrowserClient.GetAsync("/image.png") .CheckResponseContent(Cdn.IndexHtml); } else { // If we proxy all static assets for this frontend, then the image.png should be proxied - await Bff.BrowserClient.GetAsync("/image.png") + _ = await Bff.BrowserClient.GetAsync("/image.png") .CheckResponseContent(Cdn.ImageBytes); } } diff --git a/bff/test/Bff.Tests/BffFrontendMatchingTests.cs b/bff/test/Bff.Tests/BffFrontendMatchingTests.cs index 52e0b4e8b..37a9f312e 100644 --- a/bff/test/Bff.Tests/BffFrontendMatchingTests.cs +++ b/bff/test/Bff.Tests/BffFrontendMatchingTests.cs @@ -18,7 +18,7 @@ public class BffFrontendMatchingTests : BffTestBase Bff.OnConfigureApp += app => { - app.MapGet("/show-front-end", + _ = app.MapGet("/show-front-end", (CurrentFrontendAccessor currentFrontendAccessor) => { if (currentFrontendAccessor.TryGet(out var frontend)) @@ -35,31 +35,31 @@ public class BffFrontendMatchingTests : BffTestBase public async Task When_no_frontend_but_openid_config_then_all_endpoints_are_present() { Bff.OnConfigureBff += bff => bff.ConfigureOpenIdConnect(The.DefaultOpenIdConnectConfiguration); - IdentityServer.AddClient(The.ClientId, Bff.Url()); + _ = IdentityServer.AddClient(The.ClientId, Bff.Url()); await InitializeAsync(); // Remove the never-matching frontend so the default frontend is used Bff.Resolve().Remove(Some.NeverMatchingFrontEnd().Name); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); var user = await Bff.BrowserClient.CallUserEndpointAsync(); user.ShouldNotBeEmpty(); - await Bff.BrowserClient.Logout(); + _ = await Bff.BrowserClient.Logout(); } [Fact] public async Task Given_unmatched_frontend_then_default_frontend_is_disabled() { Bff.OnConfigureBff += bff => bff.ConfigureOpenIdConnect(The.DefaultOpenIdConnectConfiguration); - IdentityServer.AddClient(The.ClientId, Bff.Url("not_matched/")); + _ = IdentityServer.AddClient(The.ClientId, Bff.Url("not_matched/")); await InitializeAsync(); Bff.AddOrUpdateFrontend(Some.BffFrontend().MapToPath("/not_matched")); Bff.BrowserClient.DefaultRequestHeaders.Add("x-csrf", "1"); - await Bff.BrowserClient.Login(expectedStatusCode: HttpStatusCode.NotFound); - await Bff.BrowserClient.GetAsync("/bff/diagnostics").CheckHttpStatusCode(HttpStatusCode.NotFound); - await Bff.BrowserClient.GetAsync("/bff/logout").CheckHttpStatusCode(HttpStatusCode.NotFound); - await Bff.BrowserClient.GetAsync("/bff/user").CheckHttpStatusCode(HttpStatusCode.NotFound); + _ = await Bff.BrowserClient.Login(expectedStatusCode: HttpStatusCode.NotFound); + _ = await Bff.BrowserClient.GetAsync("/bff/diagnostics").CheckHttpStatusCode(HttpStatusCode.NotFound); + _ = await Bff.BrowserClient.GetAsync("/bff/logout").CheckHttpStatusCode(HttpStatusCode.NotFound); + _ = await Bff.BrowserClient.GetAsync("/bff/user").CheckHttpStatusCode(HttpStatusCode.NotFound); } [Fact] @@ -120,7 +120,7 @@ public class BffFrontendMatchingTests : BffTestBase { Bff.OnConfigureServices += services => { - services.Configure(options => + _ = services.Configure(options => { options.ForwardedHeaders = ForwardedHeaders.XForwardedHost; }); diff --git a/bff/test/Bff.Tests/BffFrontendSigninTests.cs b/bff/test/Bff.Tests/BffFrontendSigninTests.cs index 50c99a202..ee5c1f3cc 100644 --- a/bff/test/Bff.Tests/BffFrontendSigninTests.cs +++ b/bff/test/Bff.Tests/BffFrontendSigninTests.cs @@ -19,7 +19,7 @@ public class BffFrontendSigninTests : BffTestBase public BffFrontendSigninTests() : base() => Bff.OnConfigureApp += app => { - app.MapGet("/secret", (HttpContext c) => + _ = app.MapGet("/secret", (HttpContext c) => { if (!c.User.IsAuthenticated()) { @@ -39,7 +39,7 @@ public class BffFrontendSigninTests : BffTestBase AddOrUpdateFrontend(Some.BffFrontend()); - await Bff.BrowserClient.GetAsync("/") + _ = await Bff.BrowserClient.GetAsync("/") .CheckHttpStatusCode() .CheckResponseContent(Bff.DefaultRootResponse); } @@ -60,12 +60,12 @@ public class BffFrontendSigninTests : BffTestBase Bff.OnConfigureApp += app => { - app.MapGet(pathString, (HttpContext c, Ct ct) => "ok"); + _ = app.MapGet(pathString, (HttpContext c, Ct ct) => "ok"); }; await InitializeAsync(); - await Bff.BrowserClient.GetAsync(pathString) + _ = await Bff.BrowserClient.GetAsync(pathString) .CheckHttpStatusCode() .CheckResponseContent("ok"); } @@ -77,13 +77,13 @@ public class BffFrontendSigninTests : BffTestBase var logoutCalled = false; Bff.OnConfigureApp += app => { - app.MapGet(Bff.BffOptions.LoginPath, c => + _ = app.MapGet(Bff.BffOptions.LoginPath, c => { loginCalled = true; return c.RequestServices.GetRequiredService().ProcessRequestAsync(c); }); - app.MapGet(Bff.BffOptions.LogoutPath, c => + _ = app.MapGet(Bff.BffOptions.LogoutPath, c => { logoutCalled = true; return c.RequestServices.GetRequiredService().ProcessRequestAsync(c); @@ -93,10 +93,10 @@ public class BffFrontendSigninTests : BffTestBase AddOrUpdateFrontend(Some.BffFrontend()); - await Bff.BrowserClient.Login() + _ = await Bff.BrowserClient.Login() .CheckResponseContent(Bff.DefaultRootResponse); - await Bff.BrowserClient.Logout(); + _ = await Bff.BrowserClient.Logout(); loginCalled.ShouldBeTrue(); logoutCalled.ShouldBeTrue(); } @@ -108,22 +108,22 @@ public class BffFrontendSigninTests : BffTestBase AddOrUpdateFrontend(Some.BffFrontend()); - await Bff.BrowserClient.GetAsync("/secret") + _ = await Bff.BrowserClient.GetAsync("/secret") .CheckHttpStatusCode(HttpStatusCode.Unauthorized); } [Fact] public async Task Can_add_frontends_using_AddFrontends_ExtensionMethod() { - IdentityServer.AddClientFor(Some.BffFrontend(), [Bff.Url()]); + _ = IdentityServer.AddClientFor(Some.BffFrontend(), [Bff.Url()]); Bff.OnConfigureBff += bff => bff.AddFrontends(Some.BffFrontend()); await InitializeAsync(); - await Bff.BrowserClient.Login() + _ = await Bff.BrowserClient.Login() .CheckResponseContent(Bff.DefaultRootResponse); - await Bff.BrowserClient.GetAsync("/secret") + _ = await Bff.BrowserClient.GetAsync("/secret") .CheckHttpStatusCode(); } @@ -141,13 +141,13 @@ public class BffFrontendSigninTests : BffTestBase }, }); - IdentityServer.AddClientFor(frontEnd, [Bff.Url()]); + _ = IdentityServer.AddClientFor(frontEnd, [Bff.Url()]); Bff.AddOrUpdateFrontend(frontEnd); for (var i = 0; i < 10; i++) { var client = Internet.BuildHttpClient(Bff.Url()); - await client.GetAsync("/somepath/bff/login") + _ = await client.GetAsync("/somepath/bff/login") .CheckResponseContent(Bff.DefaultRootResponse); } } @@ -166,21 +166,21 @@ public class BffFrontendSigninTests : BffTestBase }, }); - IdentityServer.AddClientFor(frontEnd, [Bff.Url()]); + _ = IdentityServer.AddClientFor(frontEnd, [Bff.Url()]); Bff.AddOrUpdateFrontend(frontEnd); - await Bff.BrowserClient.Login("/somepath") + _ = await Bff.BrowserClient.Login("/somepath") .CheckResponseContent(Bff.DefaultRootResponse); var cookie = Bff.BrowserClient.Cookies.GetCookies(Bff.Url("/somepath")).FirstOrDefault(); - cookie.ShouldNotBeNull(); + _ = cookie.ShouldNotBeNull(); cookie.HttpOnly.ShouldBeTrue(); cookie.Name.ShouldBe(Constants.Cookies.SecurePrefix + "_" + "with_somepath"); cookie.Secure.ShouldBeTrue(); cookie.Path.ShouldBe("/somepath"); - await Bff.BrowserClient.GetAsync("/somepath/secret") + _ = await Bff.BrowserClient.GetAsync("/somepath/secret") .CheckHttpStatusCode(); } @@ -198,11 +198,11 @@ public class BffFrontendSigninTests : BffTestBase }, }); - IdentityServer.AddClientFor(frontEnd, [Bff.Url()]); + _ = IdentityServer.AddClientFor(frontEnd, [Bff.Url()]); Bff.AddOrUpdateFrontend(frontEnd); - await Bff.BrowserClient.Login(expectedStatusCode: HttpStatusCode.NotFound); + _ = await Bff.BrowserClient.Login(expectedStatusCode: HttpStatusCode.NotFound); } [Fact] @@ -211,7 +211,7 @@ public class BffFrontendSigninTests : BffTestBase { Bff.OnConfigureServices += svcs => { - svcs.Configure(options => { options.ManagementBasePath = "/custom/bff"; }); + _ = svcs.Configure(options => { options.ManagementBasePath = "/custom/bff"; }); }; await InitializeAsync(); @@ -224,10 +224,10 @@ public class BffFrontendSigninTests : BffTestBase }, }); - IdentityServer.AddClientFor(frontEnd, [Bff.Url()]); + _ = IdentityServer.AddClientFor(frontEnd, [Bff.Url()]); Bff.AddOrUpdateFrontend(frontEnd); - await Bff.BrowserClient.Login(expectedStatusCode: HttpStatusCode.NotFound); + _ = await Bff.BrowserClient.Login(expectedStatusCode: HttpStatusCode.NotFound); var response = await Bff.BrowserClient.Login("/somepath/custom"); @@ -248,11 +248,11 @@ public class BffFrontendSigninTests : BffTestBase }, }); - IdentityServer.AddClientFor(frontEnd, [Bff.Url()]); + _ = IdentityServer.AddClientFor(frontEnd, [Bff.Url()]); Bff.AddOrUpdateFrontend(frontEnd); - await Bff.BrowserClient.Login("/somepath") + _ = await Bff.BrowserClient.Login("/somepath") .CheckResponseContent(Bff.DefaultRootResponse); var response = await Bff.BrowserClient.GetAsync("/somepath/bff/silent-login"); @@ -270,14 +270,14 @@ public class BffFrontendSigninTests : BffTestBase AddOrUpdateFrontend(Some.BffFrontend()); - await Bff.BrowserClient.Login() + _ = await Bff.BrowserClient.Login() .CheckResponseContent(Bff.DefaultRootResponse); - await Bff.BrowserClient.GetAsync("/secret") + _ = await Bff.BrowserClient.GetAsync("/secret") .CheckHttpStatusCode(); var cookie = Bff.BrowserClient.Cookies.GetCookies(Bff.Url()).FirstOrDefault(); - cookie.ShouldNotBeNull(); + _ = cookie.ShouldNotBeNull(); cookie.HttpOnly.ShouldBeTrue(); cookie.Name.ShouldBe(Constants.Cookies.HostPrefix + "_" + The.FrontendName); cookie.Secure.ShouldBeTrue(); @@ -292,7 +292,7 @@ public class BffFrontendSigninTests : BffTestBase var bffFrontend = Some.BffFrontend(); AddOrUpdateFrontend(bffFrontend); - await Bff.BrowserClient.Login() + _ = await Bff.BrowserClient.Login() .CheckResponseContent(Bff.DefaultRootResponse); // Bit weird, but the easiest way to see if the new settings are used is to update @@ -306,7 +306,7 @@ public class BffFrontendSigninTests : BffTestBase } }); - await Bff.BrowserClient.Login() + _ = await Bff.BrowserClient.Login() .ShouldThrowAsync(); } @@ -315,16 +315,16 @@ public class BffFrontendSigninTests : BffTestBase { Bff.OnConfigureServices += services => { - services.AddSingleton(); + _ = services.AddSingleton(); }; Bff.OnConfigureBff += bff => bff.AddRemoteApis(); - IdentityServer.AddClient("differnet_client_id", Bff.Url()); + _ = IdentityServer.AddClient("differnet_client_id", Bff.Url()); await InitializeAsync(); var bffFrontend = Some.BffFrontend().WithRemoteApis(new RemoteApi("/test", Api.Url()).WithAccessToken(RequiredTokenType.Client)); AddOrUpdateFrontend(bffFrontend); - await Bff.BrowserClient.Login() + _ = await Bff.BrowserClient.Login() .CheckResponseContent(Bff.DefaultRootResponse); ApiCallDetails response = await Bff.BrowserClient.CallBffHostApi("/test"); @@ -344,7 +344,7 @@ public class BffFrontendSigninTests : BffTestBase // But it does so on a background thread, so we need to wait for it cache.WaitUntilRemoveByTagAsyncCalled(TimeSpan.FromSeconds(1)); - await Bff.BrowserClient.Login() + _ = await Bff.BrowserClient.Login() .CheckResponseContent(Bff.DefaultRootResponse); ApiCallDetails response2 = await Bff.BrowserClient.CallBffHostApi("/test"); @@ -360,7 +360,7 @@ public class BffFrontendSigninTests : BffTestBase var bffFrontend = Some.BffFrontend(); AddOrUpdateFrontend(bffFrontend); - await Bff.BrowserClient.Login() + _ = await Bff.BrowserClient.Login() .CheckResponseContent(Bff.DefaultRootResponse); Bff.BrowserClient.Cookies.Clear(Bff.Url()); @@ -372,7 +372,7 @@ public class BffFrontendSigninTests : BffTestBase ConfigureCookieOptions = opt => { opt.Cookie.Name = "my_custom_cookie_name"; } }); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); Bff.BrowserClient.Cookies.GetCookies(Bff.Url()) .ShouldContain(c => c.Name == "my_custom_cookie_name" && c.HttpOnly && c.Secure && c.Path == "/"); @@ -385,7 +385,7 @@ public class BffFrontendSigninTests : BffTestBase Bff.OnConfigureBff += bff => { - bff.ConfigureOpenIdConnect(options => + _ = bff.ConfigureOpenIdConnect(options => { options.Authority = IdentityServer.Url().ToString(); @@ -408,9 +408,9 @@ public class BffFrontendSigninTests : BffTestBase Name = BffFrontendName.Parse("some_frontend") }); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); - await Bff.BrowserClient.GetAsync("/secret") + _ = await Bff.BrowserClient.GetAsync("/secret") .CheckHttpStatusCode(); } @@ -448,9 +448,9 @@ public class BffFrontendSigninTests : BffTestBase Name = BffFrontendName.Parse("some_frontend") }); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); - await Bff.BrowserClient.GetAsync("/secret") + _ = await Bff.BrowserClient.GetAsync("/secret") .CheckHttpStatusCode(); onTokenValidatedInvoked.ShouldBeTrue(); @@ -476,9 +476,9 @@ public class BffFrontendSigninTests : BffTestBase } }); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); - await Bff.BrowserClient.GetAsync("/secret") + _ = await Bff.BrowserClient.GetAsync("/secret") .CheckHttpStatusCode(); onTokenValidatedInvoked.ShouldBeTrue(); @@ -505,7 +505,7 @@ public class BffFrontendSigninTests : BffTestBase await InitializeAsync(); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); onTokenValidatedInvoked.ShouldBeTrue(); onTokenValidatedInvoked = false; AddOrUpdateFrontend(new BffFrontend() @@ -524,11 +524,11 @@ public class BffFrontendSigninTests : BffTestBase Bff.OnConfigureBff += bff => { - bff.LoadConfiguration(configuration); + _ = bff.LoadConfiguration(configuration); }; await InitializeAsync(); - IdentityServer.AddClient(The.ClientId, Bff.Url()); - await Bff.BrowserClient.Login(); + _ = IdentityServer.AddClient(The.ClientId, Bff.Url()); + _ = await Bff.BrowserClient.Login(); } [Fact] @@ -538,7 +538,7 @@ public class BffFrontendSigninTests : BffTestBase Bff.OnConfigureBff += bff => { - bff.LoadConfiguration(configuration); + _ = bff.LoadConfiguration(configuration); }; await InitializeAsync(); @@ -549,8 +549,8 @@ public class BffFrontendSigninTests : BffTestBase MatchingPath = "/not_matched" } }); - IdentityServer.AddClient(The.ClientId, Bff.Url()); - await Bff.BrowserClient.Login(expectedStatusCode: HttpStatusCode.NotFound); + _ = IdentityServer.AddClient(The.ClientId, Bff.Url()); + _ = await Bff.BrowserClient.Login(expectedStatusCode: HttpStatusCode.NotFound); } [Fact] @@ -560,7 +560,7 @@ public class BffFrontendSigninTests : BffTestBase Bff.OnConfigureBff += bff => { - bff.LoadConfiguration(configuration); + _ = bff.LoadConfiguration(configuration); }; await InitializeAsync(); @@ -572,8 +572,8 @@ public class BffFrontendSigninTests : BffTestBase MatchingPath = The.Path } }); - IdentityServer.AddClient(The.ClientId, Bff.Url(The.Path + "/")); - await Bff.BrowserClient.Login(The.Path); + _ = IdentityServer.AddClient(The.ClientId, Bff.Url(The.Path + "/")); + _ = await Bff.BrowserClient.Login(The.Path); } private IConfiguration BuildValidBffOidcConfig() diff --git a/bff/test/Bff.Tests/BffOptionsConfigurationTests.cs b/bff/test/Bff.Tests/BffOptionsConfigurationTests.cs index c9ad480c8..a026d38aa 100644 --- a/bff/test/Bff.Tests/BffOptionsConfigurationTests.cs +++ b/bff/test/Bff.Tests/BffOptionsConfigurationTests.cs @@ -17,7 +17,7 @@ public class BffOptionsConfigurationTests : BffTestBase { Bff.OnConfigureApp += app => { - app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => HttpStatusCode.OK)) + _ = app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => HttpStatusCode.OK)) .RequireAuthorization() .AsBffApiEndpoint(); }; @@ -29,9 +29,9 @@ public class BffOptionsConfigurationTests : BffTestBase // when this happens, this call would fail with No HTTP Context available, // but also all subsequent requests, because IOptionsCache caches this. var opt = Bff.Resolve>(); - opt.Get(Some.BffFrontend().OidcSchemeName); + _ = opt.Get(Some.BffFrontend().OidcSchemeName); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.Path) @@ -48,7 +48,7 @@ public class BffOptionsConfigurationTests : BffTestBase { Bff.OnConfigureApp += app => { - app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => HttpStatusCode.OK)) + _ = app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => HttpStatusCode.OK)) .RequireAuthorization() .AsBffApiEndpoint(); }; @@ -60,9 +60,9 @@ public class BffOptionsConfigurationTests : BffTestBase // when this happens, this call would fail with No HTTP Context available, // but also all subsequent requests, because IOptionsCache caches this. var opt = Bff.Resolve>(); - opt.Get(Some.BffFrontend().CookieSchemeName); + _ = opt.Get(Some.BffFrontend().CookieSchemeName); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.Path) diff --git a/bff/test/Bff.Tests/BffRemoteApiTests.cs b/bff/test/Bff.Tests/BffRemoteApiTests.cs index d5b7ee867..3f65c8dcb 100644 --- a/bff/test/Bff.Tests/BffRemoteApiTests.cs +++ b/bff/test/Bff.Tests/BffRemoteApiTests.cs @@ -19,7 +19,7 @@ public class BffRemoteApiTests : BffTestBase public BffRemoteApiTests() : base() => Bff.OnConfigureBff += bff => { - bff.AddRemoteApis(); + _ = bff.AddRemoteApis(); }; [Theory] @@ -40,7 +40,7 @@ public class BffRemoteApiTests : BffTestBase }) ); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); ApiCallDetails result = await Bff.BrowserClient.CallBffHostApi(The.PathAndSubPath); result.Sub.ShouldBe(The.Sub); @@ -98,12 +98,12 @@ public class BffRemoteApiTests : BffTestBase Bff.OnConfigureBff += bff => { // The remote api registers the testtokenretriever - bff.Services.AddSingleton(); + _ = bff.Services.AddSingleton(); }; await InitializeAsync(); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); var (response, apiResult) = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.Path) @@ -133,7 +133,7 @@ public class BffRemoteApiTests : BffTestBase }) ); - await Bff.BrowserClient.CallBffHostApi(The.PathAndSubPath, + _ = await Bff.BrowserClient.CallBffHostApi(The.PathAndSubPath, expectedStatusCode: HttpStatusCode.Unauthorized); } @@ -160,7 +160,7 @@ public class BffRemoteApiTests : BffTestBase // Register a fake usermanager, that tracks if it was called Bff.OnConfigureServices += services => { - services.AddSingleton(); + _ = services.AddSingleton(); }; await InitializeAsync(); @@ -176,7 +176,7 @@ public class BffRemoteApiTests : BffTestBase ); - await Bff.BrowserClient.CallBffHostApi(The.PathAndSubPath); + _ = await Bff.BrowserClient.CallBffHostApi(The.PathAndSubPath); // A user reported an issue that, if an anonymous request is made, // that errors were being logged. This assertion ensures that no such errors are no longer logged. @@ -191,7 +191,7 @@ public class BffRemoteApiTests : BffTestBase // Register a fake usermanager, that tracks if it was called Bff.OnConfigureServices += services => { - services.AddSingleton(); + _ = services.AddSingleton(); }; await InitializeAsync(); @@ -205,7 +205,7 @@ public class BffRemoteApiTests : BffTestBase }) ); - await Bff.BrowserClient.CallBffHostApi(The.PathAndSubPath); + _ = await Bff.BrowserClient.CallBffHostApi(The.PathAndSubPath); // A user reported an issue that, if an anonymous request is made, // that errors were being logged. This assertion ensures that no such errors are no longer logged. diff --git a/bff/test/Bff.Tests/BffScenarioTests.cs b/bff/test/Bff.Tests/BffScenarioTests.cs index c5764b9b7..bc459c85d 100644 --- a/bff/test/Bff.Tests/BffScenarioTests.cs +++ b/bff/test/Bff.Tests/BffScenarioTests.cs @@ -11,13 +11,13 @@ public class BffScenarioTests : BffTestBase public async Task When_using_bff_as_host_and_client_credentials_token_manager_with_no_http_context_still_works() { var workerClientId = "worker.client.id"; - IdentityServer.AddClient(workerClientId, Bff.Url()); + _ = IdentityServer.AddClient(workerClientId, Bff.Url()); var contentReceived = new TaskCompletionSource(); var workerStarted = new TaskCompletionSource(); Bff.OnConfigureServices += services => { - services.AddClientCredentialsTokenManagement() + _ = services.AddClientCredentialsTokenManagement() .AddClient(ClientCredentialsClientName.Parse("worker.client"), client => { client.TokenEndpoint = new Uri(IdentityServer.Url(), "/connect/token"); @@ -27,14 +27,14 @@ public class BffScenarioTests : BffTestBase client.HttpClient = new HttpClient(Internet, disposeHandler: false); }); - services.AddClientCredentialsHttpClient("worker", + _ = services.AddClientCredentialsHttpClient("worker", ClientCredentialsClientName.Parse("worker.client"), client => { client.BaseAddress = Api.Url(); }) .ConfigurePrimaryHttpMessageHandler(() => Internet); - services.AddSingleton(contentReceived); - services.AddSingleton(workerStarted); - services.AddHostedService(); + _ = services.AddSingleton(contentReceived); + _ = services.AddSingleton(workerStarted); + _ = services.AddHostedService(); }; await InitializeAsync(); workerStarted.SetResult(); @@ -60,17 +60,17 @@ public class BffScenarioTests : BffTestBase if (response.IsSuccessStatusCode) { var content = await response.Content.ReadAsStringAsync(stoppingToken); - contentReceived.TrySetResult(content); + _ = contentReceived.TrySetResult(content); } else { - contentReceived.TrySetException( + _ = contentReceived.TrySetException( new Exception($"Request failed with status code: {response.StatusCode}")); } } catch (Exception ex) { - contentReceived.TrySetException(ex); + _ = contentReceived.TrySetException(ex); } } } diff --git a/bff/test/Bff.Tests/BffWithoutExplicitFrontendTests.cs b/bff/test/Bff.Tests/BffWithoutExplicitFrontendTests.cs index 18059beaf..47dda4a17 100644 --- a/bff/test/Bff.Tests/BffWithoutExplicitFrontendTests.cs +++ b/bff/test/Bff.Tests/BffWithoutExplicitFrontendTests.cs @@ -11,7 +11,7 @@ public class BffWithoutExplicitFrontendTests : BffTestBase { Bff.OnConfigureApp += app => { - app.MapGet("/secret", (HttpContext c, Ct ct) => + _ = app.MapGet("/secret", (HttpContext c, Ct ct) => { if (!c.User.IsAuthenticated()) { @@ -44,14 +44,14 @@ public class BffWithoutExplicitFrontendTests : BffTestBase { await InitializeAsync(); - await Bff.BrowserClient.Login() + _ = await Bff.BrowserClient.Login() .CheckHttpStatusCode(); - await Bff.BrowserClient.GetAsync("/secret") + _ = await Bff.BrowserClient.GetAsync("/secret") .CheckHttpStatusCode(); var cookie = Bff.BrowserClient.Cookies.GetCookies(Bff.Url("/somepath")).FirstOrDefault(); - cookie.ShouldNotBeNull(); + _ = cookie.ShouldNotBeNull(); cookie.HttpOnly.ShouldBeTrue(); cookie.Name.ShouldBe(Constants.Cookies.DefaultCookieName); cookie.Secure.ShouldBeTrue(); diff --git a/bff/test/Bff.Tests/Blazor/BffBlazorTests.cs b/bff/test/Bff.Tests/Blazor/BffBlazorTests.cs index dc1687141..aa1aeabbc 100644 --- a/bff/test/Bff.Tests/Blazor/BffBlazorTests.cs +++ b/bff/test/Bff.Tests/Blazor/BffBlazorTests.cs @@ -18,17 +18,17 @@ public class BffBlazorTests : BffTestBase Bff.MapGetForRoot = false; Bff.OnConfigureServices += services => { - services.AddRazorComponents() + _ = services.AddRazorComponents() .AddInteractiveServerComponents() .AddInteractiveWebAssemblyComponents(); - services.AddCascadingAuthenticationState(); - services.AddAntiforgery(); + _ = services.AddCascadingAuthenticationState(); + _ = services.AddAntiforgery(); }; Bff.OnConfigureBff += bff => { - bff.AddBlazorServer(); + _ = bff.AddBlazorServer(); if (_addServerSideSessions) { @@ -37,13 +37,13 @@ public class BffBlazorTests : BffTestBase $"test-{Guid.NewGuid():N}.sqlite" ); var connectionString = $"Data Source={dbFilePath}"; - bff.AddEntityFrameworkServerSideSessions(options => + _ = bff.AddEntityFrameworkServerSideSessions(options => options.UseSqlite( connectionString, dbOpts => dbOpts.MigrationsAssembly(typeof(Startup).Assembly.FullName) ) ); - bff.AddSessionCleanupBackgroundProcess(); + _ = bff.AddSessionCleanupBackgroundProcess(); } }; @@ -57,8 +57,8 @@ public class BffBlazorTests : BffTestBase scope.ServiceProvider.GetRequiredService().Database.Migrate(); } - app.UseAntiforgery(); - app.MapRazorComponents() + _ = app.UseAntiforgery(); + _ = app.MapRazorComponents() .AddInteractiveServerRenderMode() .AddInteractiveWebAssemblyRenderMode(); }; @@ -96,7 +96,7 @@ public class BffBlazorTests : BffTestBase { await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); Bff.BrowserClient.RedirectHandler.AutoFollowRedirects = false; var response = await Bff.BrowserClient.GetAsync("/secure"); diff --git a/bff/test/Bff.Tests/Blazor/Client/AntiforgeryHandlerTests.cs b/bff/test/Bff.Tests/Blazor/Client/AntiforgeryHandlerTests.cs index 1510efc29..e87d84a89 100644 --- a/bff/test/Bff.Tests/Blazor/Client/AntiforgeryHandlerTests.cs +++ b/bff/test/Bff.Tests/Blazor/Client/AntiforgeryHandlerTests.cs @@ -23,7 +23,7 @@ public class AntiForgeryHandlerTests var client = new HttpClient(sut); - await client.SendAsync(request, Ct.None); + _ = await client.SendAsync(request, Ct.None); request.Headers.ShouldContain(h => h.Key == "X-CSRF" && h.Value.Contains("1")); } diff --git a/bff/test/Bff.Tests/Blazor/Client/BffClientAuthenticationStateProviderTests.cs b/bff/test/Bff.Tests/Blazor/Client/BffClientAuthenticationStateProviderTests.cs index 38f273705..ecc84cbd9 100644 --- a/bff/test/Bff.Tests/Blazor/Client/BffClientAuthenticationStateProviderTests.cs +++ b/bff/test/Bff.Tests/Blazor/Client/BffClientAuthenticationStateProviderTests.cs @@ -3,7 +3,6 @@ using System.Security.Claims; using Duende.Bff.Blazor.Client.Internals; -using Microsoft.Extensions.Time.Testing; using NSubstitute; namespace Duende.Bff.Blazor.Client.UnitTests; @@ -16,7 +15,7 @@ public class BffClientAuthenticationStateProviderTests var userService = Substitute.For(); var persistentUserService = Substitute.For(); var anonymous = new ClaimsPrincipal(new ClaimsIdentity()); - persistentUserService.GetPersistedUser(out Arg.Any()) + _ = persistentUserService.GetPersistedUser(out Arg.Any()) .Returns(x => { x[0] = anonymous; @@ -34,7 +33,7 @@ public class BffClientAuthenticationStateProviderTests var authState = await sut.GetAuthenticationStateAsync(); authState.User.Identity?.IsAuthenticated.ShouldBeFalse(); time.Advance(TimeSpan.FromSeconds(100)); - await userService.DidNotReceive().FetchUserAsync(); + _ = await userService.DidNotReceive().FetchUserAsync(); } [Fact] @@ -54,13 +53,13 @@ public class BffClientAuthenticationStateProviderTests new Claim("name", expectedName), new Claim("source", "fetch") ], "pwd", "name", "role")); - persistentUserService.GetPersistedUser(out Arg.Any()) + _ = persistentUserService.GetPersistedUser(out Arg.Any()) .Returns(x => { x[0] = persistedUser; return true; }); - fetchUserService.FetchUserAsync().Returns(fetchedUser); + _ = fetchUserService.FetchUserAsync().Returns(fetchedUser); var sut = new BffClientAuthenticationStateProvider( fetchUserService, @@ -77,29 +76,29 @@ public class BffClientAuthenticationStateProviderTests authState.User.Identity?.IsAuthenticated.ShouldBeTrue(); authState.User.Identity?.Name.ShouldBe(expectedName); // Initially we get the persisted user and haven't yet polled - persistentUserService.Received(1).GetPersistedUser(out Arg.Any()); - await fetchUserService.DidNotReceive().FetchUserAsync(); + _ = persistentUserService.Received(1).GetPersistedUser(out Arg.Any()); + _ = await fetchUserService.DidNotReceive().FetchUserAsync(); // Advance time within the polling delay, and note that we still haven't made additional calls time.Advance(TimeSpan.FromSeconds(1)); // t = 1 - persistentUserService.Received(1).GetPersistedUser(out Arg.Any()); - await fetchUserService.DidNotReceive().FetchUserAsync(); + _ = persistentUserService.Received(1).GetPersistedUser(out Arg.Any()); + _ = await fetchUserService.DidNotReceive().FetchUserAsync(); // Advance time past the polling delay, and note that we make an additional call to fetch the user time.Advance(TimeSpan.FromSeconds(2)); // t = 3 - persistentUserService.Received(1).GetPersistedUser(out Arg.Any()); - await fetchUserService.Received(1).FetchUserAsync(); + _ = persistentUserService.Received(1).GetPersistedUser(out Arg.Any()); + _ = await fetchUserService.Received(1).FetchUserAsync(); // Advance time within the polling interval, but more than the polling delay // We don't expect additional calls yet time.Advance(TimeSpan.FromSeconds(3)); // t = 6 - persistentUserService.Received(1).GetPersistedUser(out Arg.Any()); - await fetchUserService.Received(1).FetchUserAsync(); + _ = persistentUserService.Received(1).GetPersistedUser(out Arg.Any()); + _ = await fetchUserService.Received(1).FetchUserAsync(); // Advance time past the polling interval, and note that we make an additional call time.Advance(TimeSpan.FromSeconds(10)); // t = 16 - persistentUserService.Received(1).GetPersistedUser(out Arg.Any()); - await fetchUserService.Received(2).FetchUserAsync(); + _ = persistentUserService.Received(1).GetPersistedUser(out Arg.Any()); + _ = await fetchUserService.Received(2).FetchUserAsync(); } [Fact] @@ -114,13 +113,13 @@ public class BffClientAuthenticationStateProviderTests new Claim("name", expectedName), new Claim("source", "fetch") ], "pwd", "name", "role")); - persistentUserService.GetPersistedUser(out Arg.Any()) + _ = persistentUserService.GetPersistedUser(out Arg.Any()) .Returns(x => { x[0] = null; return true; }); - fetchUserService.FetchUserAsync().Returns(fetchedUser); + _ = fetchUserService.FetchUserAsync().Returns(fetchedUser); var sut = new BffClientAuthenticationStateProvider( fetchUserService, @@ -137,16 +136,16 @@ public class BffClientAuthenticationStateProviderTests authState.User.Identity?.IsAuthenticated.ShouldBeTrue(); authState.User.Identity?.Name.ShouldBe(expectedName); // We fail to get a persisted user and immediately start polling - persistentUserService.Received(1).GetPersistedUser(out Arg.Any()); - await fetchUserService.Received(1).FetchUserAsync(); + _ = persistentUserService.Received(1).GetPersistedUser(out Arg.Any()); + _ = await fetchUserService.Received(1).FetchUserAsync(); // Repeatedly advance time past the polling interval, and note that we make an additional call // each time. for (var i = 0; i < 10; i++) { time.Advance(TimeSpan.FromSeconds(10)); - persistentUserService.Received(1).GetPersistedUser(out Arg.Any()); - await fetchUserService.Received(i + 2).FetchUserAsync(); + _ = persistentUserService.Received(1).GetPersistedUser(out Arg.Any()); + _ = await fetchUserService.Received(i + 2).FetchUserAsync(); } } @@ -170,7 +169,7 @@ public class BffClientAuthenticationStateProviderTests new Claim("source", "fetch") ], "pwd", "name", "role")); - persistentUserService.GetPersistedUser(out Arg.Any()) + _ = persistentUserService.GetPersistedUser(out Arg.Any()) .Returns(x => { x[0] = persistedUser; @@ -178,7 +177,7 @@ public class BffClientAuthenticationStateProviderTests }); // Simulate that the user got logged out by first returning a mocked logged in user, // and then returning an anonymous user - userService.FetchUserAsync().Returns(fetchedUser, anonymousUser); + _ = userService.FetchUserAsync().Returns(fetchedUser, anonymousUser); var sut = new BffClientAuthenticationStateProvider( userService, @@ -187,17 +186,17 @@ public class BffClientAuthenticationStateProviderTests TestMocks.MockOptions(), Substitute.For>()); - var _ = await sut.GetAuthenticationStateAsync(); + _ = await sut.GetAuthenticationStateAsync(); time.Advance(TimeSpan.FromSeconds(5)); - persistentUserService.Received(1).GetPersistedUser(out Arg.Any()); - await userService.Received(1).FetchUserAsync(); + _ = persistentUserService.Received(1).GetPersistedUser(out Arg.Any()); + _ = await userService.Received(1).FetchUserAsync(); time.Advance(TimeSpan.FromSeconds(10)); - persistentUserService.Received(1).GetPersistedUser(out Arg.Any()); - await userService.Received(2).FetchUserAsync(); + _ = persistentUserService.Received(1).GetPersistedUser(out Arg.Any()); + _ = await userService.Received(2).FetchUserAsync(); time.Advance(TimeSpan.FromSeconds(50)); - persistentUserService.Received(1).GetPersistedUser(out Arg.Any()); - await userService.Received(2).FetchUserAsync(); + _ = persistentUserService.Received(1).GetPersistedUser(out Arg.Any()); + _ = await userService.Received(2).FetchUserAsync(); } } diff --git a/bff/test/Bff.Tests/Blazor/Client/FetchUserServiceTests.cs b/bff/test/Bff.Tests/Blazor/Client/FetchUserServiceTests.cs index 3f31bf19d..0366d575b 100644 --- a/bff/test/Bff.Tests/Blazor/Client/FetchUserServiceTests.cs +++ b/bff/test/Bff.Tests/Blazor/Client/FetchUserServiceTests.cs @@ -29,7 +29,7 @@ public class FetchUserServiceTests result.IsInRole("admin").ShouldBeTrue(); result.IsInRole("garbage").ShouldBeFalse(); - result.Identity.ShouldNotBeNull(); + _ = result.Identity.ShouldNotBeNull(); result.Identity.Name.ShouldBe("example-user"); result.FindFirst("foo").ShouldNotBeNull() .Value.ShouldBe("bar"); diff --git a/bff/test/Bff.Tests/Blazor/Client/ServiceCollectionExtensionsTests.cs b/bff/test/Bff.Tests/Blazor/Client/ServiceCollectionExtensionsTests.cs index b70a3ffd2..159f37bac 100644 --- a/bff/test/Bff.Tests/Blazor/Client/ServiceCollectionExtensionsTests.cs +++ b/bff/test/Bff.Tests/Blazor/Client/ServiceCollectionExtensionsTests.cs @@ -15,8 +15,8 @@ public class ServiceCollectionExtensionsTests public void When_base_address_option_is_set_AddBffBlazorClient_configures_HttpClient_base_address(string configuredRemoteAddress, string expectedBaseAddress) { var sut = new ServiceCollection(); - sut.AddBffBlazorClient(); - sut.Configure(opt => + _ = sut.AddBffBlazorClient(); + _ = sut.Configure(opt => { opt.StateProviderBaseAddress = configuredRemoteAddress; }); @@ -25,8 +25,8 @@ public class ServiceCollectionExtensionsTests var sp = sut.BuildServiceProvider(); var httpClientFactory = sp.GetService(); var httpClient = httpClientFactory?.CreateClient(BffClientAuthenticationStateProvider.HttpClientName); - httpClient.ShouldNotBeNull(); - httpClient.BaseAddress.ShouldNotBeNull(); + _ = httpClient.ShouldNotBeNull(); + _ = httpClient.BaseAddress.ShouldNotBeNull(); httpClient.BaseAddress.AbsoluteUri.ShouldBe(expectedBaseAddress); } @@ -36,8 +36,8 @@ public class ServiceCollectionExtensionsTests var expectedBaseAddress = "https://example.com/"; var sut = new ServiceCollection(); - sut.AddBffBlazorClient(); - sut.AddSingleton(new FakeWebAssemblyHostEnvironment() + _ = sut.AddBffBlazorClient(); + _ = sut.AddSingleton(new FakeWebAssemblyHostEnvironment() { BaseAddress = expectedBaseAddress }); @@ -45,8 +45,8 @@ public class ServiceCollectionExtensionsTests var sp = sut.BuildServiceProvider(); var httpClientFactory = sp.GetService(); var httpClient = httpClientFactory?.CreateClient(BffClientAuthenticationStateProvider.HttpClientName); - httpClient.ShouldNotBeNull(); - httpClient.BaseAddress.ShouldNotBeNull(); + _ = httpClient.ShouldNotBeNull(); + _ = httpClient.BaseAddress.ShouldNotBeNull(); httpClient.BaseAddress.AbsoluteUri.ShouldBe(expectedBaseAddress); } @@ -56,10 +56,10 @@ public class ServiceCollectionExtensionsTests { var sut = new ServiceCollection(); - sut.AddBffBlazorClient(); - sut.AddLocalApiHttpClient("clientName"); - sut.AddSingleton(new FakeWebAssemblyHostEnvironment()); - sut.Configure(opt => + _ = sut.AddBffBlazorClient(); + _ = sut.AddLocalApiHttpClient("clientName"); + _ = sut.AddSingleton(new FakeWebAssemblyHostEnvironment()); + _ = sut.Configure(opt => { opt.RemoteApiBaseAddress = "Should_not_be_used"; opt.RemoteApiPath = "should_not_be_used"; @@ -69,8 +69,8 @@ public class ServiceCollectionExtensionsTests var sp = sut.BuildServiceProvider(); var httpClientFactory = sp.GetService(); var httpClient = httpClientFactory?.CreateClient("clientName"); - httpClient.ShouldNotBeNull(); - httpClient.BaseAddress.ShouldNotBeNull(); + _ = httpClient.ShouldNotBeNull(); + _ = httpClient.BaseAddress.ShouldNotBeNull(); httpClient.BaseAddress.AbsoluteUri.ShouldBe(new FakeWebAssemblyHostEnvironment().BaseAddress); } @@ -93,9 +93,9 @@ public class ServiceCollectionExtensionsTests public void AddRemoteApiHttpClient_configures_HttpClient_base_address(string? configuredRemoteAddress, string? configuredRemotePath, string expectedBaseAddress) { var sut = new ServiceCollection(); - sut.AddBffBlazorClient(); - sut.AddRemoteApiHttpClient("clientName"); - sut.Configure(opt => + _ = sut.AddBffBlazorClient(); + _ = sut.AddRemoteApiHttpClient("clientName"); + _ = sut.Configure(opt => { if (configuredRemoteAddress != null) { @@ -111,8 +111,8 @@ public class ServiceCollectionExtensionsTests var sp = sut.BuildServiceProvider(); var httpClientFactory = sp.GetService(); var httpClient = httpClientFactory?.CreateClient("clientName"); - httpClient.ShouldNotBeNull(); - httpClient.BaseAddress.ShouldNotBeNull(); + _ = httpClient.ShouldNotBeNull(); + _ = httpClient.BaseAddress.ShouldNotBeNull(); httpClient.BaseAddress.AbsoluteUri.ShouldBe(expectedBaseAddress); } @@ -123,9 +123,9 @@ public class ServiceCollectionExtensionsTests var expectedBaseAddress = "https://example.com/remote-apis/"; var sut = new ServiceCollection(); - sut.AddBffBlazorClient(); - sut.AddRemoteApiHttpClient("clientName"); - sut.AddSingleton(new FakeWebAssemblyHostEnvironment() + _ = sut.AddBffBlazorClient(); + _ = sut.AddRemoteApiHttpClient("clientName"); + _ = sut.AddSingleton(new FakeWebAssemblyHostEnvironment() { BaseAddress = hostBaseAddress }); @@ -133,8 +133,8 @@ public class ServiceCollectionExtensionsTests var sp = sut.BuildServiceProvider(); var httpClientFactory = sp.GetService(); var httpClient = httpClientFactory?.CreateClient("clientName"); - httpClient.ShouldNotBeNull(); - httpClient.BaseAddress.ShouldNotBeNull(); + _ = httpClient.ShouldNotBeNull(); + _ = httpClient.BaseAddress.ShouldNotBeNull(); httpClient.BaseAddress.AbsoluteUri.ShouldBe(expectedBaseAddress); } @@ -145,9 +145,9 @@ public class ServiceCollectionExtensionsTests var expectedBaseAddress = "https://example.com/remote-apis/"; var sut = new ServiceCollection(); - sut.AddBffBlazorClient(); - sut.AddRemoteApiHttpClient("clientName", c => c.Timeout = TimeSpan.FromSeconds(321)); - sut.AddSingleton(new FakeWebAssemblyHostEnvironment() + _ = sut.AddBffBlazorClient(); + _ = sut.AddRemoteApiHttpClient("clientName", c => c.Timeout = TimeSpan.FromSeconds(321)); + _ = sut.AddSingleton(new FakeWebAssemblyHostEnvironment() { BaseAddress = hostBaseAddress }); @@ -155,8 +155,8 @@ public class ServiceCollectionExtensionsTests var sp = sut.BuildServiceProvider(); var httpClientFactory = sp.GetService(); var httpClient = httpClientFactory?.CreateClient("clientName"); - httpClient.ShouldNotBeNull(); - httpClient.BaseAddress.ShouldNotBeNull(); + _ = httpClient.ShouldNotBeNull(); + _ = httpClient.BaseAddress.ShouldNotBeNull(); httpClient.BaseAddress.AbsoluteUri.ShouldBe(expectedBaseAddress); httpClient.Timeout.ShouldBe(TimeSpan.FromSeconds(321)); } @@ -168,10 +168,10 @@ public class ServiceCollectionExtensionsTests var expectedBaseAddress = "https://example.com/remote-apis/"; var sut = new ServiceCollection(); - sut.AddBffBlazorClient(); - sut.AddTransient(); - sut.AddRemoteApiHttpClient(); - sut.AddSingleton(new FakeWebAssemblyHostEnvironment() + _ = sut.AddBffBlazorClient(); + _ = sut.AddTransient(); + _ = sut.AddRemoteApiHttpClient(); + _ = sut.AddSingleton(new FakeWebAssemblyHostEnvironment() { BaseAddress = hostBaseAddress }); @@ -179,8 +179,8 @@ public class ServiceCollectionExtensionsTests var sp = sut.BuildServiceProvider(); var wrapper = sp.GetService(); var httpClient = wrapper?.Client; - httpClient.ShouldNotBeNull(); - httpClient.BaseAddress.ShouldNotBeNull(); + _ = httpClient.ShouldNotBeNull(); + _ = httpClient.BaseAddress.ShouldNotBeNull(); httpClient.BaseAddress.AbsoluteUri.ShouldBe(expectedBaseAddress); } @@ -191,10 +191,10 @@ public class ServiceCollectionExtensionsTests var expectedBaseAddress = "https://example.com/remote-apis/"; var sut = new ServiceCollection(); - sut.AddBffBlazorClient(); - sut.AddTransient(); - sut.AddRemoteApiHttpClient(c => c.Timeout = TimeSpan.FromSeconds(321)); - sut.AddSingleton(new FakeWebAssemblyHostEnvironment() + _ = sut.AddBffBlazorClient(); + _ = sut.AddTransient(); + _ = sut.AddRemoteApiHttpClient(c => c.Timeout = TimeSpan.FromSeconds(321)); + _ = sut.AddSingleton(new FakeWebAssemblyHostEnvironment() { BaseAddress = hostBaseAddress }); @@ -202,8 +202,8 @@ public class ServiceCollectionExtensionsTests var sp = sut.BuildServiceProvider(); var wrapper = sp.GetService(); var httpClient = wrapper?.Client; - httpClient.ShouldNotBeNull(); - httpClient.BaseAddress.ShouldNotBeNull(); + _ = httpClient.ShouldNotBeNull(); + _ = httpClient.BaseAddress.ShouldNotBeNull(); httpClient.BaseAddress.AbsoluteUri.ShouldBe(expectedBaseAddress); httpClient.Timeout.ShouldBe(TimeSpan.FromSeconds(321)); } @@ -218,10 +218,10 @@ public class ServiceCollectionExtensionsTests { var expectedConfiguredValue = "some-path"; var sut = new ServiceCollection(); - sut.AddBffBlazorClient(opt => opt.RemoteApiPath = expectedConfiguredValue); + _ = sut.AddBffBlazorClient(opt => opt.RemoteApiPath = expectedConfiguredValue); var sp = sut.BuildServiceProvider(); var opts = sp.GetService>(); - opts.ShouldNotBeNull(); + _ = opts.ShouldNotBeNull(); opts.Value.RemoteApiPath.ShouldBe(expectedConfiguredValue); } } diff --git a/bff/test/Bff.Tests/Blazor/Client/TestMocks.cs b/bff/test/Bff.Tests/Blazor/Client/TestMocks.cs index 2d2af31d1..1320bf354 100644 --- a/bff/test/Bff.Tests/Blazor/Client/TestMocks.cs +++ b/bff/test/Bff.Tests/Blazor/Client/TestMocks.cs @@ -19,14 +19,14 @@ public static class TestMocks BaseAddress = new Uri("https://example.com") }; var factory = Substitute.For(); - factory.CreateClient(BffClientAuthenticationStateProvider.HttpClientName).Returns(httpClient); + _ = factory.CreateClient(BffClientAuthenticationStateProvider.HttpClientName).Returns(httpClient); return factory; } public static IOptions MockOptions(BffBlazorClientOptions? opt = null) { var result = Substitute.For>(); - result.Value.Returns(opt ?? new BffBlazorClientOptions()); + _ = result.Value.Returns(opt ?? new BffBlazorClientOptions()); return result; } } diff --git a/bff/test/Bff.Tests/Configuration/BffBuilderTests.cs b/bff/test/Bff.Tests/Configuration/BffBuilderTests.cs index 7d62c2b98..6a4671e43 100644 --- a/bff/test/Bff.Tests/Configuration/BffBuilderTests.cs +++ b/bff/test/Bff.Tests/Configuration/BffBuilderTests.cs @@ -27,7 +27,7 @@ public class BffBuilderTests { Name = BffFrontendName.Parse("different") }; - services.AddBff() + _ = services.AddBff() .AddFrontends(frontend1, frontend2); var provider = services.BuildServiceProvider(); @@ -46,7 +46,7 @@ public class BffBuilderTests { Name = BffFrontendName.Parse("different") }; - services.AddBff() + _ = services.AddBff() .AddFrontends(frontend1) .AddFrontends(frontend2); @@ -71,7 +71,7 @@ public class BffBuilderTests .Build(); var services = new ServiceCollection(); - services.AddBff() + _ = services.AddBff() .LoadConfiguration(configuration); var provider = services.BuildServiceProvider(); var frontends = provider.GetRequiredService(); @@ -120,7 +120,7 @@ public class BffBuilderTests .Build(); var services = new ServiceCollection(); - services.AddBff() + _ = services.AddBff() .AddRemoteApis() .LoadConfiguration(configuration); var provider = services.BuildServiceProvider(); @@ -150,7 +150,7 @@ public class BffBuilderTests .Build(); var services = new ServiceCollection(); - services.AddBff().LoadConfiguration(configuration); + _ = services.AddBff().LoadConfiguration(configuration); var provider = services.BuildServiceProvider(); var frontends = provider.GetRequiredService(); frontends.Count.ShouldBe(1); @@ -191,9 +191,9 @@ public class BffBuilderTests // Wire up the BFF var services = new ServiceCollection(); - services + _ = services .AddSingleton(); // We need the http context to set the scope - services.AddBff().LoadConfiguration(configuration); + _ = services.AddBff().LoadConfiguration(configuration); var provider = services.BuildServiceProvider(); var frontends = provider.GetRequiredService(); frontends.Count.ShouldBe(1); @@ -240,9 +240,9 @@ public class BffBuilderTests // Wire up the BFF var services = new ServiceCollection(); - services + _ = services .AddSingleton(); // We need the http context to set the scope - services.AddBff().LoadConfiguration(configuration); + _ = services.AddBff().LoadConfiguration(configuration); var provider = services.BuildServiceProvider(); var frontends = provider.GetRequiredService(); frontends.Count.ShouldBe(1); @@ -315,7 +315,7 @@ public class BffBuilderTests .Build(); var services = new ServiceCollection(); - services.AddBff() + _ = services.AddBff() .LoadConfiguration(configuration) .AddRemoteApis(); var provider = services.BuildServiceProvider(); @@ -362,7 +362,7 @@ public class BffBuilderTests }); var services = new ServiceCollection(); - services.AddBff().LoadConfiguration(configFile.Configuration); + _ = services.AddBff().LoadConfiguration(configFile.Configuration); var provider = services.BuildServiceProvider(); var frontends = provider.GetRequiredService(); frontends.Count.ShouldBe(2); @@ -408,12 +408,12 @@ public class BffBuilderTests }); var services = new ServiceCollection(); - services.AddBff().LoadConfiguration(configFile.Configuration); + _ = services.AddBff().LoadConfiguration(configFile.Configuration); var provider = services.BuildServiceProvider(); var optionsCache = provider.GetRequiredService>(); - optionsCache.TryAdd("to_be_removed", new OpenIdConnectOptions()); - optionsCache.TryAdd("to_be_updated", new OpenIdConnectOptions()); + _ = optionsCache.TryAdd("to_be_removed", new OpenIdConnectOptions()); + _ = optionsCache.TryAdd("to_be_updated", new OpenIdConnectOptions()); var frontends = provider.GetRequiredService(); @@ -451,8 +451,8 @@ public class BffBuilderTests .Build(); var services = new ServiceCollection(); - services.AddSingleton(); - services.AddBff().LoadConfiguration(configuration); + _ = services.AddSingleton(); + _ = services.AddBff().LoadConfiguration(configuration); var provider = services.BuildServiceProvider(); var factory = provider.GetRequiredService>(); @@ -473,8 +473,8 @@ public class BffBuilderTests .Build(); var services = new ServiceCollection(); - services.AddSingleton(); - services.AddBff().LoadConfiguration(configuration); + _ = services.AddSingleton(); + _ = services.AddBff().LoadConfiguration(configuration); var provider = services.BuildServiceProvider(); var factory = provider.GetRequiredService>(); @@ -516,10 +516,10 @@ public class BffBuilderTests .Build(); var services = new ServiceCollection(); - services.AddBff().LoadConfiguration(configuration); + _ = services.AddBff().LoadConfiguration(configuration); var provider = services.BuildServiceProvider(); - Should.Throw(() => provider.GetRequiredService>().Value); + _ = Should.Throw(() => provider.GetRequiredService>().Value); } [Fact] @@ -527,7 +527,7 @@ public class BffBuilderTests { var services = new ServiceCollection(); - Should.Throw(() => services.AddBff() + _ = Should.Throw(() => services.AddBff() .AddFrontends(Some.BffFrontend(), Some.BffFrontend())) ; } diff --git a/bff/test/Bff.Tests/Configuration/ConfigBindingTests.cs b/bff/test/Bff.Tests/Configuration/ConfigBindingTests.cs index 950c86131..89de9581d 100644 --- a/bff/test/Bff.Tests/Configuration/ConfigBindingTests.cs +++ b/bff/test/Bff.Tests/Configuration/ConfigBindingTests.cs @@ -31,8 +31,8 @@ public class OptionsMonitorExplorationTests // Important: I'm binding two classes to the same IConfiguration instance // The different classes are mapped to the same data. - builder.Services.Configure(builder.Configuration); - builder.Services.Configure(builder.Configuration); + _ = builder.Services.Configure(builder.Configuration); + _ = builder.Services.Configure(builder.Configuration); using var host = builder.Build(); @@ -43,7 +43,7 @@ public class OptionsMonitorExplorationTests // Count for each data what the number of items is when the first monitor changes. var countMyConfig1 = 0; var countMyConfig2 = 0; - monitor1.OnChange(c => + _ = monitor1.OnChange(c => { countMyConfig1 = c.Items.Count; countMyConfig2 = monitor2.CurrentValue.Items.Count; @@ -52,7 +52,7 @@ public class OptionsMonitorExplorationTests // Now we load a single data item and trigger a (single) reload. provider.LoadDataWithOneItem(); provider.Reload(); - Task.Delay(200); + _ = Task.Delay(200); // After first reload both monitors have 1 item. countMyConfig1.ShouldBe(1); @@ -61,7 +61,7 @@ public class OptionsMonitorExplorationTests // Now reload the configuration, but with two items provider.LoadDataWithSecondItem(); provider.Reload(); - Task.Delay(200); + _ = Task.Delay(200); // The first config is updated (as expected) countMyConfig1.ShouldBe(2); @@ -75,7 +75,7 @@ public class OptionsMonitorExplorationTests // A second reload now causes both providers to be reloaded. customConfigurationSource.Provider.Reload(); - Task.Delay(200); + _ = Task.Delay(200); // and now the options monitors for BOTH are updated. countMyConfig1.ShouldBe(2); @@ -158,7 +158,7 @@ public class ConfigBindingTests : BffTestBase public async Task Can_load_remote_apis_at_runtime_from_multiple_config_sources() { var folder = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); - Directory.CreateDirectory(folder); + _ = Directory.CreateDirectory(folder); @@ -214,9 +214,9 @@ public class ConfigBindingTests : BffTestBase Bff.OnConfigureBff += bff => { - bff.LoadConfiguration(config); + _ = bff.LoadConfiguration(config); - bff.AddRemoteApis(); + _ = bff.AddRemoteApis(); }; diff --git a/bff/test/Bff.Tests/ConventionTests.cs b/bff/test/Bff.Tests/ConventionTests.cs index 99488431e..c88d2548c 100644 --- a/bff/test/Bff.Tests/ConventionTests.cs +++ b/bff/test/Bff.Tests/ConventionTests.cs @@ -55,7 +55,7 @@ public class ConventionTests foreach (var type in stringValueTypes) { type.IsValueType.ShouldBeTrue($"{type.Name} should be a value type (struct)."); - type.IsDefined(typeof(System.Runtime.CompilerServices.IsReadOnlyAttribute)); + _ = type.IsDefined(typeof(System.Runtime.CompilerServices.IsReadOnlyAttribute)); } } @@ -81,7 +81,7 @@ public class ConventionTests { // Find the public constructor that takes a single string parameter var ctor = type.GetConstructor([]); - ctor.ShouldNotBeNull($"{type.Name} should have a public parameterless constructor."); + _ = ctor.ShouldNotBeNull($"{type.Name} should have a public parameterless constructor."); // Try to invoke the constructor with a value and expect an exception var ex = Should.Throw(() => ctor.Invoke([])); @@ -108,7 +108,7 @@ public class ConventionTests c.IsPublic && c.GetParameters().Length == 0); - publicParameterlessCtor.ShouldNotBeNull($"{type.Name} should have a public parameterless constructor."); + _ = publicParameterlessCtor.ShouldNotBeNull($"{type.Name} should have a public parameterless constructor."); // Find the private constructor with a single string parameter var privateStringCtor = ctors.FirstOrDefault(c => @@ -116,7 +116,7 @@ public class ConventionTests c.GetParameters().Length == 1 && c.GetParameters()[0].ParameterType == typeof(string)); - privateStringCtor.ShouldNotBeNull( + _ = privateStringCtor.ShouldNotBeNull( $"{type.Name} should have a private constructor with a single string parameter."); } } diff --git a/bff/test/Bff.Tests/Endpoints/DPoPRemoteEndpointTests.cs b/bff/test/Bff.Tests/Endpoints/DPoPRemoteEndpointTests.cs index a42c9e58f..2b80255a7 100644 --- a/bff/test/Bff.Tests/Endpoints/DPoPRemoteEndpointTests.cs +++ b/bff/test/Bff.Tests/Endpoints/DPoPRemoteEndpointTests.cs @@ -33,18 +33,18 @@ public class DPoPRemoteEndpointTests : BffTestBase { Api.OnConfigureServices += services => { - services.ConfigureDPoPTokensForScheme("token"); + _ = services.ConfigureDPoPTokensForScheme("token"); }; Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url()) + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url()) .WithAccessToken(RequiredTokenType.User); }; await InitializeAsync(); - await Bff.BrowserClient.Login() + _ = await Bff.BrowserClient.Login() .CheckHttpStatusCode(); ApiCallDetails callToApi = await Bff.BrowserClient.CallBffHostApi( @@ -61,12 +61,12 @@ public class DPoPRemoteEndpointTests : BffTestBase { Api.OnConfigureServices += services => { - services.ConfigureDPoPTokensForScheme("token"); + _ = services.ConfigureDPoPTokensForScheme("token"); }; Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url()) + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url()) .WithAccessToken(RequiredTokenType.Client); }; @@ -89,12 +89,12 @@ public class DPoPRemoteEndpointTests : BffTestBase { Api.OnConfigureServices += services => { - services.ConfigureDPoPTokensForScheme("token"); + _ = services.ConfigureDPoPTokensForScheme("token"); }; Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(mappedPath, Api.Url(targetPath)) + _ = app.MapRemoteBffApiEndpoint(mappedPath, Api.Url(targetPath)) .WithAccessToken(RequiredTokenType.Client); }; @@ -122,12 +122,12 @@ public class DPoPRemoteEndpointTests : BffTestBase Api.OnConfigureServices += services => { - services.ConfigureDPoPTokensForScheme("token"); + _ = services.ConfigureDPoPTokensForScheme("token"); }; Api.OnConfigureApp += app => { - app.Use(async (context, next) => + _ = app.Use(async (context, next) => { capturedDPoPHeader = context.Request.Headers["DPoP"].FirstOrDefault(); capturedRequestPath = context.Request.Path.Value; @@ -138,7 +138,7 @@ public class DPoPRemoteEndpointTests : BffTestBase Bff.OnConfigureApp += app => { // Map BFF /api/foo to API https://localhost:port/api/foo - app.MapRemoteBffApiEndpoint("/api/foo", Api.Url("api/foo")) + _ = app.MapRemoteBffApiEndpoint("/api/foo", Api.Url("api/foo")) .WithAccessToken(RequiredTokenType.Client); }; diff --git a/bff/test/Bff.Tests/Endpoints/DPoPTestsWithManualAuthentication.cs b/bff/test/Bff.Tests/Endpoints/DPoPTestsWithManualAuthentication.cs index 6b4d0dcad..73db801c9 100644 --- a/bff/test/Bff.Tests/Endpoints/DPoPTestsWithManualAuthentication.cs +++ b/bff/test/Bff.Tests/Endpoints/DPoPTestsWithManualAuthentication.cs @@ -21,7 +21,7 @@ public class DPoPTestsWithManualAuthentication : BffTestBase, IAsyncLifetime Bff.OnConfigureServices += services => { - services.AddAuthentication(opt => + _ = services.AddAuthentication(opt => { opt.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; opt.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; @@ -38,7 +38,7 @@ public class DPoPTestsWithManualAuthentication : BffTestBase, IAsyncLifetime Bff.OnConfigureBff += bff => bff.AddRemoteApis(); Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url()) + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url()) .WithAccessToken(RequiredTokenType.Client) ; }; @@ -48,9 +48,9 @@ public class DPoPTestsWithManualAuthentication : BffTestBase, IAsyncLifetime } [Fact] + //// Can login with dpop doesn't work public async Task When_logging_in_then_dpop_is_sent() => - //// Can login with dpop doesn't work - await Bff.BrowserClient.Login() + _ = await Bff.BrowserClient.Login() .CheckHttpStatusCode(); [Fact] diff --git a/bff/test/Bff.Tests/Endpoints/LocalEndpointTests.cs b/bff/test/Bff.Tests/Endpoints/LocalEndpointTests.cs index 88ebbbd99..40d6a1015 100644 --- a/bff/test/Bff.Tests/Endpoints/LocalEndpointTests.cs +++ b/bff/test/Bff.Tests/Endpoints/LocalEndpointTests.cs @@ -18,14 +18,14 @@ public class LocalEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => LocalApiResponseStatus)) + _ = app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => LocalApiResponseStatus)) .RequireAuthorization() .AsBffApiEndpoint(); }; await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.Path) @@ -42,14 +42,14 @@ public class LocalEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => LocalApiResponseStatus)) + _ = app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => LocalApiResponseStatus)) .RequireAuthorization() .SkipAntiforgery() .AsBffApiEndpoint(); }; await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.Path), @@ -67,7 +67,7 @@ public class LocalEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => LocalApiResponseStatus)) + _ = app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => LocalApiResponseStatus)) .RequireAuthorization() .AsBffApiEndpoint(); }; @@ -88,7 +88,7 @@ public class LocalEndpointTests : BffTestBase Bff.OnConfigureApp += app => { - app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => LocalApiResponseStatus)) + _ = app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => LocalApiResponseStatus)) .AsBffApiEndpoint(); }; @@ -108,7 +108,7 @@ public class LocalEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => LocalApiResponseStatus)) + _ = app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => LocalApiResponseStatus)) .SkipAntiforgery() .AsBffApiEndpoint(); }; @@ -130,7 +130,7 @@ public class LocalEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => LocalApiResponseStatus)) + _ = app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => LocalApiResponseStatus)) .AsBffApiEndpoint(); }; await ConfigureBff(setup); @@ -150,14 +150,14 @@ public class LocalEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => LocalApiResponseStatus)) + _ = app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => LocalApiResponseStatus)) .AsBffApiEndpoint(); }; await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.Path), @@ -178,7 +178,7 @@ public class LocalEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => LocalApiResponseStatus)) + _ = app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => LocalApiResponseStatus)) .RequireAuthorization(); }; await ConfigureBff(setup); @@ -204,7 +204,7 @@ public class LocalEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => LocalApiResponseStatus)) + _ = app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => LocalApiResponseStatus)) .RequireAuthorization() .AsBffApiEndpoint(); }; @@ -226,7 +226,7 @@ public class LocalEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => LocalApiResponseStatus)) + _ = app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => LocalApiResponseStatus)) .RequireAuthorization() .AsBffApiEndpoint(); }; @@ -234,7 +234,7 @@ public class LocalEndpointTests : BffTestBase await ConfigureBff(setup); LocalApiResponseStatus = HttpStatusCode.Forbidden; - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); Bff.BrowserClient.RedirectHandler.AutoFollowRedirects = false; var response = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.Path), @@ -248,7 +248,7 @@ public class LocalEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.MapGet(The.Path, c => c.ChallengeAsync()) + _ = app.MapGet(The.Path, c => c.ChallengeAsync()) .RequireAuthorization() .AsBffApiEndpoint(); }; @@ -257,7 +257,7 @@ public class LocalEndpointTests : BffTestBase - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); var response = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.Path), @@ -271,7 +271,7 @@ public class LocalEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.MapGet(The.Path, c => c.ChallengeAsync()) + _ = app.MapGet(The.Path, c => c.ChallengeAsync()) .RequireAuthorization() .AsBffApiEndpoint() .SkipResponseHandling(); @@ -281,7 +281,7 @@ public class LocalEndpointTests : BffTestBase - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); Bff.BrowserClient.RedirectHandler.AutoFollowRedirects = false; var response = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.Path), @@ -296,7 +296,7 @@ public class LocalEndpointTests : BffTestBase Bff.OnConfigureServices += svcs => { - svcs.AddAuthorization(opts => + _ = svcs.AddAuthorization(opts => { opts.FallbackPolicy = new Microsoft.AspNetCore.Authorization.AuthorizationPolicyBuilder() @@ -317,7 +317,7 @@ public class LocalEndpointTests : BffTestBase { var identityServer = new IdentityServerTestHost(Context); var bff = new BffTestHost(Context, identityServer); - identityServer.AddClient(The.ClientId, bff.Url()); + _ = identityServer.AddClient(The.ClientId, bff.Url()); bff.OnConfigureBffOptions += opt => { @@ -345,11 +345,11 @@ public class LocalEndpointTests : BffTestBase bff.OnConfigureApp += app => { - app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => LocalApiResponseStatus)) + _ = app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c, () => LocalApiResponseStatus)) .RequireAuthorization(policy => { - policy.RequireAuthenticatedUser(); - policy.RequireClaim("given_name", "Bob"); // Alice won't have this claim + _ = policy.RequireAuthenticatedUser(); + _ = policy.RequireClaim("given_name", "Bob"); // Alice won't have this claim }) .AsBffApiEndpoint(); }; @@ -357,10 +357,10 @@ public class LocalEndpointTests : BffTestBase await identityServer.InitializeAsync(); await bff.InitializeAsync(); - await bff.BrowserClient.Login(); + _ = await bff.BrowserClient.Login(); bff.BrowserClient.RedirectHandler.AutoFollowRedirects = false; - await bff.BrowserClient.CallBffHostApi( + _ = await bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.Path), expectedStatusCode: HttpStatusCode.Forbidden ); diff --git a/bff/test/Bff.Tests/Endpoints/Management/BackchannelLogoutEndpointTests.cs b/bff/test/Bff.Tests/Endpoints/Management/BackchannelLogoutEndpointTests.cs index 7ba656db2..2bc51551f 100644 --- a/bff/test/Bff.Tests/Endpoints/Management/BackchannelLogoutEndpointTests.cs +++ b/bff/test/Bff.Tests/Endpoints/Management/BackchannelLogoutEndpointTests.cs @@ -12,7 +12,7 @@ public class BackchannelLogoutEndpointTests : BffTestBase { public BackchannelLogoutEndpointTests() : base() => Bff.OnConfigureBff += bff => { - bff.AddServerSideSessions(); + _ = bff.AddServerSideSessions(); }; public override async ValueTask InitializeAsync() @@ -32,7 +32,7 @@ public class BackchannelLogoutEndpointTests : BffTestBase { Bff.OnConfigureServices += svcs => { - svcs.AddAuthorization(opts => + _ = svcs.AddAuthorization(opts => { opts.FallbackPolicy = new Microsoft.AspNetCore.Authorization.AuthorizationPolicyBuilder() @@ -43,7 +43,7 @@ public class BackchannelLogoutEndpointTests : BffTestBase await ConfigureBff(setup); // if you call the endpoint without a token, it should return 400 - await Bff.BrowserClient.PostAsync(Bff.Url("/bff/backchannel"), null) + _ = await Bff.BrowserClient.PostAsync(Bff.Url("/bff/backchannel"), null) .CheckHttpStatusCode(HttpStatusCode.BadRequest); } @@ -53,7 +53,7 @@ public class BackchannelLogoutEndpointTests : BffTestBase { await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); await Bff.BrowserClient.RevokeIdentityServerSession(); @@ -68,7 +68,7 @@ public class BackchannelLogoutEndpointTests : BffTestBase await Bff.BrowserClient.CreateIdentityServerSessionCookieAsync(IdentityServer, The.Sub, The.Sid); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); await Bff.BrowserClient.CreateIdentityServerSessionCookieAsync(IdentityServer, "different_sub", The.Sid); @@ -83,7 +83,7 @@ public class BackchannelLogoutEndpointTests : BffTestBase { await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); await Bff.BrowserClient.CreateIdentityServerSessionCookieAsync(IdentityServer, The.Sub, "different_sid"); @@ -103,14 +103,14 @@ public class BackchannelLogoutEndpointTests : BffTestBase await Bff.BrowserClient.CreateIdentityServerSessionCookieAsync(IdentityServer, The.Sub, The.Sid); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); // Set a Set-Cookie header to clear the "__Host-bff-auth" cookie Bff.BrowserClient.Cookies.Clear(Bff.Url()); await Bff.BrowserClient.CreateIdentityServerSessionCookieAsync(IdentityServer, The.Sub, "different"); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); (await GetUserSessions()).Count.ShouldBe(2); @@ -153,14 +153,14 @@ public class BackchannelLogoutEndpointTests : BffTestBase await Bff.BrowserClient.CreateIdentityServerSessionCookieAsync(IdentityServer, The.Sub, The.Sid); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); // Set a Set-Cookie header to clear the "__Host-bff-auth" cookie Bff.BrowserClient.Cookies.Clear(Bff.Url()); await Bff.BrowserClient.CreateIdentityServerSessionCookieAsync(IdentityServer, The.Sub, "different"); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); (await GetUserSessions()).Count.ShouldBe(2); diff --git a/bff/test/Bff.Tests/Endpoints/Management/LoginEndpointTests.cs b/bff/test/Bff.Tests/Endpoints/Management/LoginEndpointTests.cs index 92f2e8e20..0564be8cc 100644 --- a/bff/test/Bff.Tests/Endpoints/Management/LoginEndpointTests.cs +++ b/bff/test/Bff.Tests/Endpoints/Management/LoginEndpointTests.cs @@ -22,7 +22,7 @@ public class LoginEndpointTests : BffTestBase Bff.OnConfigureServices += svcs => { - svcs.AddAuthorization(opts => + _ = svcs.AddAuthorization(opts => { opts.FallbackPolicy = new Microsoft.AspNetCore.Authorization.AuthorizationPolicyBuilder() @@ -56,7 +56,7 @@ public class LoginEndpointTests : BffTestBase { await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); var response = await Bff.BrowserClient.GetAsync(Bff.Url("/bff/silent-login?redirectUri=/")) .CheckHttpStatusCode(); @@ -76,7 +76,7 @@ public class LoginEndpointTests : BffTestBase { await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); var response = await Bff.BrowserClient.GetAsync(Bff.Url("/bff/login?prompt=none")) .CheckHttpStatusCode(); @@ -138,12 +138,12 @@ public class LoginEndpointTests : BffTestBase { Bff.OnConfigureServices += svcs => { - svcs.Configure(options => { options.ManagementBasePath = "/custom/bff"; }); + _ = svcs.Configure(options => { options.ManagementBasePath = "/custom/bff"; }); }; await ConfigureBff(setup); - await Bff.BrowserClient.Login(expectedStatusCode: HttpStatusCode.NotFound); + _ = await Bff.BrowserClient.Login(expectedStatusCode: HttpStatusCode.NotFound); var response = await Bff.BrowserClient.Login("/custom"); response.RequestMessage!.RequestUri.ShouldBe(Bff.Url("/")); @@ -156,13 +156,13 @@ public class LoginEndpointTests : BffTestBase { Bff.OnConfigureServices += svcs => { - svcs.Configure(options => { options.ManagementBasePath = "/custom/bff/"; }); + _ = svcs.Configure(options => { options.ManagementBasePath = "/custom/bff/"; }); }; await ConfigureBff(setup); - await Bff.BrowserClient.Login(expectedStatusCode: HttpStatusCode.NotFound); + _ = await Bff.BrowserClient.Login(expectedStatusCode: HttpStatusCode.NotFound); var response = await Bff.BrowserClient.Login("/custom"); response.RequestMessage!.RequestUri.ShouldBe(Bff.Url("/")); @@ -174,7 +174,7 @@ public class LoginEndpointTests : BffTestBase { Bff.OnConfigureServices += svcs => { - svcs.Configure(options => { options.ManagementBasePath = "/"; }); + _ = svcs.Configure(options => { options.ManagementBasePath = "/"; }); }; await ConfigureBff(setup); @@ -191,7 +191,7 @@ public class LoginEndpointTests : BffTestBase { await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); // Disable auto redirects, to see if we get a challenge Bff.BrowserClient.RedirectHandler.AutoFollowRedirects = false; @@ -235,7 +235,7 @@ public class LoginEndpointTests : BffTestBase await ConfigureBff(setup); Bff.BffOptions.AllowedSilentLoginReferers.Add("https://allowed.com"); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); Bff.BrowserClient.DefaultRequestHeaders.Add("Referer", "https://ALLOWED.com"); @@ -260,9 +260,9 @@ public class LoginEndpointTests : BffTestBase await ConfigureBff(setup); Bff.BffOptions.AllowedSilentLoginReferers.Add("https://allowed.com"); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); - await Bff.BrowserClient.GetAsync(Bff.Url("/bff/login?prompt=none")) + _ = await Bff.BrowserClient.GetAsync(Bff.Url("/bff/login?prompt=none")) .CheckHttpStatusCode(HttpStatusCode.BadRequest); } @@ -275,10 +275,10 @@ public class LoginEndpointTests : BffTestBase await ConfigureBff(setup); Bff.BffOptions.AllowedSilentLoginReferers.Add("https://allowed.com"); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); Bff.BrowserClient.DefaultRequestHeaders.Add("Referer", "https://not_allowed.com"); - await Bff.BrowserClient.GetAsync(Bff.Url("/bff/login?prompt=none")) + _ = await Bff.BrowserClient.GetAsync(Bff.Url("/bff/login?prompt=none")) .CheckHttpStatusCode(HttpStatusCode.BadRequest); } } diff --git a/bff/test/Bff.Tests/Endpoints/Management/LogoutEndpointTests.cs b/bff/test/Bff.Tests/Endpoints/Management/LogoutEndpointTests.cs index 03fafbbf3..e891c9926 100644 --- a/bff/test/Bff.Tests/Endpoints/Management/LogoutEndpointTests.cs +++ b/bff/test/Bff.Tests/Endpoints/Management/LogoutEndpointTests.cs @@ -16,7 +16,7 @@ public class LogoutEndpointTests : BffTestBase { Bff.OnConfigureServices += svcs => { - svcs.AddAuthorization(opts => + _ = svcs.AddAuthorization(opts => { opts.FallbackPolicy = new Microsoft.AspNetCore.Authorization.AuthorizationPolicyBuilder() @@ -37,7 +37,7 @@ public class LogoutEndpointTests : BffTestBase { await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); var response = await Bff.BrowserClient.Logout(); response.StatusCode.ShouldBe(HttpStatusCode.OK); @@ -51,7 +51,7 @@ public class LogoutEndpointTests : BffTestBase public async Task logout_endpoint_for_authenticated_should_require_sid(BffSetupType setup) { await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); var problem = await Bff.BrowserClient.GetAsync(Bff.Url("/bff/logout")) .ShouldBeProblem(); @@ -67,7 +67,7 @@ public class LogoutEndpointTests : BffTestBase BffSetupType setup) { await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); Bff.BffOptions.RequireLogoutSessionId = false; Bff.BrowserClient.RedirectHandler.AutoFollowRedirects = false; @@ -85,7 +85,7 @@ public class LogoutEndpointTests : BffTestBase // Workaround to place a session cookie in the BFF without a session id claim. Bff.OnConfigureApp += app => { - app.MapGet("/__signin", async ctx => + _ = app.MapGet("/__signin", async ctx => { var props = new AuthenticationProperties(); await ctx.SignInAsync( @@ -97,7 +97,7 @@ public class LogoutEndpointTests : BffTestBase }; await ConfigureBff(setup); - await Bff.BrowserClient.GetAsync("__signin"); + _ = await Bff.BrowserClient.GetAsync("__signin"); // workaround for RevokeUserRefreshTokenAsync throwing when no RT in session Bff.BffOptions.RevokeRefreshTokenOnLogout = false; @@ -129,10 +129,10 @@ public class LogoutEndpointTests : BffTestBase public async Task can_logout_twice(BffSetupType setup) { await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); var sid = await Bff.BrowserClient.GetSid(); - await Bff.BrowserClient.Logout(sid) + _ = await Bff.BrowserClient.Logout(sid) .CheckHttpStatusCode(); Bff.BrowserClient.RedirectHandler.AutoFollowRedirects = false; @@ -154,7 +154,7 @@ public class LogoutEndpointTests : BffTestBase Bff.OnConfigureApp += app => app.MapGet("/foo", () => "foo'd you"); await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); var response = await Bff.BrowserClient.Logout(returnUrl: new Uri("/foo", UriKind.Relative)) .CheckHttpStatusCode(); @@ -167,7 +167,7 @@ public class LogoutEndpointTests : BffTestBase public async Task logout_endpoint_should_reject_non_local_returnUrl(BffSetupType setup) { await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); var problem = await Bff.BrowserClient.Logout(returnUrl: new Uri("https://foo")) .ShouldBeProblem(); diff --git a/bff/test/Bff.Tests/Endpoints/Management/ManagementBasePathTests.cs b/bff/test/Bff.Tests/Endpoints/Management/ManagementBasePathTests.cs index 83f41d9c0..d6b6aa769 100644 --- a/bff/test/Bff.Tests/Endpoints/Management/ManagementBasePathTests.cs +++ b/bff/test/Bff.Tests/Endpoints/Management/ManagementBasePathTests.cs @@ -20,7 +20,7 @@ public class ManagementBasePathTests : BffTestBase { Bff.OnConfigureServices += svcs => { - svcs.Configure(options => + _ = svcs.Configure(options => { options.ManagementBasePath = new PathString("/{path:regex(^[a-zA-Z\\d-]+$)}/bff"); }); diff --git a/bff/test/Bff.Tests/Endpoints/Management/UserEndpointTests.cs b/bff/test/Bff.Tests/Endpoints/Management/UserEndpointTests.cs index 0aa7b554f..ca997736c 100644 --- a/bff/test/Bff.Tests/Endpoints/Management/UserEndpointTests.cs +++ b/bff/test/Bff.Tests/Endpoints/Management/UserEndpointTests.cs @@ -20,7 +20,7 @@ public class UserEndpointTests : BffTestBase { // Setup a login endpoint that allows you to simulate signing in as a specific // user in the BFF. - app.MapGet("/__signin", async ctx => + _ = app.MapGet("/__signin", async ctx => { var props = new AuthenticationProperties(); await ctx.SignInAsync(UserToSignIn!, props); @@ -59,14 +59,14 @@ public class UserEndpointTests : BffTestBase Bff.OnConfigureServices += services => { // We're adding an AccessTokenManagement HTTP Client that can access the API Endpoint. - services.AddUserAccessTokenHttpClient("c1", + _ = services.AddUserAccessTokenHttpClient("c1", configureClient: client => { client.BaseAddress = Api.Url(); }).ConfigurePrimaryHttpMessageHandler(() => Internet); // Then we're adding the claims enricher that will call the endpoint. - services.AddSingleton(); + _ = services.AddSingleton(); }; Bff.OnConfigureBff += bff => bff.ConfigureOpenIdConnect(opt => @@ -80,7 +80,7 @@ public class UserEndpointTests : BffTestBase await InitializeAsync(); AddCustomUserClaims(new Claim("foo", "foo1"), new Claim("foo", "foo2")); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); var data = await Bff.BrowserClient.CallUserEndpointAsync(); @@ -99,7 +99,7 @@ public class UserEndpointTests : BffTestBase await ConfigureBff(setup); AddCustomUserClaims(new Claim("foo", "foo1"), new Claim("foo", "foo2")); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); var data = await Bff.BrowserClient.CallUserEndpointAsync(); @@ -124,7 +124,7 @@ public class UserEndpointTests : BffTestBase new Claim("sid", "123"), ], "test", "name", "role")); - await Bff.BrowserClient.GetAsync("/__signin"); + _ = await Bff.BrowserClient.GetAsync("/__signin"); var data = await Bff.BrowserClient.CallUserEndpointAsync(); diff --git a/bff/test/Bff.Tests/Endpoints/RemoteEndpointTests.cs b/bff/test/Bff.Tests/Endpoints/RemoteEndpointTests.cs index 18306181e..26f36903d 100644 --- a/bff/test/Bff.Tests/Endpoints/RemoteEndpointTests.cs +++ b/bff/test/Bff.Tests/Endpoints/RemoteEndpointTests.cs @@ -28,7 +28,7 @@ public class RemoteEndpointTests : BffTestBase Bff.OnConfigureServices += services => { // Add a custom default transform that adds a header to the request - services.AddSingleton(CustomDefaultBffTransformBuilder); + _ = services.AddSingleton(CustomDefaultBffTransformBuilder); }; Bff.OnConfigureBff += bff => bff.AddRemoteApis(); @@ -36,7 +36,7 @@ public class RemoteEndpointTests : BffTestBase private void CustomDefaultBffTransformBuilder(string localpath, TransformBuilderContext context) { - context.AddResponseHeader("added-by-custom-default-transform", "some-value"); + _ = context.AddResponseHeader("added-by-custom-default-transform", "some-value"); DefaultBffYarpTransformerBuilders.DirectProxyWithAccessToken(localpath, context); } @@ -46,12 +46,12 @@ public class RemoteEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) .WithAccessToken(); }; await ConfigureBff(setup); - await Bff.BrowserClient.CallBffHostApi( + _ = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.Path), expectedStatusCode: HttpStatusCode.Unauthorized ); @@ -63,12 +63,12 @@ public class RemoteEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) .WithAccessToken(); }; await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); var (response, apiResult) = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.Path) @@ -97,7 +97,7 @@ public class RemoteEndpointTests : BffTestBase Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) .WithUserAccessTokenParameter(new BffUserAccessTokenParameters { SignInScheme = scheme, @@ -126,7 +126,7 @@ public class RemoteEndpointTests : BffTestBase }; The.DefaultOpenIdConnectConfiguration(options); }); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); var (response, apiResult) = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.Path) @@ -152,7 +152,7 @@ public class RemoteEndpointTests : BffTestBase Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) .WithUserAccessTokenParameter(new BffUserAccessTokenParameters { SignInScheme = scheme, @@ -181,7 +181,7 @@ public class RemoteEndpointTests : BffTestBase }; The.DefaultOpenIdConnectConfiguration(options); }); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); var (response, apiResult) = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.Path), @@ -194,12 +194,12 @@ public class RemoteEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) .WithAccessToken(); }; await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.Path), method: HttpMethod.Put, @@ -217,13 +217,13 @@ public class RemoteEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) .WithAccessToken(); }; await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.Path), method: HttpMethod.Post, @@ -241,7 +241,7 @@ public class RemoteEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) .WithAccessToken(RequiredTokenType.UserOrNone); }; @@ -258,7 +258,7 @@ public class RemoteEndpointTests : BffTestBase } { - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.Path) @@ -277,7 +277,7 @@ public class RemoteEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) .WithAccessToken(RequiredTokenType.Client); }; @@ -300,19 +300,19 @@ public class RemoteEndpointTests : BffTestBase Bff.OnConfigureServices += services => { // Add a custom access token retriever that always fails - services.AddSingleton(); + _ = services.AddSingleton(); }; Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) .WithAccessTokenRetriever() .WithAccessToken(RequiredTokenType.UserOrClient); }; await ConfigureBff(setup); - await Bff.BrowserClient.CallBffHostApi( + _ = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.Path), expectedStatusCode: HttpStatusCode.Unauthorized ); @@ -328,13 +328,13 @@ public class RemoteEndpointTests : BffTestBase Api.ApiStatusCodeToReturn = HttpStatusCode.Forbidden; Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) .WithAccessToken(RequiredTokenType.None); }; await ConfigureBff(setup); - await Bff.BrowserClient.CallBffHostApi( + _ = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.Path), expectedStatusCode: HttpStatusCode.Forbidden ); @@ -346,13 +346,13 @@ public class RemoteEndpointTests : BffTestBase Api.ApiStatusCodeToReturn = HttpStatusCode.Unauthorized; Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) .WithAccessToken(RequiredTokenType.None); }; await ConfigureBff(setup); - await Bff.BrowserClient.CallBffHostApi( + _ = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.Path), expectedStatusCode: HttpStatusCode.Unauthorized ); @@ -365,12 +365,12 @@ public class RemoteEndpointTests : BffTestBase Bff.OnConfigureServices += services => { // Add a custom access token retriever that always fails - services.AddSingleton(new TestAccessTokenRetriever(() => CreateAccessToken("123", "fake-client"))); + _ = services.AddSingleton(new TestAccessTokenRetriever(() => CreateAccessToken("123", "fake-client"))); }; Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) .WithAccessTokenRetriever() .WithAccessToken(); }; @@ -417,7 +417,7 @@ public class RemoteEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) .WithAccessToken(RequiredTokenType.UserOrClient); }; @@ -434,7 +434,7 @@ public class RemoteEndpointTests : BffTestBase } { - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.Path) @@ -453,7 +453,7 @@ public class RemoteEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) .WithAccessToken(RequiredTokenType.None); }; @@ -470,7 +470,7 @@ public class RemoteEndpointTests : BffTestBase } { - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.Path) ); @@ -487,13 +487,13 @@ public class RemoteEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint("/api_user_or_client", Api.Url()) + _ = app.MapRemoteBffApiEndpoint("/api_user_or_client", Api.Url()) .WithAccessToken(RequiredTokenType.UserOrClient); - app.MapRemoteBffApiEndpoint("/api_client", Api.Url()) + _ = app.MapRemoteBffApiEndpoint("/api_client", Api.Url()) .WithAccessToken(RequiredTokenType.Client); - app.MapRemoteBffApiEndpoint("/none", Api.Url()) + _ = app.MapRemoteBffApiEndpoint("/none", Api.Url()) .WithAccessToken(RequiredTokenType.None); }; @@ -503,16 +503,16 @@ public class RemoteEndpointTests : BffTestBase client.Enabled = false; } - await Bff.BrowserClient.CallBffHostApi( + _ = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url("/api_user_or_client/test"), expectedStatusCode: HttpStatusCode.Unauthorized ); - await Bff.BrowserClient.CallBffHostApi( + _ = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url("/api_client/test"), expectedStatusCode: HttpStatusCode.Unauthorized ); - await Bff.BrowserClient.CallBffHostApi( + _ = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url("/none"), expectedStatusCode: HttpStatusCode.OK ); @@ -523,16 +523,16 @@ public class RemoteEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) .WithAccessToken(RequiredTokenType.None); }; await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); Api.ApiStatusCodeToReturn = HttpStatusCode.Unauthorized; - await Bff.BrowserClient.CallBffHostApi( + _ = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.Path), expectedStatusCode: HttpStatusCode.Unauthorized ); @@ -543,16 +543,16 @@ public class RemoteEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) .WithAccessToken(RequiredTokenType.None); }; await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); Api.ApiStatusCodeToReturn = HttpStatusCode.Forbidden; - await Bff.BrowserClient.CallBffHostApi( + _ = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.Path), expectedStatusCode: HttpStatusCode.Forbidden ); @@ -563,7 +563,7 @@ public class RemoteEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) .WithAccessToken(RequiredTokenType.None); }; @@ -580,13 +580,13 @@ public class RemoteEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) .WithAccessToken(RequiredTokenType.UserOrClient) .SkipAntiforgery(); }; await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); var req = new HttpRequestMessage(HttpMethod.Get, Bff.Url(The.Path)); var response = await Bff.BrowserClient.SendAsync(req); @@ -598,12 +598,12 @@ public class RemoteEndpointTests : BffTestBase { Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path), c => + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path), c => { DefaultBffYarpTransformerBuilders.DirectProxyWithAccessToken(The.Path, c); - c.AddRequestHeader("custom", "with value"); + _ = c.AddRequestHeader("custom", "with value"); // Add a transform that adds the catchall route value to a header - c.AddRequestTransform(async context => + _ = c.AddRequestTransform(async context => { // One of our customers asked how to access the catch-all route value in subsequent transforms if (context.HttpContext.Request.RouteValues.TryGetValue("catch-all", out var value) && @@ -619,7 +619,7 @@ public class RemoteEndpointTests : BffTestBase }; await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); ApiCallDetails result = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.PathAndSubPath) @@ -643,7 +643,7 @@ public class RemoteEndpointTests : BffTestBase Api.OnConfigureApp += app => { - app.Use(async (c, n) => + _ = app.Use(async (c, n) => { if (shouldDelay) { @@ -657,7 +657,7 @@ public class RemoteEndpointTests : BffTestBase Bff.OnConfigureServices += services => { // Add a default ForwarderRequestConfig that has a 100 ms timeout - services.AddSingleton(new ForwarderRequestConfig() + _ = services.AddSingleton(new ForwarderRequestConfig() { ActivityTimeout = TimeSpan.FromMilliseconds(100) }); @@ -665,7 +665,7 @@ public class RemoteEndpointTests : BffTestBase Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint( + _ = app.MapRemoteBffApiEndpoint( pathMatch: The.Path, apiAddress: Api.Url(The.Path)) .WithAccessToken(); @@ -673,17 +673,17 @@ public class RemoteEndpointTests : BffTestBase await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); // first, ensure that the 'normal' process works, becuase delay's are turned off. - await Bff.BrowserClient.CallBffHostApi( + _ = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.PathAndSubPath) ); // turn on delays. Now the timeout of 100 ms should kick in. shouldDelay = true; - await Bff.BrowserClient.CallBffHostApi( + _ = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.PathAndSubPath), expectedStatusCode: HttpStatusCode.BadGateway ); @@ -697,7 +697,7 @@ public class RemoteEndpointTests : BffTestBase Api.OnConfigureApp += app => { - app.Use(async (c, n) => + _ = app.Use(async (c, n) => { if (shouldDelay) { @@ -710,7 +710,7 @@ public class RemoteEndpointTests : BffTestBase Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint( + _ = app.MapRemoteBffApiEndpoint( pathMatch: The.Path, apiAddress: Api.Url(The.Path), requestConfig: new ForwarderRequestConfig() @@ -724,10 +724,10 @@ public class RemoteEndpointTests : BffTestBase await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); // first, ensure that the 'normal' process works, becuase delay's are turned off. - await Bff.BrowserClient.CallBffHostApi( + _ = await Bff.BrowserClient.CallBffHostApi( url: Bff.Url(The.PathAndSubPath) ); diff --git a/bff/test/Bff.Tests/Endpoints/WireupTests.cs b/bff/test/Bff.Tests/Endpoints/WireupTests.cs index 433cb845d..2eb867d2d 100644 --- a/bff/test/Bff.Tests/Endpoints/WireupTests.cs +++ b/bff/test/Bff.Tests/Endpoints/WireupTests.cs @@ -16,7 +16,7 @@ public class WireupTests : BffTestBase }; await InitializeAsync(); - await Bff.BrowserClient.Login(expectedStatusCode: HttpStatusCode.NotFound); + _ = await Bff.BrowserClient.Login(expectedStatusCode: HttpStatusCode.NotFound); } [Fact] public async Task Can_call_map_management_endpoints_with_automapping_when_management_path_has_template() @@ -37,7 +37,7 @@ public class WireupTests : BffTestBase await InitializeAsync(); - await Bff.BrowserClient.Login(basePath: "/some_value"); + _ = await Bff.BrowserClient.Login(basePath: "/some_value"); } [Fact] @@ -57,6 +57,6 @@ public class WireupTests : BffTestBase await InitializeAsync(); - await Bff.BrowserClient.Login(basePath: "/some_base"); + _ = await Bff.BrowserClient.Login(basePath: "/some_base"); } } diff --git a/bff/test/Bff.Tests/Endpoints/YarpTests.cs b/bff/test/Bff.Tests/Endpoints/YarpTests.cs index dd36b1866..94d1f6219 100644 --- a/bff/test/Bff.Tests/Endpoints/YarpTests.cs +++ b/bff/test/Bff.Tests/Endpoints/YarpTests.cs @@ -16,16 +16,16 @@ public class YarpTests : BffTestBase public YarpTests() : base() => Bff.OnConfigureApp += app => { - app.MapReverseProxy(proxyApp => + _ = app.MapReverseProxy(proxyApp => { - proxyApp.UseAntiforgeryCheck(); + _ = proxyApp.UseAntiforgeryCheck(); }); }; private void ConfigureYarp(RouteConfig routeConfig) => Bff.OnConfigureBff += bff => { - bff.AddYarpConfig([routeConfig], [Some.ClusterConfig(Api)]); + _ = bff.AddYarpConfig([routeConfig], [Some.ClusterConfig(Api)]); }; [Theory] @@ -38,7 +38,7 @@ public class YarpTests : BffTestBase await ConfigureBff(setup); - await Bff.BrowserClient.CallBffHostApi( + _ = await Bff.BrowserClient.CallBffHostApi( path: The.PathAndSubPath, expectedStatusCode: HttpStatusCode.OK ); @@ -81,7 +81,7 @@ public class YarpTests : BffTestBase await ConfigureBff(setup); - await Bff.BrowserClient.CallBffHostApi( + _ = await Bff.BrowserClient.CallBffHostApi( path: The.PathAndSubPath, expectedStatusCode: HttpStatusCode.OK ); @@ -95,7 +95,7 @@ public class YarpTests : BffTestBase await ConfigureBff(setup); - await Bff.BrowserClient.CallBffHostApi( + _ = await Bff.BrowserClient.CallBffHostApi( path: The.PathAndSubPath, expectedStatusCode: HttpStatusCode.Unauthorized ); @@ -148,7 +148,7 @@ public class YarpTests : BffTestBase ConfigureYarp(Some.RouteConfig().WithAccessToken(RequiredTokenType.User)); await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( path: The.PathAndSubPath @@ -170,7 +170,7 @@ public class YarpTests : BffTestBase await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( path: The.PathAndSubPath, @@ -190,7 +190,7 @@ public class YarpTests : BffTestBase ConfigureYarp(Some.RouteConfig().WithAccessToken(RequiredTokenType.User)); await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( path: The.PathAndSubPath, @@ -210,7 +210,7 @@ public class YarpTests : BffTestBase ConfigureYarp(Some.RouteConfig().WithAccessToken(RequiredTokenType.UserOrNone)); await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( path: The.PathAndSubPath, @@ -230,7 +230,7 @@ public class YarpTests : BffTestBase ConfigureYarp(Some.RouteConfig().WithAccessToken(RequiredTokenType.Client)); await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( path: The.PathAndSubPath @@ -249,7 +249,7 @@ public class YarpTests : BffTestBase ConfigureYarp(Some.RouteConfig().WithAccessToken(RequiredTokenType.UserOrClient)); await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( path: The.PathAndSubPath @@ -281,7 +281,7 @@ public class YarpTests : BffTestBase AddOrUpdateFrontend(frontEnd); - await Bff.BrowserClient.Login("/somepath"); + _ = await Bff.BrowserClient.Login("/somepath"); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( path: "/somepath" + The.PathAndSubPath ); @@ -300,9 +300,9 @@ public class YarpTests : BffTestBase await ConfigureBff(setup); Api.ApiStatusCodeToReturn = HttpStatusCode.Unauthorized; - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); - await Bff.BrowserClient.CallBffHostApi( + _ = await Bff.BrowserClient.CallBffHostApi( path: The.PathAndSubPath, expectedStatusCode: HttpStatusCode.Unauthorized ); @@ -316,9 +316,9 @@ public class YarpTests : BffTestBase await ConfigureBff(setup); Api.ApiStatusCodeToReturn = HttpStatusCode.Forbidden; - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); - await Bff.BrowserClient.CallBffHostApi( + _ = await Bff.BrowserClient.CallBffHostApi( path: The.PathAndSubPath, expectedStatusCode: HttpStatusCode.Forbidden ); diff --git a/bff/test/Bff.Tests/EntityFramework/SessionIntegrationTests.cs b/bff/test/Bff.Tests/EntityFramework/SessionIntegrationTests.cs index 242471542..2673b5875 100644 --- a/bff/test/Bff.Tests/EntityFramework/SessionIntegrationTests.cs +++ b/bff/test/Bff.Tests/EntityFramework/SessionIntegrationTests.cs @@ -27,7 +27,7 @@ public class HostBuilder_SessionTests : BffTestBase Bff.OnConfigureBff += bff => { // Enable server-side sessions with in-memory storage - bff.AddServerSideSessions(); + _ = bff.AddServerSideSessions(); }; await InitializeAsync(); @@ -36,7 +36,7 @@ public class HostBuilder_SessionTests : BffTestBase // you get the InMemoryUserSessionStore. var userSessionStore = Bff.Server.Services.GetRequiredService(); var userSessionStore2 = Bff.Server.Services.GetRequiredService(); - userSessionStore.ShouldBeOfType(); + _ = userSessionStore.ShouldBeOfType(); userSessionStore2.ShouldBe(userSessionStore, "should be singleton"); } @@ -48,14 +48,14 @@ public class HostBuilder_SessionTests : BffTestBase Bff.OnConfigureBff += bff => { // Enable server-side sessions with in-memory storage - bff.AddEntityFrameworkServerSideSessions(opt => opt.UseInMemoryDatabase(_databaseName)); + _ = bff.AddEntityFrameworkServerSideSessions(opt => opt.UseInMemoryDatabase(_databaseName)); }; await InitializeAsync(); // The bff should use the UserSessionStore, which is registered by the WithEntityFramework var userSessionStore = Bff.Server.Services.GetRequiredService(); - userSessionStore.ShouldBeOfType(); + _ = userSessionStore.ShouldBeOfType(); } [Fact] @@ -64,14 +64,14 @@ public class HostBuilder_SessionTests : BffTestBase Bff.OnConfigureBff += bff => { // Enable server-side sessions with in-memory storage - bff.AddEntityFrameworkServerSideSessions(opt => opt.UseInMemoryDatabase(_databaseName)); - bff.AddSessionCleanupBackgroundProcess(); - bff.ConfigureOpenIdConnect(The.DefaultOpenIdConnectConfiguration); + _ = bff.AddEntityFrameworkServerSideSessions(opt => opt.UseInMemoryDatabase(_databaseName)); + _ = bff.AddSessionCleanupBackgroundProcess(); + _ = bff.ConfigureOpenIdConnect(The.DefaultOpenIdConnectConfiguration); }; - IdentityServer.AddClient(The.ClientId, Bff.Url()); + _ = IdentityServer.AddClient(The.ClientId, Bff.Url()); await InitializeAsync(); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); var sessionStore = Bff.Server.Services.GetRequiredService(); // Get the partition key from the first host, which is where the session was created @@ -109,21 +109,21 @@ public class HostBuilder_SessionTests : BffTestBase host2.OnConfigureBff += bff => { // Enable server-side sessions with in-memory storage - bff.AddEntityFrameworkServerSideSessions(opt => opt.UseInMemoryDatabase(_databaseName)); - bff.AddSessionCleanupBackgroundProcess(); + _ = bff.AddEntityFrameworkServerSideSessions(opt => opt.UseInMemoryDatabase(_databaseName)); + _ = bff.AddSessionCleanupBackgroundProcess(); }; Bff.OnConfigureBff += bff => { // Enable server-side sessions with in-memory storage - bff.AddEntityFrameworkServerSideSessions(opt => opt.UseInMemoryDatabase(_databaseName)); - bff.ConfigureOpenIdConnect(The.DefaultOpenIdConnectConfiguration); + _ = bff.AddEntityFrameworkServerSideSessions(opt => opt.UseInMemoryDatabase(_databaseName)); + _ = bff.ConfigureOpenIdConnect(The.DefaultOpenIdConnectConfiguration); }; - IdentityServer.AddClient(The.ClientId, Bff.Url()); + _ = IdentityServer.AddClient(The.ClientId, Bff.Url()); await InitializeAsync(); await host2.InitializeAsync(); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); var sessionStore = Bff.Server.Services.GetRequiredService(); // Get the partition key from the first host, which is where the session was created @@ -160,10 +160,10 @@ public class HostBuilder_SessionTests : BffTestBase Bff.OnConfigureBff += bff => { // Enable server-side sessions with in-memory storage - bff.AddSessionCleanupBackgroundProcess(); - bff.ConfigureOpenIdConnect(The.DefaultOpenIdConnectConfiguration); + _ = bff.AddSessionCleanupBackgroundProcess(); + _ = bff.ConfigureOpenIdConnect(The.DefaultOpenIdConnectConfiguration); }; - IdentityServer.AddClient(The.ClientId, Bff.Url()); + _ = IdentityServer.AddClient(The.ClientId, Bff.Url()); var exception = await Should.ThrowAsync(() => InitializeAsync().AsTask()); exception.Message.ShouldBe("No IUserSessionStoreCleanup is registered. Did you add session storage, such as EntityFramework?"); diff --git a/bff/test/Bff.Tests/EntityFramework/UserSessionStoreTests.cs b/bff/test/Bff.Tests/EntityFramework/UserSessionStoreTests.cs index 0a5ce24cb..85e5330d4 100644 --- a/bff/test/Bff.Tests/EntityFramework/UserSessionStoreTests.cs +++ b/bff/test/Bff.Tests/EntityFramework/UserSessionStoreTests.cs @@ -32,14 +32,14 @@ public class UserSessionStoreTests : IAsyncLifetime _dbFilePath = Path.Combine(Path.GetTempPath(), $"test-{Guid.NewGuid():N}.sqlite"); var connectionString = $"Data Source={_dbFilePath}"; - services + _ = services .AddSingleton() .AddSingleton(_fakeHttpContextAccessor) .AddLogging(l => l.AddProvider(new TestLoggerProvider(output.WriteLine, "db"))) .AddBff() .AddEntityFrameworkServerSideSessions(options => options.UseSqlite(connectionString, dbOpts => dbOpts.MigrationsAssembly(typeof(Startup).Assembly.FullName))); - services.AddDataProtection(s => s.ApplicationDiscriminator = "bob"); + _ = services.AddDataProtection(s => s.ApplicationDiscriminator = "bob"); _provider = services.BuildServiceProvider(); @@ -139,7 +139,7 @@ public class UserSessionStoreTests : IAsyncLifetime }); var item = await _subject.GetUserSessionAsync(The.UserSessionKey); - item.ShouldNotBeNull(); + _ = item.ShouldNotBeNull(); item.Key.ShouldBe(The.UserKey); item.SubjectId.ShouldBe("sub"); item.SessionId.ShouldBe("sid"); @@ -160,7 +160,7 @@ public class UserSessionStoreTests : IAsyncLifetime }); var item = await _subject.GetUserSessionAsync(The.UserSessionKey); - item.ShouldNotBeNull(); + _ = item.ShouldNotBeNull(); item.Key.ShouldBe(The.UserKey); item.SubjectId.ShouldBe("sub2"); item.SessionId.ShouldBe("sid2"); @@ -503,7 +503,7 @@ public class UserSessionStoreTests : IAsyncLifetime Func f = () => _subject.GetUserSessionsAsync(The.PartitionKey, new UserSessionsFilter() { }); - await f.ShouldThrowAsync(); + _ = await f.ShouldThrowAsync(); } @@ -772,7 +772,7 @@ public class UserSessionStoreTests : IAsyncLifetime Func f = () => _subject.DeleteUserSessionsAsync(The.PartitionKey, new UserSessionsFilter() { }); - await f.ShouldThrowAsync(); + _ = await f.ShouldThrowAsync(); } [Fact] @@ -780,14 +780,14 @@ public class UserSessionStoreTests : IAsyncLifetime { var dbName = Guid.NewGuid().ToString(); var services = new ServiceCollection(); - services.AddBff() + _ = services.AddBff() .AddEntityFrameworkServerSideSessions(options => options.UseInMemoryDatabase(dbName)); var provider = services.BuildServiceProvider(); using var scope0 = provider.CreateScope(); var ctx0 = scope0.ServiceProvider.GetRequiredService(); var key = UserKey.Parse(Guid.NewGuid().ToString()); - ctx0.UserSessions.Add(new UserSessionEntity + _ = ctx0.UserSessions.Add(new UserSessionEntity { PartitionKey = The.PartitionKey, Key = key, @@ -795,26 +795,26 @@ public class UserSessionStoreTests : IAsyncLifetime SubjectId = "sub", SessionId = "sid", }); - await ctx0.SaveChangesAsync(); + _ = await ctx0.SaveChangesAsync(); using var scope1 = provider.CreateScope(); var ctx1 = scope1.ServiceProvider.GetRequiredService(); var item1 = ctx1.UserSessions.Single(x => x.Key == key); - ctx1.UserSessions.Remove(item1); + _ = ctx1.UserSessions.Remove(item1); using var scope2 = provider.CreateScope(); var ctx2 = scope2.ServiceProvider.GetRequiredService(); var item2 = ctx2.UserSessions.Single(x => x.Key == key); - ctx2.UserSessions.Remove(item2); + _ = ctx2.UserSessions.Remove(item2); - await ctx1.SaveChangesAsync(); + _ = await ctx1.SaveChangesAsync(); Func f1 = async () => await ctx2.SaveChangesAsync(); - await f1.ShouldThrowAsync(); + _ = await f1.ShouldThrowAsync(); try { - await ctx2.SaveChangesAsync(); + _ = await ctx2.SaveChangesAsync(); } catch (DbUpdateConcurrencyException ex) { @@ -826,7 +826,7 @@ public class UserSessionStoreTests : IAsyncLifetime } // calling again to not throw - await ctx2.SaveChangesAsync(); + _ = await ctx2.SaveChangesAsync(); } public IDisposable UseFrontend(BffFrontend frontent) @@ -839,9 +839,8 @@ public class UserSessionStoreTests : IAsyncLifetime }); } - public async ValueTask InitializeAsync() => - // Ensure the database is created and migrations are applied - await _database.Database.MigrateAsync(); + // Ensure the database is created and migrations are applied + public async ValueTask InitializeAsync() => await _database.Database.MigrateAsync(); public async ValueTask DisposeAsync() diff --git a/bff/test/Bff.Tests/Headers/ApiAndBffUseForwardedHeaders.cs b/bff/test/Bff.Tests/Headers/ApiAndBffUseForwardedHeaders.cs index 7663c5f3f..bdcbe3d3b 100644 --- a/bff/test/Bff.Tests/Headers/ApiAndBffUseForwardedHeaders.cs +++ b/bff/test/Bff.Tests/Headers/ApiAndBffUseForwardedHeaders.cs @@ -13,7 +13,7 @@ public class ApiAndBffUseForwardedHeaders : BffTestBase, IAsyncLifetime { Bff.OnConfigureApp += app => { - app.UseForwardedHeaders(new ForwardedHeadersOptions + _ = app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | @@ -25,7 +25,7 @@ public class ApiAndBffUseForwardedHeaders : BffTestBase, IAsyncLifetime Api.OnConfigureApp += app => { - app.UseForwardedHeaders(new ForwardedHeadersOptions + _ = app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | @@ -35,7 +35,7 @@ public class ApiAndBffUseForwardedHeaders : BffTestBase, IAsyncLifetime Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url()); + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url()); }; } diff --git a/bff/test/Bff.Tests/Headers/ApiUseForwardedHeaders.cs b/bff/test/Bff.Tests/Headers/ApiUseForwardedHeaders.cs index 7f02f662f..80d71161a 100644 --- a/bff/test/Bff.Tests/Headers/ApiUseForwardedHeaders.cs +++ b/bff/test/Bff.Tests/Headers/ApiUseForwardedHeaders.cs @@ -15,7 +15,7 @@ public class ApiUseForwardedHeaders : BffTestBase Api.OnConfigureApp += app => { - app.UseForwardedHeaders(new ForwardedHeadersOptions + _ = app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | @@ -25,7 +25,7 @@ public class ApiUseForwardedHeaders : BffTestBase Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url()); + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url()); }; } diff --git a/bff/test/Bff.Tests/Headers/GeneralTests.cs b/bff/test/Bff.Tests/Headers/GeneralTests.cs index 37e066bcb..2a9d50055 100644 --- a/bff/test/Bff.Tests/Headers/GeneralTests.cs +++ b/bff/test/Bff.Tests/Headers/GeneralTests.cs @@ -17,7 +17,7 @@ public class GeneralTests : BffTestBase { Bff.OnConfigureApp += app => { - app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c)) + _ = app.Map(The.Path, c => ApiHost.ReturnApiCallDetails(c)) .RequireAuthorization(); }; await ConfigureBff(setup); @@ -41,7 +41,7 @@ public class GeneralTests : BffTestBase Bff.OnConfigureBff += bff => bff.AddRemoteApis(); Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url()) + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url()) .WithAccessToken(RequiredTokenType.None); }; await ConfigureBff(setup); @@ -65,7 +65,7 @@ public class GeneralTests : BffTestBase Bff.OnConfigureBff += bff => bff.AddRemoteApis(); Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url()) + _ = app.MapRemoteBffApiEndpoint(The.Path, Api.Url()) .WithAccessToken(RequiredTokenType.None); }; await ConfigureBff(setup); @@ -93,7 +93,7 @@ public class GeneralTests : BffTestBase Context.LogMessages.ToString().ShouldNotContain("Already mapped Login endpoint"); // And we can log in, which means the login endpoint was registered - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); } [Theory, MemberData(nameof(AllSetups))] @@ -103,7 +103,7 @@ public class GeneralTests : BffTestBase await ConfigureBff(setup); // And we can log in, which means the login endpoint was registered - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); Context.LogMessages.ToString().ShouldContain("Management endpoints are automatically mapped"); } diff --git a/bff/test/Bff.Tests/IAccessTokenRetriever_Extensibility_tests.cs b/bff/test/Bff.Tests/IAccessTokenRetriever_Extensibility_tests.cs index d351ec1c4..34d036490 100644 --- a/bff/test/Bff.Tests/IAccessTokenRetriever_Extensibility_tests.cs +++ b/bff/test/Bff.Tests/IAccessTokenRetriever_Extensibility_tests.cs @@ -17,14 +17,14 @@ public class IAccessTokenRetriever_Extensibility_tests : BffTestBase public IAccessTokenRetriever_Extensibility_tests() : base() { - IdentityServer.AddClient(The.ClientId, Bff.Url()); + _ = IdentityServer.AddClient(The.ClientId, Bff.Url()); Bff.OnConfigureBff += bff => bff .ConfigureOpenIdConnect(The.DefaultOpenIdConnectConfiguration) .AddRemoteApis(); Bff.OnConfigureServices += services => { - services.AddSingleton(_customAccessTokenReceiver); + _ = services.AddSingleton(_customAccessTokenReceiver); }; } @@ -33,15 +33,15 @@ public class IAccessTokenRetriever_Extensibility_tests : BffTestBase { Bff.OnConfigureApp += app => { - app.MapRemoteBffApiEndpoint("/custom", Api.Url("/some/path")) + _ = app.MapRemoteBffApiEndpoint("/custom", Api.Url("/some/path")) .WithAccessToken() .WithAccessTokenRetriever(); }; await InitializeAsync(); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); - await Bff.BrowserClient.CallBffHostApi(Bff.Url("/custom")); + _ = await Bff.BrowserClient.CallBffHostApi(Bff.Url("/custom")); var usedContext = _customAccessTokenReceiver.UsedContext.ShouldNotBeNull(); @@ -58,13 +58,13 @@ public class IAccessTokenRetriever_Extensibility_tests : BffTestBase Bff.OnConfigureApp += app => { - app.Map("/subPath", + _ = app.Map("/subPath", subPath => { - subPath.UseRouting(); - subPath.UseEndpoints((endpoints) => + _ = subPath.UseRouting(); + _ = subPath.UseEndpoints((endpoints) => { - endpoints.MapRemoteBffApiEndpoint("/custom_within_subpath", Api.Url("/some/path")) + _ = endpoints.MapRemoteBffApiEndpoint("/custom_within_subpath", Api.Url("/some/path")) .WithAccessToken() .WithAccessTokenRetriever(); }); @@ -72,8 +72,8 @@ public class IAccessTokenRetriever_Extensibility_tests : BffTestBase }; await InitializeAsync(); - await Bff.BrowserClient.Login(); - await Bff.BrowserClient.CallBffHostApi(Bff.Url("/subPath/custom_within_subpath")); + _ = await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.CallBffHostApi(Bff.Url("/subPath/custom_within_subpath")); var usedContext = _customAccessTokenReceiver.UsedContext.ShouldNotBeNull(); diff --git a/bff/test/Bff.Tests/Internal/ClaimsPrincipalRecordTests.cs b/bff/test/Bff.Tests/Internal/ClaimsPrincipalRecordTests.cs index 3d1916546..5eb778558 100644 --- a/bff/test/Bff.Tests/Internal/ClaimsPrincipalRecordTests.cs +++ b/bff/test/Bff.Tests/Internal/ClaimsPrincipalRecordTests.cs @@ -41,7 +41,7 @@ public class ClaimsPrincipalRecordTests { var original = new ClaimsPrincipalRecord(); - Should.NotThrow(() => original.ToClaimsPrincipal()); + _ = Should.NotThrow(() => original.ToClaimsPrincipal()); } [Fact] @@ -55,7 +55,7 @@ public class ClaimsPrincipalRecordTests ] }; - Should.NotThrow(() => original.ToClaimsPrincipal()); + _ = Should.NotThrow(() => original.ToClaimsPrincipal()); } [Fact] @@ -64,7 +64,7 @@ public class ClaimsPrincipalRecordTests var serializedClaimsPrincipal = """{"Claims": null}"""; var record = JsonSerializer.Deserialize(serializedClaimsPrincipal); - Should.NotThrow(() => record!.ToClaimsPrincipal()); + _ = Should.NotThrow(() => record!.ToClaimsPrincipal()); } [Fact] diff --git a/bff/test/Bff.Tests/LicensingTests.cs b/bff/test/Bff.Tests/LicensingTests.cs index 53695b9f3..547d9e5ed 100644 --- a/bff/test/Bff.Tests/LicensingTests.cs +++ b/bff/test/Bff.Tests/LicensingTests.cs @@ -44,7 +44,7 @@ public class LicensingTests : BffTestBase { var subjectId = Guid.NewGuid().ToString(); await Bff.BrowserClient.CreateIdentityServerSessionCookieAsync(IdentityServer, subjectId); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); } var bffLogMessages = Context.LogMessages.ToString().Split(Environment.NewLine).Where(x => x.StartsWith("bff")) @@ -70,7 +70,7 @@ public class LicensingTests : BffTestBase { var subjectId = Guid.NewGuid().ToString(); await Bff.BrowserClient.CreateIdentityServerSessionCookieAsync(IdentityServer, subjectId); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); } var bffLogMessages = Context.LogMessages.ToString().Split(Environment.NewLine).Where(x => x.StartsWith("bff")) @@ -91,7 +91,7 @@ public class LicensingTests : BffTestBase { var subjectId = Guid.NewGuid().ToString(); await Bff.BrowserClient.CreateIdentityServerSessionCookieAsync(IdentityServer, subjectId); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); } var bffLogMessages = Context.LogMessages.ToString().Split(Environment.NewLine).Where(x => x.StartsWith("bff")) diff --git a/bff/test/Bff.Tests/MultiFrontend/FrontendCollectionTests.cs b/bff/test/Bff.Tests/MultiFrontend/FrontendCollectionTests.cs index dbaa8fb73..e1c743e53 100644 --- a/bff/test/Bff.Tests/MultiFrontend/FrontendCollectionTests.cs +++ b/bff/test/Bff.Tests/MultiFrontend/FrontendCollectionTests.cs @@ -171,7 +171,7 @@ public class FrontendCollectionTests updateCount.ShouldBe(1); addedCount.ShouldBe(1); - eventArg.ShouldNotBeNull(); + _ = eventArg.ShouldNotBeNull(); eventArg.ShouldBe(updatedFrontend); } @@ -209,7 +209,7 @@ public class FrontendCollectionTests updateCount.ShouldBe(0); addedCount.ShouldBe(1); - eventArg.ShouldNotBeNull(); + _ = eventArg.ShouldNotBeNull(); eventArg.ShouldBe(updatedFrontend); } @@ -235,7 +235,7 @@ public class FrontendCollectionTests cache.Remove(bffFrontend.Name); eventCount.ShouldBe(1); - eventArg.ShouldNotBeNull(); + _ = eventArg.ShouldNotBeNull(); eventArg.ShouldBe(bffFrontend); } } diff --git a/bff/test/Bff.Tests/MultiFrontend/FrontendSelectorTests.cs b/bff/test/Bff.Tests/MultiFrontend/FrontendSelectorTests.cs index 12c33b2b1..391e30daa 100644 --- a/bff/test/Bff.Tests/MultiFrontend/FrontendSelectorTests.cs +++ b/bff/test/Bff.Tests/MultiFrontend/FrontendSelectorTests.cs @@ -29,7 +29,7 @@ public class FrontendSelectorTests var testLoggerProvider = new TestLoggerProvider((s) => { _output.WriteLine(s); - _logMessages.AppendLine(s); + _ = _logMessages.AppendLine(s); }, "", forceToWriteOutput: true); var loggerFactory = new LoggerFactory([testLoggerProvider]); @@ -72,7 +72,7 @@ public class FrontendSelectorTests // Assert result.ShouldBeTrue(); - selectedFrontend.ShouldNotBeNull(); + _ = selectedFrontend.ShouldNotBeNull(); selectedFrontend.Name.ToString().ShouldBe("test-frontend1"); } @@ -90,7 +90,7 @@ public class FrontendSelectorTests // Assert result.ShouldBeTrue(); - selectedFrontend.ShouldNotBeNull(); + _ = selectedFrontend.ShouldNotBeNull(); selectedFrontend.Name.ToString().ShouldBe(The.FrontendName); } [Fact] @@ -107,7 +107,7 @@ public class FrontendSelectorTests // Assert result.ShouldBeTrue(); - selectedFrontend.ShouldNotBeNull(); + _ = selectedFrontend.ShouldNotBeNull(); selectedFrontend.Name.ToString().ShouldBe(The.FrontendName); } [Fact] @@ -124,7 +124,7 @@ public class FrontendSelectorTests // Assert result.ShouldBeTrue(); - selectedFrontend.ShouldNotBeNull(); + _ = selectedFrontend.ShouldNotBeNull(); selectedFrontend.Name.ToString().ShouldBe(The.FrontendName); } @@ -142,7 +142,7 @@ public class FrontendSelectorTests // Assert result.ShouldBeTrue(); - selectedFrontend.ShouldNotBeNull(); + _ = selectedFrontend.ShouldNotBeNull(); selectedFrontend.Name.ToString().ShouldBe(The.FrontendName); //_logMessages.ToString().ShouldContain("has different case"); @@ -163,7 +163,7 @@ public class FrontendSelectorTests // Assert result.ShouldBeTrue(); - selectedFrontend.ShouldNotBeNull(); + _ = selectedFrontend.ShouldNotBeNull(); selectedFrontend.Name.ToString().ShouldBe(The.FrontendName); } [Fact] @@ -182,7 +182,7 @@ public class FrontendSelectorTests // Assert result.ShouldBeTrue(); - selectedFrontend.ShouldNotBeNull(); + _ = selectedFrontend.ShouldNotBeNull(); selectedFrontend.Name.ToString().ShouldBe(The.FrontendName); } @@ -201,7 +201,7 @@ public class FrontendSelectorTests // Assert result.ShouldBeTrue(); - selectedFrontend.ShouldNotBeNull(); + _ = selectedFrontend.ShouldNotBeNull(); selectedFrontend.Name.ToString().ShouldBe(The.FrontendName); } @@ -225,7 +225,7 @@ public class FrontendSelectorTests // Assert result.ShouldBeTrue(); - selectedFrontend.ShouldNotBeNull(); + _ = selectedFrontend.ShouldNotBeNull(); selectedFrontend.Name.ToString().ShouldBe("specific-frontend"); } @@ -248,7 +248,7 @@ public class FrontendSelectorTests // Assert result.ShouldBeTrue(); - selectedFrontend.ShouldNotBeNull(); + _ = selectedFrontend.ShouldNotBeNull(); selectedFrontend.Name.ToString().ShouldBe("specific-frontend"); } @@ -290,16 +290,16 @@ public class FrontendSelectorTests // Act - _selector.TrySelectFrontend(CreateHttpRequest("https://different.com/path"), out var selectedFrontend); + _ = _selector.TrySelectFrontend(CreateHttpRequest("https://different.com/path"), out var selectedFrontend); selectedFrontend!.Name.ToString().ShouldBe("path"); - _selector.TrySelectFrontend(CreateHttpRequest("https://test.com/otherpath"), out selectedFrontend); + _ = _selector.TrySelectFrontend(CreateHttpRequest("https://test.com/otherpath"), out selectedFrontend); selectedFrontend!.Name.ToString().ShouldBe("Host"); - _selector.TrySelectFrontend(CreateHttpRequest("https://test.com/path/otherSubPath"), out selectedFrontend); + _ = _selector.TrySelectFrontend(CreateHttpRequest("https://test.com/path/otherSubPath"), out selectedFrontend); selectedFrontend!.Name.ToString().ShouldBe("path_and_Host"); - _selector.TrySelectFrontend(CreateHttpRequest("https://test.com/path/subpath"), out selectedFrontend); + _ = _selector.TrySelectFrontend(CreateHttpRequest("https://test.com/path/subpath"), out selectedFrontend); selectedFrontend!.Name.ToString().ShouldBe("path_subpath_and_Host"); } @@ -321,7 +321,7 @@ public class FrontendSelectorTests // Assert result.ShouldBeTrue(); - selectedFrontend.ShouldNotBeNull(); + _ = selectedFrontend.ShouldNotBeNull(); selectedFrontend.Name.ToString().ShouldBe("default-frontend"); } @@ -343,7 +343,7 @@ public class FrontendSelectorTests // Assert result.ShouldBeTrue(); - selectedFrontend.ShouldNotBeNull(); + _ = selectedFrontend.ShouldNotBeNull(); selectedFrontend.Name.ToString().ShouldBe("default-frontend"); } diff --git a/bff/test/Bff.Tests/MultiFrontend/HostHeaderValueTests.cs b/bff/test/Bff.Tests/MultiFrontend/HostHeaderValueTests.cs index 602abdec0..f4d5cd9b3 100644 --- a/bff/test/Bff.Tests/MultiFrontend/HostHeaderValueTests.cs +++ b/bff/test/Bff.Tests/MultiFrontend/HostHeaderValueTests.cs @@ -123,7 +123,7 @@ public class HostHeaderValueTests public void Will_catch_invalid_hostheader(string input, string reason) { var action = () => HostHeaderValue.Parse(input); - action.ShouldThrow(); + _ = action.ShouldThrow(); } [Fact] diff --git a/bff/test/Bff.Tests/PublicApiVerificationTests.VerifyPublicApi_Bff.verified.txt b/bff/test/Bff.Tests/PublicApiVerificationTests.VerifyPublicApi_Bff.verified.txt index a7bd220ef..6ecc6cada 100644 --- a/bff/test/Bff.Tests/PublicApiVerificationTests.VerifyPublicApi_Bff.verified.txt +++ b/bff/test/Bff.Tests/PublicApiVerificationTests.VerifyPublicApi_Bff.verified.txt @@ -15,44 +15,25 @@ { protected AccessTokenResult() { } } - [System.Runtime.CompilerServices.RequiredMember] public sealed class AccessTokenRetrievalContext : System.IEquatable { - [System.Obsolete("Constructors of types with required members are not supported in this version of " + - "your compiler.", true)] - [System.Runtime.CompilerServices.CompilerFeatureRequired("RequiredMembers")] public AccessTokenRetrievalContext() { } - [System.Runtime.CompilerServices.RequiredMember] - public System.Uri ApiAddress { get; init; } - [System.Runtime.CompilerServices.RequiredMember] - public Microsoft.AspNetCore.Http.HttpContext HttpContext { get; init; } - [System.Runtime.CompilerServices.RequiredMember] - public Duende.Bff.Configuration.BffRemoteApiEndpointMetadata Metadata { get; init; } - [System.Runtime.CompilerServices.RequiredMember] - public Microsoft.AspNetCore.Http.PathString PathMatch { get; init; } - [System.Runtime.CompilerServices.RequiredMember] - public Duende.Bff.Configuration.BffUserAccessTokenParameters? UserTokenRequestParameters { get; init; } + public required System.Uri ApiAddress { get; init; } + public required Microsoft.AspNetCore.Http.HttpContext HttpContext { get; init; } + public required Duende.Bff.Configuration.BffRemoteApiEndpointMetadata Metadata { get; init; } + public required Microsoft.AspNetCore.Http.PathString PathMatch { get; init; } + public required Duende.Bff.Configuration.BffUserAccessTokenParameters? UserTokenRequestParameters { get; init; } } - [System.Runtime.CompilerServices.RequiredMember] public class AccessTokenRetrievalError : Duende.Bff.AccessTokenManagement.AccessTokenResult, System.IEquatable { - [System.Obsolete("Constructors of types with required members are not supported in this version of " + - "your compiler.", true)] - [System.Runtime.CompilerServices.CompilerFeatureRequired("RequiredMembers")] public AccessTokenRetrievalError() { } + public required string Error { get; init; } public string? ErrorDescription { get; init; } - [System.Runtime.CompilerServices.RequiredMember] - public string Error { get; init; } } - [System.Runtime.CompilerServices.RequiredMember] public sealed class BearerTokenResult : Duende.Bff.AccessTokenManagement.AccessTokenResult, System.IEquatable { - [System.Obsolete("Constructors of types with required members are not supported in this version of " + - "your compiler.", true)] - [System.Runtime.CompilerServices.CompilerFeatureRequired("RequiredMembers")] public BearerTokenResult() { } - [System.Runtime.CompilerServices.RequiredMember] - public Duende.Bff.AccessTokenManagement.AccessToken AccessToken { get; init; } + public required Duende.Bff.AccessTokenManagement.AccessToken AccessToken { get; init; } } [System.ComponentModel.TypeConverter(typeof(Duende.Bff.Internal.StringValueConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(Duende.Bff.Internal.StringValueJsonConverter))] @@ -69,17 +50,11 @@ public static Duende.AccessTokenManagement.DPoP.DPoPProofKey op_Implicit(Duende.Bff.AccessTokenManagement.DPoPProofKey value) { } public static string op_Implicit(Duende.Bff.AccessTokenManagement.DPoPProofKey value) { } } - [System.Runtime.CompilerServices.RequiredMember] public sealed class DPoPTokenResult : Duende.Bff.AccessTokenManagement.AccessTokenResult, System.IEquatable { - [System.Obsolete("Constructors of types with required members are not supported in this version of " + - "your compiler.", true)] - [System.Runtime.CompilerServices.CompilerFeatureRequired("RequiredMembers")] public DPoPTokenResult() { } - [System.Runtime.CompilerServices.RequiredMember] - public Duende.Bff.AccessTokenManagement.AccessToken AccessToken { get; init; } - [System.Runtime.CompilerServices.RequiredMember] - public Duende.Bff.AccessTokenManagement.DPoPProofKey DPoPJsonWebKey { get; init; } + public required Duende.Bff.AccessTokenManagement.AccessToken AccessToken { get; init; } + public required Duende.Bff.AccessTokenManagement.DPoPProofKey DPoPJsonWebKey { get; init; } } public interface IAccessTokenRetriever { @@ -199,10 +174,10 @@ namespace Duende.Bff public ClaimRecord(string type, object value) { } [System.Text.Json.Serialization.JsonPropertyName("type")] public string Type { get; init; } - [System.Text.Json.Serialization.JsonPropertyName("valueType")] - public string? ValueType { get; init; } [System.Text.Json.Serialization.JsonPropertyName("value")] public object Value { get; init; } + [System.Text.Json.Serialization.JsonPropertyName("valueType")] + public string? ValueType { get; init; } } public static class Constants { @@ -371,23 +346,18 @@ namespace Duende.Bff.DynamicFrontends public static readonly Duende.Bff.AccessTokenManagement.Scheme BffCookie; public static readonly Duende.Bff.AccessTokenManagement.Scheme BffOpenIdConnect; } - [System.Runtime.CompilerServices.RequiredMember] public sealed class BffFrontend : System.IEquatable { - [System.Obsolete("Constructors of types with required members are not supported in this version of " + - "your compiler.", true)] - [System.Runtime.CompilerServices.CompilerFeatureRequired("RequiredMembers")] public BffFrontend() { } [System.Diagnostics.CodeAnalysis.SetsRequiredMembers] public BffFrontend(Duende.Bff.DynamicFrontends.BffFrontendName name) { } - public Duende.Bff.AccessTokenManagement.Scheme CookieSchemeName { get; } - public Duende.Bff.AccessTokenManagement.Scheme OidcSchemeName { get; } public System.Uri? CdnIndexHtmlUrl { get; init; } public System.Action? ConfigureCookieOptions { get; init; } public System.Action? ConfigureOpenIdConnectOptions { get; init; } + public Duende.Bff.AccessTokenManagement.Scheme CookieSchemeName { get; } public Duende.Bff.DynamicFrontends.FrontendMatchingCriteria MatchingCriteria { get; init; } - [System.Runtime.CompilerServices.RequiredMember] - public Duende.Bff.DynamicFrontends.BffFrontendName Name { get; init; } + public required Duende.Bff.DynamicFrontends.BffFrontendName Name { get; init; } + public Duende.Bff.AccessTokenManagement.Scheme OidcSchemeName { get; } public System.Uri? StaticAssetsUrl { get; init; } public bool Equals(Duende.Bff.DynamicFrontends.BffFrontend? other) { } public override int GetHashCode() { } @@ -427,22 +397,17 @@ namespace Duende.Bff.DynamicFrontends public bool Equals(Duende.Bff.DynamicFrontends.FrontendMatchingCriteria? other) { } public override int GetHashCode() { } } - [System.Runtime.CompilerServices.RequiredMember] public sealed class HostHeaderValue : System.IEquatable, System.IEquatable { - [System.Obsolete("Constructors of types with required members are not supported in this version of " + - "your compiler.", true)] - [System.Runtime.CompilerServices.CompilerFeatureRequired("RequiredMembers")] public HostHeaderValue() { } - [System.Runtime.CompilerServices.RequiredMember] - public string Host { get; init; } + public required string Host { get; init; } public int Port { get; init; } public bool Equals(Duende.Bff.DynamicFrontends.HostHeaderValue? other) { } public bool Equals(Microsoft.AspNetCore.Http.HttpRequest? request) { } public override int GetHashCode() { } public override string ToString() { } - public static Duende.Bff.DynamicFrontends.HostHeaderValue Parse(string hostHeaderValue) { } public static Duende.Bff.DynamicFrontends.HostHeaderValue Parse(System.Uri uri) { } + public static Duende.Bff.DynamicFrontends.HostHeaderValue Parse(string hostHeaderValue) { } public static Duende.Bff.DynamicFrontends.HostHeaderValue? ParseOrDefault(string? origin) { } } public interface IFrontendCollection : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable diff --git a/bff/test/Bff.Tests/PublicApiVerificationTests.VerifyPublicApi_Bff_Yarp.verified.txt b/bff/test/Bff.Tests/PublicApiVerificationTests.VerifyPublicApi_Bff_Yarp.verified.txt index b6dcf3274..117713682 100644 --- a/bff/test/Bff.Tests/PublicApiVerificationTests.VerifyPublicApi_Bff_Yarp.verified.txt +++ b/bff/test/Bff.Tests/PublicApiVerificationTests.VerifyPublicApi_Bff_Yarp.verified.txt @@ -30,12 +30,8 @@ namespace Duende.Bff.Yarp public static Duende.Bff.Yarp.RemoteApi[] GetRemoteApis(this Duende.Bff.DynamicFrontends.BffFrontend frontend) { } public static Duende.Bff.DynamicFrontends.BffFrontend WithRemoteApis(this Duende.Bff.DynamicFrontends.BffFrontend frontend, params Duende.Bff.Yarp.RemoteApi[] config) { } } - [System.Runtime.CompilerServices.RequiredMember] public sealed class RemoteApi : System.IEquatable { - [System.Obsolete("Constructors of types with required members are not supported in this version of " + - "your compiler.", true)] - [System.Runtime.CompilerServices.CompilerFeatureRequired("RequiredMembers")] public RemoteApi() { } [System.Diagnostics.CodeAnalysis.SetsRequiredMembers] public RemoteApi(Microsoft.AspNetCore.Http.PathString pathMatch, System.Uri targetUri) { } @@ -43,12 +39,9 @@ namespace Duende.Bff.Yarp public System.TimeSpan? ActivityTimeout { get; init; } public bool? AllowResponseBuffering { get; init; } public Duende.Bff.Configuration.BffUserAccessTokenParameters? Parameters { get; init; } - [System.Runtime.CompilerServices.RequiredMember] - public Microsoft.AspNetCore.Http.PathString PathMatch { get; init; } - [System.Runtime.CompilerServices.RequiredMember] - public Duende.Bff.AccessTokenManagement.RequiredTokenType RequiredTokenType { get; init; } - [System.Runtime.CompilerServices.RequiredMember] - public System.Uri TargetUri { get; init; } + public required Microsoft.AspNetCore.Http.PathString PathMatch { get; init; } + public required Duende.Bff.AccessTokenManagement.RequiredTokenType RequiredTokenType { get; init; } + public required System.Uri TargetUri { get; init; } public bool Equals(Duende.Bff.Yarp.RemoteApi? other) { } public override int GetHashCode() { } public Duende.Bff.Yarp.RemoteApi WithAccessToken(Duende.Bff.AccessTokenManagement.RequiredTokenType type) { } diff --git a/bff/test/Bff.Tests/PublicApiVerificationTests.cs b/bff/test/Bff.Tests/PublicApiVerificationTests.cs index b2f7654b1..35016ffb4 100644 --- a/bff/test/Bff.Tests/PublicApiVerificationTests.cs +++ b/bff/test/Bff.Tests/PublicApiVerificationTests.cs @@ -22,7 +22,7 @@ public class PublicApiVerificationTests }; var publicApi = typeof(BffBuilder).Assembly.GeneratePublicApi(apiGeneratorOptions); var settings = new VerifySettings(); - await Verify(publicApi, settings); + _ = await Verify(publicApi, settings); } [Fact] @@ -34,7 +34,7 @@ public class PublicApiVerificationTests }; var publicApi = typeof(AccessTokenRequestTransform).Assembly.GeneratePublicApi(apiGeneratorOptions); var settings = new VerifySettings(); - await Verify(publicApi, settings); + _ = await Verify(publicApi, settings); } [Fact] @@ -46,7 +46,7 @@ public class PublicApiVerificationTests }; var publicApi = typeof(ISessionDbContext).Assembly.GeneratePublicApi(apiGeneratorOptions); var settings = new VerifySettings(); - await Verify(publicApi, settings); + _ = await Verify(publicApi, settings); } [Fact] @@ -58,7 +58,7 @@ public class PublicApiVerificationTests }; var publicApi = typeof(BffBlazorServerOptions).Assembly.GeneratePublicApi(apiGeneratorOptions); var settings = new VerifySettings(); - await Verify(publicApi, settings); + _ = await Verify(publicApi, settings); } @@ -71,7 +71,7 @@ public class PublicApiVerificationTests }; var publicApi = typeof(AntiForgeryHandler).Assembly.GeneratePublicApi(apiGeneratorOptions); var settings = new VerifySettings(); - await Verify(publicApi, settings); + _ = await Verify(publicApi, settings); } } diff --git a/bff/test/Bff.Tests/SessionManagement/CookieSlidingTests.cs b/bff/test/Bff.Tests/SessionManagement/CookieSlidingTests.cs index cdf0de833..3f72631f7 100644 --- a/bff/test/Bff.Tests/SessionManagement/CookieSlidingTests.cs +++ b/bff/test/Bff.Tests/SessionManagement/CookieSlidingTests.cs @@ -22,7 +22,7 @@ public class CookieSlidingTests : BffTestBase { await ConfigureBff(setup, UseSlidingCookieExpiration); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); var sessions = await GetUserSessions(); sessions.Count().ShouldBe(1); @@ -30,13 +30,13 @@ public class CookieSlidingTests : BffTestBase var session = sessions.Single(); var firstTicket = await GetTicket(session.Key.ToString()!); - firstTicket.ShouldNotBeNull(); + _ = firstTicket.ShouldNotBeNull(); AdvanceClock(TimeSpan.FromMinutes(8)); (await Bff.BrowserClient.GetIsUserLoggedInAsync()).ShouldBeTrue(); var secondTicket = await GetTicket(session.Key.ToString()!); - secondTicket.ShouldNotBeNull(); + _ = secondTicket.ShouldNotBeNull(); (secondTicket.Properties.IssuedUtc > firstTicket.Properties.IssuedUtc).ShouldBeTrue(); (secondTicket.Properties.ExpiresUtc > firstTicket.Properties.ExpiresUtc).ShouldBeTrue(); @@ -49,7 +49,7 @@ public class CookieSlidingTests : BffTestBase { await ConfigureBff(setup, UseSlidingCookieExpiration); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); var sessions = await GetUserSessions(); sessions.Count().ShouldBe(1); @@ -57,13 +57,13 @@ public class CookieSlidingTests : BffTestBase var session = sessions.Single(); var firstTicket = await GetTicket(session.Key.ToString()!); - firstTicket.ShouldNotBeNull(); + _ = firstTicket.ShouldNotBeNull(); AdvanceClock(TimeSpan.FromMinutes(8)); (await Bff.BrowserClient.GetIsUserLoggedInAsync("slide=false")).ShouldBeTrue(); var secondTicket = await GetTicket(session.Key.ToString()!); - secondTicket.ShouldNotBeNull(); + _ = secondTicket.ShouldNotBeNull(); (secondTicket.Properties.IssuedUtc == firstTicket.Properties.IssuedUtc).ShouldBeTrue(); (secondTicket.Properties.ExpiresUtc == firstTicket.Properties.ExpiresUtc).ShouldBeTrue(); @@ -89,7 +89,7 @@ public class CookieSlidingTests : BffTestBase }); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); var sessions = await GetUserSessions(); sessions.Count().ShouldBe(1); @@ -97,14 +97,14 @@ public class CookieSlidingTests : BffTestBase var session = sessions.Single(); var firstTicket = await GetTicket(session.Key.ToString()!); - firstTicket.ShouldNotBeNull(); + _ = firstTicket.ShouldNotBeNull(); shouldRenew = true; AdvanceClock(TimeSpan.FromSeconds(1)); (await Bff.BrowserClient.GetIsUserLoggedInAsync()).ShouldBeTrue(); var secondTicket = await GetTicket(session.Key.ToString()!); - secondTicket.ShouldNotBeNull(); + _ = secondTicket.ShouldNotBeNull(); (secondTicket.Properties.IssuedUtc > firstTicket.Properties.IssuedUtc).ShouldBeTrue(); (secondTicket.Properties.ExpiresUtc > firstTicket.Properties.ExpiresUtc).ShouldBeTrue(); @@ -130,7 +130,7 @@ public class CookieSlidingTests : BffTestBase }); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); var sessions = await GetUserSessions(); sessions.Count().ShouldBe(1); @@ -138,14 +138,14 @@ public class CookieSlidingTests : BffTestBase var session = sessions.Single(); var firstTicket = await GetTicket(session.Key.ToString()!); - firstTicket.ShouldNotBeNull(); + _ = firstTicket.ShouldNotBeNull(); shouldRenew = true; AdvanceClock(TimeSpan.FromSeconds(1)); (await Bff.BrowserClient.GetIsUserLoggedInAsync("slide=false")).ShouldBeTrue(); var secondTicket = await GetTicket(session.Key.ToString()!); - secondTicket.ShouldNotBeNull(); + _ = secondTicket.ShouldNotBeNull(); (secondTicket.Properties.IssuedUtc == firstTicket.Properties.IssuedUtc).ShouldBeTrue(); (secondTicket.Properties.ExpiresUtc == firstTicket.Properties.ExpiresUtc).ShouldBeTrue(); diff --git a/bff/test/Bff.Tests/SessionManagement/RevokeRefreshTokenTests.cs b/bff/test/Bff.Tests/SessionManagement/RevokeRefreshTokenTests.cs index 90dc5f9d2..7313dae8d 100644 --- a/bff/test/Bff.Tests/SessionManagement/RevokeRefreshTokenTests.cs +++ b/bff/test/Bff.Tests/SessionManagement/RevokeRefreshTokenTests.cs @@ -16,7 +16,7 @@ public class RevokeRefreshTokenTests : BffTestBase options.Scope.Add("offline_access"); }); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); { var store = IdentityServer.Resolve(); @@ -25,10 +25,10 @@ public class RevokeRefreshTokenTests : BffTestBase SubjectId = The.Sub }); var rt = grants.Single(x => x.Type == "refresh_token"); - rt.ShouldNotBeNull(); + _ = rt.ShouldNotBeNull(); } - await Bff.BrowserClient.Logout(); + _ = await Bff.BrowserClient.Logout(); { var store = IdentityServer.Resolve(); @@ -51,7 +51,7 @@ public class RevokeRefreshTokenTests : BffTestBase Bff.BffOptions.RevokeRefreshTokenOnLogout = false; - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); { var store = IdentityServer.Resolve(); @@ -60,10 +60,10 @@ public class RevokeRefreshTokenTests : BffTestBase SubjectId = The.Sub }); var rt = grants.Single(x => x.Type == "refresh_token"); - rt.ShouldNotBeNull(); + _ = rt.ShouldNotBeNull(); } - await Bff.BrowserClient.Logout(); + _ = await Bff.BrowserClient.Logout(); { var store = IdentityServer.Resolve(); @@ -72,7 +72,7 @@ public class RevokeRefreshTokenTests : BffTestBase SubjectId = The.Sub }); var rt = grants.Single(x => x.Type == "refresh_token"); - rt.ShouldNotBeNull(); + _ = rt.ShouldNotBeNull(); } } @@ -93,7 +93,7 @@ public class RevokeRefreshTokenTests : BffTestBase client.BackChannelLogoutSessionRequired = true; } - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); { var store = IdentityServer.Resolve(); @@ -102,7 +102,7 @@ public class RevokeRefreshTokenTests : BffTestBase SubjectId = The.Sub }); var rt = grants.Single(x => x.Type == "refresh_token"); - rt.ShouldNotBeNull(); + _ = rt.ShouldNotBeNull(); } await Bff.BrowserClient.RevokeIdentityServerSession(); @@ -138,7 +138,7 @@ public class RevokeRefreshTokenTests : BffTestBase client.BackChannelLogoutSessionRequired = true; } - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); { var store = IdentityServer.Resolve(); @@ -147,7 +147,7 @@ public class RevokeRefreshTokenTests : BffTestBase SubjectId = The.Sub }); var rt = grants.Single(x => x.Type == "refresh_token"); - rt.ShouldNotBeNull(); + _ = rt.ShouldNotBeNull(); } await Bff.BrowserClient.RevokeIdentityServerSession(); @@ -159,7 +159,7 @@ public class RevokeRefreshTokenTests : BffTestBase SubjectId = The.Sub }); var rt = grants.Single(x => x.Type == "refresh_token"); - rt.ShouldNotBeNull(); + _ = rt.ShouldNotBeNull(); } } } diff --git a/bff/test/Bff.Tests/SessionManagement/ServerSideTicketStoreTests.cs b/bff/test/Bff.Tests/SessionManagement/ServerSideTicketStoreTests.cs index 8e51b2ab5..c1ab3d063 100644 --- a/bff/test/Bff.Tests/SessionManagement/ServerSideTicketStoreTests.cs +++ b/bff/test/Bff.Tests/SessionManagement/ServerSideTicketStoreTests.cs @@ -12,7 +12,7 @@ public class ServerSideTicketStoreTests : BffTestBase public ServerSideTicketStoreTests() : base() => Bff.OnConfigureBff += bff => { - bff.AddServerSideSessions(); + _ = bff.AddServerSideSessions(); }; [Theory, MemberData(nameof(AllSetups))] @@ -20,12 +20,12 @@ public class ServerSideTicketStoreTests : BffTestBase { Bff.OnConfigureBff += bff => bff.AddServerSideSessions(); await ConfigureBff(setup); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); Bff.BrowserClient.Cookies.Clear(Bff.Url()); (await GetUserSessions()).Count.ShouldBe(1); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); (await GetUserSessions()).Count.ShouldBe(1); } @@ -41,11 +41,11 @@ public class ServerSideTicketStoreTests : BffTestBase .MapToHost(HostHeaderValue.Parse(The.DomainName)); AddOrUpdateFrontend(frontendWithOrigin); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); (await GetUserSessions()).Count.ShouldBe(1); var bffClientForOtherOrigin = Bff.BuildBrowserClient(The.DomainName, Bff.BrowserClient.Cookies); - await bffClientForOtherOrigin.Login(); + _ = await bffClientForOtherOrigin.Login(); (await Bff.BrowserClient.GetIsUserLoggedInAsync("slide=false")).ShouldBeTrue(); (await bffClientForOtherOrigin.GetIsUserLoggedInAsync("slide=false")).ShouldBeTrue(); @@ -71,16 +71,16 @@ public class ServerSideTicketStoreTests : BffTestBase .MapToHost(HostHeaderValue.Parse(The.DomainName)); AddOrUpdateFrontend(frontendWithOrigin); - await Bff.BrowserClient.Login(); + _ = await Bff.BrowserClient.Login(); (await GetUserSessions()).Count.ShouldBe(1); var bffClientForOtherOrigin = Bff.BuildBrowserClient(The.DomainName, Bff.BrowserClient.Cookies); - await bffClientForOtherOrigin.Login(); + _ = await bffClientForOtherOrigin.Login(); (await Bff.BrowserClient.GetIsUserLoggedInAsync("slide=false")).ShouldBeTrue(); (await bffClientForOtherOrigin.GetIsUserLoggedInAsync("slide=false")).ShouldBeTrue(); - await Bff.BrowserClient.Logout(); + _ = await Bff.BrowserClient.Logout(); (await Bff.BrowserClient.GetIsUserLoggedInAsync("slide=false")).ShouldBeFalse(); (await bffClientForOtherOrigin.GetIsUserLoggedInAsync("slide=false")).ShouldBeTrue(); diff --git a/bff/test/Bff.Tests/SessionManagement/ServerSideTokenStoreTests.cs b/bff/test/Bff.Tests/SessionManagement/ServerSideTokenStoreTests.cs index 23ffff2e4..2293fb301 100644 --- a/bff/test/Bff.Tests/SessionManagement/ServerSideTokenStoreTests.cs +++ b/bff/test/Bff.Tests/SessionManagement/ServerSideTokenStoreTests.cs @@ -14,7 +14,6 @@ using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Components.Authorization; using Microsoft.AspNetCore.DataProtection; using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Time.Testing; using NSubstitute; namespace Bff.Tests.Blazor; @@ -59,7 +58,7 @@ public class ServerSideTokenStoreTests HttpContext = new DefaultHttpContext() }, logger: new NullLogger()); - await sessionService.StoreAsync(new AuthenticationTicket( + _ = await sessionService.StoreAsync(new AuthenticationTicket( user, props, "test" @@ -83,7 +82,7 @@ public class ServerSideTokenStoreTests var tokenForParameters = await sut.GetTokenAsync(user).GetToken(); var actualToken = tokenForParameters.TokenForSpecifiedParameters; - actualToken.ShouldNotBeNull(); + _ = actualToken.ShouldNotBeNull(); actualToken.AccessToken.ShouldBe(expectedToken.AccessToken); await sut.ClearTokenAsync(user); diff --git a/bff/test/Bff.Tests/TestFramework/ApiCallDetails.cs b/bff/test/Bff.Tests/TestFramework/ApiCallDetails.cs index 0d2ba9d52..9cd70a020 100644 --- a/bff/test/Bff.Tests/TestFramework/ApiCallDetails.cs +++ b/bff/test/Bff.Tests/TestFramework/ApiCallDetails.cs @@ -47,7 +47,7 @@ internal record ApiCallDetails(HttpMethod Method, string Path, string? Sub, stri public T BodyAs() { - Body.ShouldNotBeNull(); + _ = Body.ShouldNotBeNull(); return JsonSerializer.Deserialize(Body, TestSerializerOptions.Default) ?? throw new NullReferenceException($"result {Body} could not be deserialized to {typeof(T).Name}"); } } diff --git a/bff/test/Bff.Tests/TestInfra/ApiHost.cs b/bff/test/Bff.Tests/TestInfra/ApiHost.cs index efe921d61..b8a2e8d8f 100644 --- a/bff/test/Bff.Tests/TestInfra/ApiHost.cs +++ b/bff/test/Bff.Tests/TestInfra/ApiHost.cs @@ -17,7 +17,7 @@ public class ApiHost : TestHost { OnConfigureServices += services => { - services.AddAuthentication("token") + _ = services.AddAuthentication("token") .AddJwtBearer("token", options => { options.Authority = identityServerUri.Url().ToString(); @@ -29,7 +29,7 @@ public class ApiHost : TestHost OnConfigureApp += app => { - app.Map("/{**catch-all}", + _ = app.Map("/{**catch-all}", async context => { await ReturnApiCallDetails(context, () => ApiStatusCodeToReturn ?? HttpStatusCode.OK); @@ -39,11 +39,11 @@ public class ApiHost : TestHost protected override void ConfigureApp(IApplicationBuilder app) { - app.UseRouting(); + _ = app.UseRouting(); - app.UseAuthentication(); + _ = app.UseAuthentication(); // adds authorization for local and remote API endpoints - app.UseAuthorization(); + _ = app.UseAuthorization(); base.ConfigureApp(app); } diff --git a/bff/test/Bff.Tests/TestInfra/BffHttpClient.cs b/bff/test/Bff.Tests/TestInfra/BffHttpClient.cs index eaa33a0c6..3f32d8d16 100644 --- a/bff/test/Bff.Tests/TestInfra/BffHttpClient.cs +++ b/bff/test/Bff.Tests/TestInfra/BffHttpClient.cs @@ -166,7 +166,7 @@ public class BffHttpClient(RedirectHandler handler, CookieContainer cookies, Ide var claims = await CallUserEndpointAsync(); var sidClaim = claims.FirstOrDefault(c => c.Type == "sid")?.Value; - sidClaim.ShouldNotBeNull(); + _ = sidClaim.ShouldNotBeNull(); var sid = sidClaim.Value.ToString(); return sid; } diff --git a/bff/test/Bff.Tests/TestInfra/BffTestBase.cs b/bff/test/Bff.Tests/TestInfra/BffTestBase.cs index 6fc564f93..3b7068ce4 100644 --- a/bff/test/Bff.Tests/TestInfra/BffTestBase.cs +++ b/bff/test/Bff.Tests/TestInfra/BffTestBase.cs @@ -40,7 +40,7 @@ public abstract class BffTestBase : IAsyncDisposable Api = new ApiHost(Context, IdentityServer); Bff = new BffTestHost(Context, IdentityServer); Cdn = new CdnHost(Context); - IdentityServer.AddClient(DefaultOidcClient.ClientId, Bff.Url()); + _ = IdentityServer.AddClient(DefaultOidcClient.ClientId, Bff.Url()); Some = Context.Some; } @@ -77,11 +77,11 @@ public abstract class BffTestBase : IAsyncDisposable } else if (setup == BffSetupType.V4Bff) { - IdentityServer.AddClient(The.ClientId, Bff.Url()); + _ = IdentityServer.AddClient(The.ClientId, Bff.Url()); Bff.OnConfigureBff += bff => { - bff.ConfigureOpenIdConnect(openIdConfiguration); - bff.ConfigureCookies(options => + _ = bff.ConfigureOpenIdConnect(openIdConfiguration); + _ = bff.ConfigureCookies(options => { configureCookie?.Invoke(options); }); @@ -90,11 +90,11 @@ public abstract class BffTestBase : IAsyncDisposable else if (setup == BffSetupType.ManuallyConfiguredBff) { // Old style setup. Explicitly configuring the authentication including cookie, and openid connect - IdentityServer.AddClient(The.ClientId, Bff.Url()); + _ = IdentityServer.AddClient(The.ClientId, Bff.Url()); Bff.OnConfigureServices += services => { - services.AddAuthentication(options => + _ = services.AddAuthentication(options => { options.DefaultScheme = "cookie"; options.DefaultChallengeScheme = "oidc"; @@ -191,7 +191,7 @@ public abstract class BffTestBase : IAsyncDisposable { baseUris.Add(ToUri(frontend.MatchingCriteria.MatchingHostHeader)); } - IdentityServer.AddClientFor(frontend, baseUris); + _ = IdentityServer.AddClientFor(frontend, baseUris); } public Uri ToUri(HostHeaderValue value) => new UriBuilder @@ -251,4 +251,3 @@ public abstract class BffTestBase : IAsyncDisposable protected void AdvanceClock(TimeSpan by) => The.Clock.SetUtcNow(The.Clock.GetUtcNow().Add(by)); } - diff --git a/bff/test/Bff.Tests/TestInfra/BffTestHost.cs b/bff/test/Bff.Tests/TestInfra/BffTestHost.cs index 0e3b4d831..814b70aef 100644 --- a/bff/test/Bff.Tests/TestInfra/BffTestHost.cs +++ b/bff/test/Bff.Tests/TestInfra/BffTestHost.cs @@ -37,7 +37,7 @@ public class BffTestHost(TestHostContext context, IdentityServerTestHost identit OnConfigureServices += services => { - services.AddSingleton( + _ = services.AddSingleton( new CallbackForwarderHttpClientFactory(context => new HttpMessageInvoker(Internet, false))); var builder = services.AddBff(options => @@ -58,7 +58,7 @@ public class BffTestHost(TestHostContext context, IdentityServerTestHost identit { if (MapGetForRoot) { - app.MapGet("/", () => DefaultRootResponse); + _ = app.MapGet("/", () => DefaultRootResponse); } }; } @@ -81,19 +81,19 @@ public class BffTestHost(TestHostContext context, IdentityServerTestHost identit protected override void ConfigureApp(IApplicationBuilder app) { - app.UseRouting(); - app.Use(async (c, n) => + _ = app.UseRouting(); + _ = app.Use(async (c, n) => { await n(); }); - app.UseAuthentication(); - app.Use(async (c, n) => + _ = app.UseAuthentication(); + _ = app.Use(async (c, n) => { await n(); }); - app.UseAuthorization(); + _ = app.UseAuthorization(); - app.UseBff(); + _ = app.UseBff(); base.ConfigureApp(app); } diff --git a/bff/test/Bff.Tests/TestInfra/CdnHost.cs b/bff/test/Bff.Tests/TestInfra/CdnHost.cs index c2f82028e..f0a468988 100644 --- a/bff/test/Bff.Tests/TestInfra/CdnHost.cs +++ b/bff/test/Bff.Tests/TestInfra/CdnHost.cs @@ -24,19 +24,19 @@ public class CdnHost(TestHostContext context) : TestHost(context, new Uri("https public override void Initialize() => OnConfigureApp += app => { - app.UseAuthentication(); + _ = app.UseAuthentication(); // adds authorization for local and remote API endpoints - app.UseAuthorization(); + _ = app.UseAuthorization(); - app.MapGet("/", () => Results.Content(IndexHtml, "text/html")); - app.MapGet("/index.html", () => Results.Content(IndexHtml, "text/html")); - app.MapGet("/index2.html", () => Results.Content(IndexHtml, "text/html")); - app.MapGet("/image.png", () => Results.File(ImageBytes, "image/png")); + _ = app.MapGet("/", () => Results.Content(IndexHtml, "text/html")); + _ = app.MapGet("/index.html", () => Results.Content(IndexHtml, "text/html")); + _ = app.MapGet("/index2.html", () => Results.Content(IndexHtml, "text/html")); + _ = app.MapGet("/image.png", () => Results.File(ImageBytes, "image/png")); }; protected override void ConfigureApp(IApplicationBuilder app) { - app.UseRouting(); + _ = app.UseRouting(); base.ConfigureApp(app); } } diff --git a/bff/test/Bff.Tests/TestInfra/ConfigFile.cs b/bff/test/Bff.Tests/TestInfra/ConfigFile.cs index 685f988f1..910147361 100644 --- a/bff/test/Bff.Tests/TestInfra/ConfigFile.cs +++ b/bff/test/Bff.Tests/TestInfra/ConfigFile.cs @@ -15,7 +15,7 @@ internal class ConfigFile : IDisposable var dir = Path.GetDirectoryName(_file)!; if (!Directory.Exists(dir)) { - Directory.CreateDirectory(dir); + _ = Directory.CreateDirectory(dir); } } diff --git a/bff/test/Bff.Tests/TestInfra/IdentityServerTestHost.cs b/bff/test/Bff.Tests/TestInfra/IdentityServerTestHost.cs index e8a3cd96f..16ed32c71 100644 --- a/bff/test/Bff.Tests/TestInfra/IdentityServerTestHost.cs +++ b/bff/test/Bff.Tests/TestInfra/IdentityServerTestHost.cs @@ -25,7 +25,7 @@ public class IdentityServerTestHost : TestHost ApiScopes.Add(new ApiScope(The.Scope)); } - services.AddHttpClient(IdentityServerConstants.HttpClients.BackChannelLogoutHttpClient) + _ = services.AddHttpClient(IdentityServerConstants.HttpClients.BackChannelLogoutHttpClient) .ConfigurePrimaryHttpMessageHandler(() => context.Internet); var idsrv = services.AddIdentityServer(options => @@ -37,23 +37,23 @@ public class IdentityServerTestHost : TestHost .AddInMemoryIdentityResources(IdentityResources) .AddInMemoryApiScopes(ApiScopes); - idsrv.AddBackChannelLogoutHttpClient(); + _ = idsrv.AddBackChannelLogoutHttpClient(); }; OnConfigureApp += app => { - app.MapGet("/account/create", context => + _ = app.MapGet("/account/create", context => { return Task.CompletedTask; }); - app.MapGet("/account/login", async ctx => + _ = app.MapGet("/account/login", async ctx => { var props = PropsToSignIn ?? new AuthenticationProperties(); await ctx.SignInAsync(UserToSignIn, props); }); - app.MapGet("/account/logout", async ctx => + _ = app.MapGet("/account/logout", async ctx => { // signout as if the user were prompted await ctx.SignOutAsync(PropsToSignIn); @@ -66,7 +66,7 @@ public class IdentityServerTestHost : TestHost ctx.Response.Redirect(signOutContext.PostLogoutRedirectUri ?? "/"); }); - app.MapGet("/__signin", async ctx => + _ = app.MapGet("/__signin", async ctx => { var props = PropsToSignIn ?? new AuthenticationProperties(); await ctx.SignInAsync(UserToSignIn, props); @@ -74,7 +74,7 @@ public class IdentityServerTestHost : TestHost ctx.Response.StatusCode = 204; }); - app.MapGet("/__signout", async ctx => + _ = app.MapGet("/__signout", async ctx => { var props = PropsToSignIn ?? new AuthenticationProperties(); await ctx.SignOutAsync(props); @@ -88,10 +88,10 @@ public class IdentityServerTestHost : TestHost protected override void ConfigureApp(IApplicationBuilder app) { - app.UseIdentityServer(); - app.UseAuthorization(); + _ = app.UseIdentityServer(); + _ = app.UseAuthorization(); - app.UseRouting(); + _ = app.UseRouting(); base.ConfigureApp(app); } @@ -136,7 +136,7 @@ public class IdentityServerTestHost : TestHost var existing = Clients.FirstOrDefault(c => c.ClientId == clientId); if (existing != null) { - Clients.Remove(existing); + _ = Clients.Remove(existing); } var clientSecret = options.ClientSecret ?? The.ClientSecret; diff --git a/bff/test/Bff.Tests/TestInfra/RoutingMessageHandler.cs b/bff/test/Bff.Tests/TestInfra/RoutingMessageHandler.cs index 9d1502f14..f644efafd 100644 --- a/bff/test/Bff.Tests/TestInfra/RoutingMessageHandler.cs +++ b/bff/test/Bff.Tests/TestInfra/RoutingMessageHandler.cs @@ -22,7 +22,7 @@ public class RoutingMessageHandler : HttpMessageHandler { var endpoint = new HostHandler(handler); var host = $"{hostHeaderValue.Host}:{hostHeaderValue.Port}"; - _hosts.TryAdd(host, endpoint); + _ = _hosts.TryAdd(host, endpoint); } protected override Task SendAsync( diff --git a/bff/test/Bff.Tests/TestInfra/TestData.cs b/bff/test/Bff.Tests/TestInfra/TestData.cs index afc312d0b..a6c65589e 100644 --- a/bff/test/Bff.Tests/TestInfra/TestData.cs +++ b/bff/test/Bff.Tests/TestInfra/TestData.cs @@ -8,7 +8,6 @@ using Duende.Bff.AccessTokenManagement; using Duende.Bff.DynamicFrontends; using Duende.Bff.SessionManagement.SessionStore; using Microsoft.AspNetCore.Authentication.OpenIdConnect; -using Microsoft.Extensions.Time.Testing; using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.Tokens; diff --git a/bff/test/Bff.Tests/TestInfra/TestHost.cs b/bff/test/Bff.Tests/TestInfra/TestHost.cs index da693a549..37119295f 100644 --- a/bff/test/Bff.Tests/TestInfra/TestHost.cs +++ b/bff/test/Bff.Tests/TestInfra/TestHost.cs @@ -98,11 +98,11 @@ public class TestHost(TestHostContext context, Uri baseAddress) : IAsyncDisposab ApplicationName = baseAddress.ToString(), }); - hostBuilder.WebHost.UseTestServer(); + _ = hostBuilder.WebHost.UseTestServer(); ConfigureServices(hostBuilder.Services); - hostBuilder.Logging.ClearProviders(); - hostBuilder.Logging.SetMinimumLevel(LogLevel.Debug); - hostBuilder.Logging.AddProvider(Logger); + _ = hostBuilder.Logging.ClearProviders(); + _ = hostBuilder.Logging.SetMinimumLevel(LogLevel.Debug); + _ = hostBuilder.Logging.AddProvider(Logger); _webApplication = hostBuilder.Build(); Server = (_webApplication.Services.GetRequiredService() as TestServer)!; @@ -118,11 +118,11 @@ public class TestHost(TestHostContext context, Uri baseAddress) : IAsyncDisposab protected virtual void ConfigureServices(IServiceCollection services) { - services.AddSingleton(The.Clock); + _ = services.AddSingleton(The.Clock); - services.AddAuthentication(); - services.AddAuthorization(); - services.AddRouting(); + _ = services.AddAuthentication(); + _ = services.AddAuthorization(); + _ = services.AddRouting(); @@ -133,12 +133,12 @@ public class TestHost(TestHostContext context, Uri baseAddress) : IAsyncDisposab { _appServices = app.ApplicationServices; - app.Use(async (c, n) => + _ = app.Use(async (c, n) => { await n(); }); - app.UseEndpoints(endpoints => + _ = app.UseEndpoints(endpoints => { OnConfigureApp(new BffWebApplication(app, endpoints)); }); diff --git a/bff/test/Bff.Tests/TestInfra/TestHostContext.cs b/bff/test/Bff.Tests/TestInfra/TestHostContext.cs index 01ee6bd82..da0806ef9 100644 --- a/bff/test/Bff.Tests/TestInfra/TestHostContext.cs +++ b/bff/test/Bff.Tests/TestInfra/TestHostContext.cs @@ -12,7 +12,7 @@ public record TestHostContext(ITestOutputHelper OutputHelper) public WriteTestOutput WriteOutput => s => { OutputHelper.WriteLine(_watch.ElapsedMilliseconds.ToString() + "ms - " + s); - LogMessages.AppendLine(s); + _ = LogMessages.AppendLine(s); }; public readonly TestData The = new TestData(); public TestDataBuilder Some => new TestDataBuilder(The); diff --git a/bff/test/Bff.Tests/TestInfra/TestHybridCache.cs b/bff/test/Bff.Tests/TestInfra/TestHybridCache.cs index 24ec0cd22..ae3b6f0cc 100644 --- a/bff/test/Bff.Tests/TestInfra/TestHybridCache.cs +++ b/bff/test/Bff.Tests/TestInfra/TestHybridCache.cs @@ -25,7 +25,7 @@ internal class TestHybridCache : HybridCache RemoveAsync(string key, Ct ct = new Ct()) { _waitUntilRemoveAsyncCalled.Set(); - _cache.TryRemove(key, out _); + _ = _cache.TryRemove(key, out _); return ValueTask.CompletedTask; } @@ -42,7 +42,7 @@ internal class TestHybridCache : HybridCache public void WaitUntilRemoveByTagAsyncCalled(TimeSpan until) { - _waitUntilRemoveByTagAsyncCalled.Wait(until); + _ = _waitUntilRemoveByTagAsyncCalled.Wait(until); if (!_waitUntilRemoveByTagAsyncCalled.IsSet) { throw new TimeoutException(); @@ -51,7 +51,7 @@ internal class TestHybridCache : HybridCache public void WaitUntilRemoveAsyncCalled(TimeSpan until) { - _waitUntilRemoveAsyncCalled.Wait(until); + _ = _waitUntilRemoveAsyncCalled.Wait(until); if (!_waitUntilRemoveAsyncCalled.IsSet) { throw new TimeoutException(); diff --git a/bff/test/Bff.Tests/TestInfra/TestInfraTests.cs b/bff/test/Bff.Tests/TestInfra/TestInfraTests.cs index 7de13de53..1c4526184 100644 --- a/bff/test/Bff.Tests/TestInfra/TestInfraTests.cs +++ b/bff/test/Bff.Tests/TestInfra/TestInfraTests.cs @@ -13,7 +13,7 @@ public class TestInfraTests : BffTestBase await InitializeAsync(); var client = Internet.BuildHttpClient(IdentityServer.Url()); - await client.GetAsync("/account/login") + _ = await client.GetAsync("/account/login") .CheckHttpStatusCode(); } @@ -24,12 +24,12 @@ public class TestInfraTests : BffTestBase await InitializeAsync(); var client = Internet.BuildHttpClient(Bff.Url()); - await client.GetAsync("/bff/login") + _ = await client.GetAsync("/bff/login") .CheckHttpStatusCode(); } private void AddManualOidcFlow(IServiceCollection services) => - services.AddAuthentication(options => + _ = services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; @@ -70,7 +70,7 @@ public class TestInfraTests : BffTestBase { Bff.OnConfigureApp += app => { - app.MapGet("/api/test", async context => + _ = app.MapGet("/api/test", async context => { context.Response.StatusCode = 200; await context.Response.WriteAsync("Hello World"); @@ -81,7 +81,7 @@ public class TestInfraTests : BffTestBase var client = Internet.BuildHttpClient(Bff.Url()); - await client.GetAsync("/api/test") + _ = await client.GetAsync("/api/test") .CheckHttpStatusCode(); } diff --git a/bff/test/Bff.Tests/TestInfra/TestOptionsMonitor.cs b/bff/test/Bff.Tests/TestInfra/TestOptionsMonitor.cs index 4a9692749..1d8687d3c 100644 --- a/bff/test/Bff.Tests/TestInfra/TestOptionsMonitor.cs +++ b/bff/test/Bff.Tests/TestInfra/TestOptionsMonitor.cs @@ -22,7 +22,7 @@ public class TestOptionsMonitor(T value) : IOptionsMonitor _actions.Add(listener); return new DelegateDisposable(() => { - _actions.Remove(listener); + _ = _actions.Remove(listener); }); } diff --git a/bff/test/Directory.Build.props b/bff/test/Directory.Build.props index ea73da2cd..f9dc2ea41 100644 --- a/bff/test/Directory.Build.props +++ b/bff/test/Directory.Build.props @@ -1,8 +1,15 @@ + Duende.$(MSBuildProjectName) $(AssemblyName) + + + $(NoWarn);RS0026 + + + $(NoWarn);RS0027 diff --git a/bff/test/Hosts.Tests/BffBlazorWebAssemblyTests.cs b/bff/test/Hosts.Tests/BffBlazorWebAssemblyTests.cs index dc0c8ffb1..9024dcff1 100644 --- a/bff/test/Hosts.Tests/BffBlazorWebAssemblyTests.cs +++ b/bff/test/Hosts.Tests/BffBlazorWebAssemblyTests.cs @@ -14,7 +14,7 @@ public class BffBlazorWebAssemblyTests(BffHostTestFixture fixture) { public async Task GoToHome() { - await Page.GotoAsync(Fixture.GetUrlTo(AppHostServices.BffBlazorWebassembly).ToString(), Defaults.PageGotoOptions); + _ = await Page.GotoAsync(Fixture.GetUrlTo(AppHostServices.BffBlazorWebassembly).ToString(), Defaults.PageGotoOptions); return new WebAssemblyPageModel() { Page = Page @@ -31,7 +31,7 @@ public class BffBlazorWebAssemblyTests(BffHostTestFixture fixture) await homePage.VerifyNotLoggedIn(); - await homePage.Login(); + _ = await homePage.Login(); await homePage.VerifyLoggedIn(); @@ -39,7 +39,7 @@ public class BffBlazorWebAssemblyTests(BffHostTestFixture fixture) await weatherPage.VerifyWeatherListIsShown(); - await homePage.LogOut(); + _ = await homePage.LogOut(); } private async Task Warmup() diff --git a/bff/test/Hosts.Tests/BlazorPerComponentTests.cs b/bff/test/Hosts.Tests/BlazorPerComponentTests.cs index 90b7a3b11..e6d0a0ab4 100644 --- a/bff/test/Hosts.Tests/BlazorPerComponentTests.cs +++ b/bff/test/Hosts.Tests/BlazorPerComponentTests.cs @@ -14,7 +14,7 @@ public class BlazorPerComponentTests(BffHostTestFixture fixture) public async Task GoToHome() { - await Page.GotoAsync(Fixture.GetUrlTo(AppHostServices.BffBlazorPerComponent).ToString(), Defaults.PageGotoOptions); + _ = await Page.GotoAsync(Fixture.GetUrlTo(AppHostServices.BffBlazorPerComponent).ToString(), Defaults.PageGotoOptions); return new PerComponentPageModel() { Page = Page @@ -27,7 +27,7 @@ public class BlazorPerComponentTests(BffHostTestFixture fixture) await Warmup(); var homePage = await GoToHome(); - await homePage.Login(); + _ = await homePage.Login(); var callApiPage = await homePage.GoToCallApiPage(); diff --git a/bff/test/Hosts.Tests/Hosts.Tests.csproj b/bff/test/Hosts.Tests/Hosts.Tests.csproj index 9ae982da3..c347c7f29 100644 --- a/bff/test/Hosts.Tests/Hosts.Tests.csproj +++ b/bff/test/Hosts.Tests/Hosts.Tests.csproj @@ -1,5 +1,4 @@ - net10.0 enable @@ -7,36 +6,29 @@ Debug;Release;Debug_ncrunch Hosts.Tests - $(DefineConstants);DEBUG_NCRUNCH - - - - - + + + + - - - - - diff --git a/bff/test/Hosts.Tests/PageModels/PerComponentPageModel.cs b/bff/test/Hosts.Tests/PageModels/PerComponentPageModel.cs index 89e990c26..0a4165c1e 100644 --- a/bff/test/Hosts.Tests/PageModels/PerComponentPageModel.cs +++ b/bff/test/Hosts.Tests/PageModels/PerComponentPageModel.cs @@ -37,7 +37,7 @@ public class CallApiPageModel : PerComponentPageModel var parentDiv = heading.Locator("xpath=ancestor::div[@class='col']").First; // Assert that the parent div is found - parentDiv.ShouldNotBeNull(); + _ = parentDiv.ShouldNotBeNull(); var button = parentDiv.GetByRole(AriaRole.Button, new() { Name = "Call Api" }); await button.ClickAsync(); diff --git a/bff/test/Hosts.Tests/Templates/BffBlazorTemplateTests.cs b/bff/test/Hosts.Tests/Templates/BffBlazorTemplateTests.cs index 28d12fbdf..abe142844 100644 --- a/bff/test/Hosts.Tests/Templates/BffBlazorTemplateTests.cs +++ b/bff/test/Hosts.Tests/Templates/BffBlazorTemplateTests.cs @@ -14,7 +14,7 @@ public class BffBlazorTemplateTests(BffHostTestFixture fixture) { public async Task GoToHome() { - await Page.GotoAsync(Fixture.GetUrlTo(AppHostServices.TemplateBffBlazor).ToString(), Defaults.PageGotoOptions); + _ = await Page.GotoAsync(Fixture.GetUrlTo(AppHostServices.TemplateBffBlazor).ToString(), Defaults.PageGotoOptions); return new WebAssemblyPageModel() { Page = Page @@ -28,7 +28,7 @@ public class BffBlazorTemplateTests(BffHostTestFixture fixture) var homePage = await GoToHome(); - await homePage.Login(); + _ = await homePage.Login(); var weatherPage = await homePage.GoToWeather(); diff --git a/conformance-report/build.cs b/conformance-report/build.cs new file mode 100644 index 000000000..a21b0e597 --- /dev/null +++ b/conformance-report/build.cs @@ -0,0 +1,25 @@ +#:project ../.github/build/BuildHelpers.csproj + +using BuildHelpers; +using static Bullseye.Targets; + +var repoRoot = Repo.FindRoot(); + +Targets.Shared(repoRoot, "conformance-report/conformance-report.slnf"); + +const string TestsConformanceReportTests = "tests-conformance-report-tests"; + +Targets.Test(TestsConformanceReportTests, "conformance-report/test/ConformanceReport.Tests", repoRoot); + +Target(SharedTargets.Default, [ + SharedTargets.CheckSolutions, + SharedTargets.CheckUnusedPackages, + SharedTargets.CheckSortedRefs, + SharedTargets.VerifyFormatting, + SharedTargets.Clean, + SharedTargets.VerifyNoChanges, + SharedTargets.DotnetDevCerts, + TestsConformanceReportTests +]); + +await RunTargetsAndExitAsync(args); diff --git a/conformance-report/src/ConformanceReport/ConformanceReport.csproj b/conformance-report/src/ConformanceReport/ConformanceReport.csproj index 98988d2ff..bf2444356 100644 --- a/conformance-report/src/ConformanceReport/ConformanceReport.csproj +++ b/conformance-report/src/ConformanceReport/ConformanceReport.csproj @@ -6,6 +6,8 @@ Conformance assessment for FAPI 2.0 and OAuth 2.1 profiles true false + + Generated Library $(NoWarn);NETSDK1086 diff --git a/conformance-report/src/Directory.Build.props b/conformance-report/src/Directory.Build.props index 7074fd1f9..803971578 100644 --- a/conformance-report/src/Directory.Build.props +++ b/conformance-report/src/Directory.Build.props @@ -1,4 +1,5 @@ + enable diff --git a/conformance-report/src/Directory.Build.targets b/conformance-report/src/Directory.Build.targets new file mode 100644 index 000000000..acbac1881 --- /dev/null +++ b/conformance-report/src/Directory.Build.targets @@ -0,0 +1,4 @@ + + + + diff --git a/conformance-report/test/Directory.Build.props b/conformance-report/test/Directory.Build.props index 8a724a8b3..689890199 100644 --- a/conformance-report/test/Directory.Build.props +++ b/conformance-report/test/Directory.Build.props @@ -1,4 +1,5 @@ + enable diff --git a/docs-mcp/build.cs b/docs-mcp/build.cs new file mode 100644 index 000000000..2c65a0514 --- /dev/null +++ b/docs-mcp/build.cs @@ -0,0 +1,20 @@ +#:project ../.github/build/BuildHelpers.csproj + +using BuildHelpers; +using static Bullseye.Targets; + +var repoRoot = Repo.FindRoot(); + +Targets.Shared(repoRoot, "docs-mcp/docs-mcp.slnf"); + +Target(SharedTargets.Default, [ + SharedTargets.CheckSolutions, + SharedTargets.CheckUnusedPackages, + SharedTargets.CheckSortedRefs, + SharedTargets.VerifyFormatting, + SharedTargets.Clean, + SharedTargets.VerifyNoChanges, + SharedTargets.DotnetDevCerts +]); + +await RunTargetsAndExitAsync(args); diff --git a/docs-mcp/docs-mcp.slnf b/docs-mcp/docs-mcp.slnf index 2e03d2bb7..052f8b65f 100644 --- a/docs-mcp/docs-mcp.slnf +++ b/docs-mcp/docs-mcp.slnf @@ -2,7 +2,6 @@ "solution": { "path": "..\\products.slnx", "projects": [ - ".github\\workflow-gen\\workflow-gen.csproj", "docs-mcp\\src\\Documentation.Mcp\\Documentation.Mcp.csproj" ] } diff --git a/docs-mcp/src/Directory.Build.props b/docs-mcp/src/Directory.Build.props index d50713caa..690b48359 100644 --- a/docs-mcp/src/Directory.Build.props +++ b/docs-mcp/src/Directory.Build.props @@ -1,15 +1,14 @@ + - All OAuth 2.0;OpenID Connect;Security;Identity;IdentityServer;ASP.NET Core Duende Documentation MCP Server dmcp- 1.0 enable - $(NoWarn);CA2007 diff --git a/docs-mcp/src/Directory.Build.targets b/docs-mcp/src/Directory.Build.targets new file mode 100644 index 000000000..acbac1881 --- /dev/null +++ b/docs-mcp/src/Directory.Build.targets @@ -0,0 +1,4 @@ + + + + diff --git a/docs-mcp/src/Documentation.Mcp/Database/McpDb.cs b/docs-mcp/src/Documentation.Mcp/Database/McpDb.cs index b88c9d666..28f0f5eaf 100644 --- a/docs-mcp/src/Documentation.Mcp/Database/McpDb.cs +++ b/docs-mcp/src/Documentation.Mcp/Database/McpDb.cs @@ -21,7 +21,7 @@ internal sealed class McpDb(DbContextOptions options) : DbContext(options var stateEntity = await State.FirstOrDefaultAsync(it => it.Key == key); if (stateEntity == null) { - State.Add(new State + _ = State.Add(new State { Id = Guid.NewGuid().ToString(), Key = key, @@ -33,7 +33,7 @@ internal sealed class McpDb(DbContextOptions options) : DbContext(options stateEntity.Value = JsonSerializer.Serialize(value); } - await SaveChangesAsync(); + _ = await SaveChangesAsync(); } public async Task GetLastUpdateStateAsync(string key) diff --git a/docs-mcp/src/Documentation.Mcp/Database/Migrations/.editorconfig b/docs-mcp/src/Documentation.Mcp/Database/Migrations/.editorconfig new file mode 100644 index 000000000..98e806338 --- /dev/null +++ b/docs-mcp/src/Documentation.Mcp/Database/Migrations/.editorconfig @@ -0,0 +1,2 @@ +[*.cs] +dotnet_diagnostic.IDE0058.severity = none diff --git a/docs-mcp/src/Documentation.Mcp/Sources/Blog/BlogArticleIndexer.cs b/docs-mcp/src/Documentation.Mcp/Sources/Blog/BlogArticleIndexer.cs index 8dc18fced..f3aa965fb 100644 --- a/docs-mcp/src/Documentation.Mcp/Sources/Blog/BlogArticleIndexer.cs +++ b/docs-mcp/src/Documentation.Mcp/Sources/Blog/BlogArticleIndexer.cs @@ -60,14 +60,14 @@ internal sealed class BlogArticleIndexer(IServiceProvider services, ILogger it.PublishDate >= ReferenceDate && it.Categories?.Contains("blog") == true).ToList(); - await db.FTSBlogArticle.ExecuteDeleteAsync(stoppingToken); + _ = await db.FTSBlogArticle.ExecuteDeleteAsync(stoppingToken); foreach (var filteredItem in filteredItems) { await RunIndexerForDocumentAsync(filteredItem.Title ?? "", filteredItem.GetSummary(), filteredItem.Uri, db, httpClient, stoppingToken); } - await db.SaveChangesAsync(stoppingToken); + _ = await db.SaveChangesAsync(stoppingToken); logger.LogInformation("Saved {Count} blog articles", db.FTSBlogArticle.Count()); await db.SetLastUpdateStateAsync("blog", DateTimeOffset.UtcNow); @@ -102,7 +102,7 @@ internal sealed class BlogArticleIndexer(IServiceProvider services, ILogger()) { @@ -69,7 +69,7 @@ internal sealed class DocsArticleIndexer(IServiceProvider services, ILogger 0) { - db.FTSSampleProject.Add(new FTSSampleProject + _ = db.FTSSampleProject.Add(new FTSSampleProject { Id = Guid.NewGuid().ToString(), Product = "IdentityServer", @@ -99,7 +99,7 @@ internal sealed class SamplesIndexer(IServiceProvider services, ILogger 0) { - db.FTSSampleProject.Add(new FTSSampleProject + _ = db.FTSSampleProject.Add(new FTSSampleProject { Id = Guid.NewGuid().ToString(), Product = "IdentityServer", @@ -131,7 +131,7 @@ internal sealed class SamplesIndexer(IServiceProvider services, ILogger - - - - true - false - false - true - true - $(NoWarn);CS1591 - - - - - true - true - - - - - - diff --git a/identity-server/.vscode/launch.json b/identity-server/.vscode/launch.json deleted file mode 100644 index 1859a8908..000000000 --- a/identity-server/.vscode/launch.json +++ /dev/null @@ -1,658 +0,0 @@ -{ - "version": "0.2.0", - "compounds": [ - { - "name": "main host, mvc.code client", - "configurations": ["host: main", "client: MvcCode"], - "presentation": { - "hidden": false, - "group": "10-compunds", - // "order": 10 - } - }, - { - "name": "main host, simple api", - "configurations": ["host: main", "api: Simple"], - "presentation": { - "hidden": false, - "group": "10-compunds", - // "order": 10 - } - } - ], - "configurations": [ - //------- - // Hosts - //------- - { - "name": "host: main", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-host-main", - "program": "${workspaceFolder}/hosts/main/bin/Debug/net8.0/Host.Main.dll", - "args": [], - "cwd": "${workspaceFolder}/hosts/main", - "env": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "10-hosts", - "order": 10 - } - }, - { - "name": "host: AspNetIdentity", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-host-aspnetidentity", - "program": "${workspaceFolder}/hosts/AspNetIdentity/bin/Debug/net8.0/Host.AspNetIdentity.dll", - "args": [], - "cwd": "${workspaceFolder}/hosts/AspNetIdentity", - "env": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "10-hosts", - "order": 30 - } - }, - { - "name": "host: EntityFramework (dotnet 8)", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-host-entityframework-8", - "program": "${workspaceFolder}/hosts/EntityFramework/bin/Debug/net8.0/Host.EntityFramework.dll", - "args": [], - "cwd": "${workspaceFolder}/hosts/EntityFramework", - "env": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "10-hosts", - "order": 40 - } - }, - { - "name": "host: EntityFramework (dotnet 9)", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-host-entityframework-9", - "program": "${workspaceFolder}/hosts/EntityFramework-dotnet9/bin/Debug/net9.0/Host.EntityFramework.dotnet9.dll", - "args": [], - "cwd": "${workspaceFolder}/hosts/EntityFramework-dotnet9", - "env": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "10-hosts", - "order": 40 - } - }, - { - "name": "host: Configuration", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-host-configuration", - "program": "${workspaceFolder}/hosts/Configuration/bin/Debug/net8.0/Host.Configuration.dll", - "args": [], - "cwd": "${workspaceFolder}/hosts/Configuration", - "env": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "10-hosts", - "order": 50 - } - }, - //------------ - // Migrations - //------------ - { - "name": "migration: IdentityServer", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-migration-identityServerDb", - "program": "${workspaceFolder}/migrations/IdentityServerDb/bin/Debug/net8.0/IdentityServerDb.dll", - "args": [], - "cwd": "${workspaceFolder}/migrations/IdentityServerDb", - "env": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "migrations", - // "order": 10 - } - }, - { - "name": "migration: AspNetIdentity", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-migration-aspNetIdentityDb", - "program": "${workspaceFolder}/migrations/AspNetIdentityDb/bin/Debug/net8.0/AspNetIdentityDb.dll", - "args": [], - "cwd": "${workspaceFolder}/migrations/AspNetIdentityDb", - "env": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "migrations", - // "order": 20 - } - }, - //--------- - // Clients - //--------- - { - "name": "client: ConsoleCibaClient", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-ConsoleCibaClient", - "program": "${workspaceFolder}/clients/src/ConsoleCibaClient/bin/Debug/net8.0/ConsoleCibaClient.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/ConsoleCibaClient", - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: ConsoleClientCredentialsFlow", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-ConsoleClientCredentialsFlow", - "program": "${workspaceFolder}/clients/src/ConsoleClientCredentialsFlow/bin/Debug/net8.0/ConsoleClientCredentialsFlow.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/ConsoleClientCredentialsFlow", - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: ConsoleClientCredentialsFlowCallingIdentityServerApi", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-ConsoleClientCredentialsFlowCallingIdentityServerApi", - "program": "${workspaceFolder}/clients/src/ConsoleClientCredentialsFlowCallingIdentityServerApi/bin/Debug/net8.0/ConsoleClientCredentialsFlowCallingIdentityServerApi.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/ConsoleClientCredentialsFlowCallingIdentityServerApi", - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: ConsoleClientCredentialsFlowDPoP", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-ConsoleClientCredentialsFlowDPoP", - "program": "${workspaceFolder}/clients/src/ConsoleClientCredentialsFlowDPoP/bin/Debug/net8.0/ConsoleClientCredentialsFlowDPoP.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/ConsoleClientCredentialsFlowDPoP", - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: ConsoleClientCredentialsFlowPostBody", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-ConsoleClientCredentialsFlowPostBody", - "program": "${workspaceFolder}/clients/src/ConsoleClientCredentialsFlowPostBody/bin/Debug/net8.0/ConsoleClientCredentialsFlowPostBody.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/ConsoleClientCredentialsFlowPostBody", - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: ConsoleCode", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-ConsoleCode", - "program": "${workspaceFolder}/clients/src/ConsoleCode/bin/Debug/net8.0/ConsoleCode.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/ConsoleCode", - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: ConsoleCustomGrant", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-ConsoleCustomGrant", - "program": "${workspaceFolder}/clients/src/ConsoleCustomGrant/bin/Debug/net8.0/ConsoleExtensionGrant.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/ConsoleCustomGrant", - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: ConsoleDcrClient", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-ConsoleDcrClient", - "program": "${workspaceFolder}/clients/src/ConsoleDcrClient/bin/Debug/net8.0/ConsoleDcrClient.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/ConsoleDcrClient", - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: ConsoleDeviceFlow", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-ConsoleDeviceFlow", - "program": "${workspaceFolder}/clients/src/ConsoleDeviceFlow/bin/Debug/net8.0/ConsoleDeviceFlow.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/ConsoleDeviceFlow", - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: ConsoleEphemeralMtlsClient", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-ConsoleEphemeralMtlsClient", - "program": "${workspaceFolder}/clients/src/ConsoleEphemeralMtlsClient/bin/Debug/net8.0/ConsoleEphemeralMtlsClient.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/ConsoleEphemeralMtlsClient", - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: ConsoleIntrospectionClient", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-ConsoleIntrospectionClient", - "program": "${workspaceFolder}/clients/src/ConsoleIntrospectionClient/bin/Debug/net8.0/ConsoleIntrospectionClient.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/ConsoleIntrospectionClient", - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: ConsoleMTLSClient", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-ConsoleMTLSClient", - "program": "${workspaceFolder}/clients/src/ConsoleMTLSClient/bin/Debug/net8.0/ConsoleMTLSClient.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/ConsoleMTLSClient", - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: ConsoleParameterizedScopeClient", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-ConsoleParameterizedScopeClient", - "program": "${workspaceFolder}/clients/src/ConsoleParameterizedScopeClient/bin/Debug/net8.0/ConsoleParameterizedScopeClient.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/ConsoleParameterizedScopeClient", - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: ConsolePrivateKeyJwtClient", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-ConsolePrivateKeyJwtClient", - "program": "${workspaceFolder}/clients/src/ConsolePrivateKeyJwtClient/bin/Debug/net8.0/ConsolePrivateKeyJwtClient.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/ConsolePrivateKeyJwtClient", - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: ConsoleResourceIndicators", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-ConsoleResourceIndicators", - "program": "${workspaceFolder}/clients/src/ConsoleResourceIndicators/bin/Debug/net8.0/ConsoleResourceIndicators.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/ConsoleResourceIndicators", - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: ConsoleResourceOwnerFlow", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-ConsoleResourceOwnerFlow", - "program": "${workspaceFolder}/clients/src/ConsoleResourceOwnerFlow/bin/Debug/net8.0/ConsoleResourceOwnerFlow.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/ConsoleResourceOwnerFlow", - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: ConsoleResourceOwnerFlowPublic", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-ConsoleResourceOwnerFlowPublic", - "program": "${workspaceFolder}/clients/src/ConsoleResourceOwnerFlowPublic/bin/Debug/net8.0/ConsoleResourceOwnerFlowPublic.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/ConsoleResourceOwnerFlowPublic", - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: ConsoleResourceOwnerFlowReference", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-ConsoleResourceOwnerFlowReference", - "program": "${workspaceFolder}/clients/src/ConsoleResourceOwnerFlowReference/bin/Debug/net8.0/ConsoleResourceOwnerFlowReference.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/ConsoleResourceOwnerFlowReference", - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: ConsoleResourceOwnerFlowRefreshToken", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-ConsoleResourceOwnerFlowRefreshToken", - "program": "${workspaceFolder}/clients/src/ConsoleResourceOwnerFlowRefreshToken/bin/Debug/net8.0/ConsoleResourceOwnerFlowRefreshToken.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/ConsoleResourceOwnerFlowRefreshToken", - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: ConsoleResourceOwnerFlowUserInfo", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-ConsoleResourceOwnerFlowUserInfo", - "program": "${workspaceFolder}/clients/src/ConsoleResourceOwnerFlowUserInfo/bin/Debug/net8.0/ConsoleResourceOwnerFlowUserInfo.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/ConsoleResourceOwnerFlowUserInfo", - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: ConsoleScopesResources", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-ConsoleScopesResources", - "program": "${workspaceFolder}/clients/src/ConsoleScopesResources/bin/Debug/net8.0/ConsoleScopesResources.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/ConsoleScopesResources", - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: JsOidc", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-JsOidc", - "program": "${workspaceFolder}/clients/src/JsOidc/bin/Debug/net8.0/JsOidc.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/JsOidc", - "env": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: MvcAutomaticTokenManagement", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-MvcAutomaticTokenManagement", - "program": "${workspaceFolder}/clients/src/MvcAutomaticTokenManagement/bin/Debug/net9.0/MvcAutomaticTokenManagement.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/MvcAutomaticTokenManagement", - "env": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "presentation": { - "hidden": false, - "group": "20-clients", - }, - "console": "integratedTerminal" - }, - { - "name": "client: MvcCode", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-MvcCode", - "program": "${workspaceFolder}/clients/src/MvcCode/bin/Debug/net9.0/MvcCode.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/MvcCode", - "env": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "presentation": { - "hidden": false, - "group": "20-clients", - }, - "console": "integratedTerminal" - }, - { - "name": "client: MvcDPoP", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-MvcDPoP", - "program": "${workspaceFolder}/clients/src/MvcDPoP/bin/Debug/net9.0/MvcDPoP.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/MvcDPoP", - "env": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "20-clients", - }, - }, - { - "name": "client: MvcHybridBackChannel", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-MvcHybridBackChannel", - "program": "${workspaceFolder}/clients/src/MvcHybridBackChannel/bin/Debug/net9.0/MvcHybridBackChannel.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/MvcHybridBackChannel", - "console": "integratedTerminal", - "env": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: MvcJarJwt", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-MvcJarJwt", - "program": "${workspaceFolder}/clients/src/MvcJarJwt/bin/Debug/net9.0/MvcJarJwt.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/MvcJarJwt", - "console": "integratedTerminal", - "env": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: MvcJarUriJwt", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-client-MvcJarUriJwt", - "program": "${workspaceFolder}/clients/src/MvcJarUriJwt/bin/Debug/net9.0/MvcJarUriJwt.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/MvcJarUriJwt", - "env": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - { - "name": "client: WindowsConsoleSystemBrowser", - "type": "clr", - "request": "launch", - "preLaunchTask": "build-client-WindowsConsoleSystemBrowser", - "program": "${workspaceFolder}/clients/src/WindowsConsoleSystemBrowser/bin/Debug/net472/WindowsConsoleSystemBrowser.exe", - "args": [], - "cwd": "${workspaceFolder}/clients/src/WindowsConsoleSystemBrowser", - "console": "integratedTerminal", - "presentation": { - "hidden": false, - "group": "20-clients", - } - }, - - //------ - // APIs - //------ - { - "name": "api: Simple", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-api-simple", - "program": "${workspaceFolder}/clients/src/APIs/SimpleApi/bin/Debug/net9.0/SimpleApi.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/APIs/SimpleApi", - "console": "integratedTerminal", - "env": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "presentation": { - "hidden": false, - "group": "15-apis", - } - }, - { - "name": "api: DPoP", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-api-dpop", - "program": "${workspaceFolder}/clients/src/APIs/DPoPApi/bin/Debug/net9.0/DPoPApi.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/APIs/DPoPApi", - "console": "integratedTerminal", - "env": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "presentation": { - "hidden": false, - "group": "15-apis", - } - }, - { - "name": "api: Resource Based", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-api-resourceBased", - "program": "${workspaceFolder}/clients/src/APIs/ResourceBasedApi/bin/Debug/net9.0/ResourceBasedApi.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/APIs/ResourceBasedApi", - "env": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "presentation": { - "hidden": false, - "group": "15-apis", - }, - "console": "integratedTerminal" - }, - { - "name": "api: mTLS", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-api-mtls", - "program": "${workspaceFolder}/clients/src/APIs/MtlsApi/bin/Debug/net9.0/MtlsApi.dll", - "args": [], - "cwd": "${workspaceFolder}/clients/src/APIs/MtlsApi", - "env": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "presentation": { - "hidden": false, - "group": "15-apis", - }, - "console": "integratedTerminal" - }, - ], -} diff --git a/identity-server/.vscode/tasks.json b/identity-server/.vscode/tasks.json deleted file mode 100644 index 1a28530fc..000000000 --- a/identity-server/.vscode/tasks.json +++ /dev/null @@ -1,515 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - //----------------- - // Full solution - //----------------- - { - "label": "build", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/Duende.IdentityServer.sln", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - - //------- - // Hosts - //------- - { - "label": "build-host-main", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/hosts/main/Host.Main.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-host-entityframework-8", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/hosts/EntityFramework/Host.EntityFramework.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-host-entityframework-9", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/hosts/EntityFramework-dotnet9/Host.EntityFramework.dotnet9.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-host-aspnetidentity", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/hosts/AspNetIdentity/Host.AspNetIdentity.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-host-configuration", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/hosts/Configuration/Host.Configuration.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - //------------ - // Migrations - //------------ - { - "label": "build-migration-identityServerDb", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/migrations/IdentityServerDb/IdentityServerDb.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-migration-aspNetIdentityDb", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/migrations/AspNetIdentityDb/AspNetIdentityDb.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - - //--------- - // Clients - //--------- - { - "label": "build-client-ConsoleCibaClient", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/ConsoleCibaClient/ConsoleCibaClient.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-ConsoleClientCredentialsFlow", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/ConsoleClientCredentialsFlow/ConsoleClientCredentialsFlow.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-ConsoleClientCredentialsFlowCallingIdentityServerApi", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/ConsoleClientCredentialsFlowCallingIdentityServerApi/ConsoleClientCredentialsFlowCallingIdentityServerApi.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-ConsoleClientCredentialsFlowDPoP", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/ConsoleClientCredentialsFlowDPoP/ConsoleClientCredentialsFlowDPoP.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-ConsoleClientCredentialsFlowPostBody", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/ConsoleClientCredentialsFlowPostBody/ConsoleClientCredentialsFlowPostBody.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-ConsoleCode", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/ConsoleCode/ConsoleCode.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-ConsoleCustomGrant", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/ConsoleCustomGrant/ConsoleExtensionGrant.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-ConsoleDcrClient", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/ConsoleDcrClient/ConsoleDcrClient.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-ConsoleDeviceFlow", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/ConsoleDeviceFlow/ConsoleDeviceFlow.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-ConsoleEphemeralMtlsClient", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/ConsoleEphemeralMtlsClient/ConsoleEphemeralMtlsClient.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-ConsoleIntrospectionClient", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/ConsoleIntrospectionClient/ConsoleIntrospectionClient.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-ConsoleMTLSClient", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/ConsoleMTLSClient/ConsoleMTLSClient.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-ConsoleParameterizedScopeClient", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/ConsoleParameterizedScopeClient/ConsoleParameterizedScopeClient.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-ConsolePrivateKeyJwtClient", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/ConsolePrivateKeyJwtClient/ConsolePrivateKeyJwtClient.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-ConsoleResourceIndicators", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/ConsoleResourceIndicators/ConsoleResourceIndicators.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-ConsoleResourceOwnerFlow", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/ConsoleResourceOwnerFlow/ConsoleResourceOwnerFlow.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-ConsoleResourceOwnerFlowPublic", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/ConsoleResourceOwnerFlowPublic/ConsoleResourceOwnerFlowPublic.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-ConsoleResourceOwnerFlowReference", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/ConsoleResourceOwnerFlowReference/ConsoleResourceOwnerFlowReference.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-ConsoleResourceOwnerFlowRefreshToken", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/ConsoleResourceOwnerFlowRefreshToken/ConsoleResourceOwnerFlowRefreshToken.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-ConsoleResourceOwnerFlowUserInfo", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/ConsoleResourceOwnerFlowUserInfo/ConsoleResourceOwnerFlowUserInfo.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-ConsoleScopesResources", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/ConsoleScopesResources/ConsoleScopesResources.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-JsOidc", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/JsOidc/JsOidc.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-MvcAutomaticTokenManagement", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/MvcAutomaticTokenManagement/MvcAutomaticTokenManagement.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-MvcCode", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/MvcCode/MvcCode.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-MvcDPoP", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/MvcDPoP/MvcDPoP.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-MvcHybridBackChannel", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/MvcHybridBackChannel/MvcHybridBackChannel.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-MvcJarJwt", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/MvcJarJwt/MvcJarJwt.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-MvcJarUriJwt", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/MvcJarUriJwt/MvcJarUriJwt.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-client-WindowsConsoleSystemBrowser", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/WindowsConsoleSystemBrowser/WindowsConsoleSystemBrowser.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - - //------ - // APIs - //------ - { - "label": "build-api-simple", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/APIs/SimpleApi/SimpleApi.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-api-dpop", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/APIs/DPoPApi/DPoPApi.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-api-resourceBased", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/APIs/ResourceBasedApi/ResourceBasedApi.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-api-mtls", - "type": "process", - "command": "dotnet", - "args": [ - "build", - "${workspaceFolder}/clients/src/APIs/MtlsApi/MtlsApi.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - } - ] -} diff --git a/identity-server/Duende.IdentityServer.v3.ncrunchsolution b/identity-server/Duende.IdentityServer.v3.ncrunchsolution deleted file mode 100644 index 13107d394..000000000 --- a/identity-server/Duende.IdentityServer.v3.ncrunchsolution +++ /dev/null @@ -1,8 +0,0 @@ - - - True - True - True - True - - \ No newline at end of file diff --git a/identity-server/aspire/AppHosts/All/All.csproj b/identity-server/aspire/AppHosts/All/All.csproj index 454b3eab2..c0bbe258a 100644 --- a/identity-server/aspire/AppHosts/All/All.csproj +++ b/identity-server/aspire/AppHosts/All/All.csproj @@ -2,12 +2,10 @@ Exe - net10.0 - enable enable true b86a3528-3d86-4514-b57f-9839f472ef31 - true + diff --git a/identity-server/aspire/AppHosts/All/Program.cs b/identity-server/aspire/AppHosts/All/Program.cs index fd091b320..c0ca34947 100644 --- a/identity-server/aspire/AppHosts/All/Program.cs +++ b/identity-server/aspire/AppHosts/All/Program.cs @@ -67,7 +67,7 @@ void ConfigureIdentityServerHosts() var aspnetMigration = builder.AddProject(name: "aspnetidentitydb-migrations") .WithReference(identityServerDb, connectionName: "DefaultConnection") .WaitFor(identityServerDb); - hostAspNetIdentity.WaitForCompletion(aspnetMigration); + _ = hostAspNetIdentity.WaitForCompletion(aspnetMigration); } projectRegistry.Add("is-host", hostAspNetIdentity); @@ -84,7 +84,7 @@ void ConfigureIdentityServerHosts() var idSrvMigration = builder.AddProject(name: "identityserverdb-migrations") .WithReference(identityServerDb, connectionName: "DefaultConnection") .WaitFor(identityServerDb); - hostEntityFramework.WaitForCompletion(idSrvMigration); + _ = hostEntityFramework.WaitForCompletion(idSrvMigration); } projectRegistry.Add("is-host", hostEntityFramework); @@ -111,46 +111,46 @@ void ConfigureClients() void ConfigureWebClients() { - RegisterClientIfEnabled("mvc-code"); - RegisterClientIfEnabled("mvc-dpop"); - RegisterClientIfEnabled("js-oidc"); - RegisterClientIfEnabled("mvc-automatic-token-management"); - RegisterClientIfEnabled("mvc-hybrid-backchannel"); - RegisterClientIfEnabled("mvc-jar-jwt"); - RegisterClientIfEnabled("mvc-jar-uri-jwt"); - RegisterClientIfEnabled("mvc-saml"); - RegisterClientIfEnabled("web"); - RegisterTemplateIfEnabled("template-is", 7001); - RegisterTemplateIfEnabled("template-is-empty", 7002); - RegisterTemplateIfEnabled("template-is-inmem", 7003); - RegisterTemplateIfEnabled("template-is-aspid", 7004); - RegisterTemplateIfEnabled("template-is-ef", 7005); + _ = RegisterClientIfEnabled("mvc-code"); + _ = RegisterClientIfEnabled("mvc-dpop"); + _ = RegisterClientIfEnabled("js-oidc"); + _ = RegisterClientIfEnabled("mvc-automatic-token-management"); + _ = RegisterClientIfEnabled("mvc-hybrid-backchannel"); + _ = RegisterClientIfEnabled("mvc-jar-jwt"); + _ = RegisterClientIfEnabled("mvc-jar-uri-jwt"); + _ = RegisterClientIfEnabled("mvc-saml"); + _ = RegisterClientIfEnabled("web"); + _ = RegisterTemplateIfEnabled("template-is", 7001); + _ = RegisterTemplateIfEnabled("template-is-empty", 7002); + _ = RegisterTemplateIfEnabled("template-is-inmem", 7003); + _ = RegisterTemplateIfEnabled("template-is-aspid", 7004); + _ = RegisterTemplateIfEnabled("template-is-ef", 7005); } void ConfigureConsoleClients() { - RegisterClientIfEnabled("console-ciba-client", explicitStart: true); - RegisterClientIfEnabled("console-device-flow", explicitStart: true); - RegisterClientIfEnabled("console-client-credentials-flow", explicitStart: true); - RegisterClientIfEnabled("console-client-credentials-flow-callingidentityserverapi", explicitStart: true); - RegisterClientIfEnabled("console-client-credentials-flow-postbody", explicitStart: true); - RegisterClientIfEnabled("console-client-credentials-flow-dpop", explicitStart: true); - RegisterClientIfEnabled("console-dcr-client", explicitStart: true); - RegisterClientIfEnabled("console-ephemeral-mtls-client", explicitStart: true); - RegisterClientIfEnabled("console-extension-grant", explicitStart: true); - RegisterClientIfEnabled("console-introspection-client", explicitStart: true); - RegisterClientIfEnabled("console-mtls-client", explicitStart: true); - RegisterClientIfEnabled("console-parameterized-scope-client", explicitStart: true); - RegisterClientIfEnabled("console-private-key-jwt-client", explicitStart: true); - RegisterClientIfEnabled("console-resource-owner-flow", explicitStart: true); - RegisterClientIfEnabled("console-resource-owner-flow-public", explicitStart: true); - RegisterClientIfEnabled("console-resource-owner-flow-reference", explicitStart: true); - RegisterClientIfEnabled("console-resource-owner-flow-refresh-token", explicitStart: true); - RegisterClientIfEnabled("console-resource-owner-flow-userinfo", explicitStart: true); - RegisterClientIfEnabled("console-system-browser", explicitStart: true); - RegisterClientIfEnabled("console-scopes-resources", explicitStart: true); - RegisterClientIfEnabled("console-code", explicitStart: true); - RegisterClientIfEnabled("console-resource-indicators", explicitStart: true); + _ = RegisterClientIfEnabled("console-ciba-client", explicitStart: true); + _ = RegisterClientIfEnabled("console-device-flow", explicitStart: true); + _ = RegisterClientIfEnabled("console-client-credentials-flow", explicitStart: true); + _ = RegisterClientIfEnabled("console-client-credentials-flow-callingidentityserverapi", explicitStart: true); + _ = RegisterClientIfEnabled("console-client-credentials-flow-postbody", explicitStart: true); + _ = RegisterClientIfEnabled("console-client-credentials-flow-dpop", explicitStart: true); + _ = RegisterClientIfEnabled("console-dcr-client", explicitStart: true); + _ = RegisterClientIfEnabled("console-ephemeral-mtls-client", explicitStart: true); + _ = RegisterClientIfEnabled("console-extension-grant", explicitStart: true); + _ = RegisterClientIfEnabled("console-introspection-client", explicitStart: true); + _ = RegisterClientIfEnabled("console-mtls-client", explicitStart: true); + _ = RegisterClientIfEnabled("console-parameterized-scope-client", explicitStart: true); + _ = RegisterClientIfEnabled("console-private-key-jwt-client", explicitStart: true); + _ = RegisterClientIfEnabled("console-resource-owner-flow", explicitStart: true); + _ = RegisterClientIfEnabled("console-resource-owner-flow-public", explicitStart: true); + _ = RegisterClientIfEnabled("console-resource-owner-flow-reference", explicitStart: true); + _ = RegisterClientIfEnabled("console-resource-owner-flow-refresh-token", explicitStart: true); + _ = RegisterClientIfEnabled("console-resource-owner-flow-userinfo", explicitStart: true); + _ = RegisterClientIfEnabled("console-system-browser", explicitStart: true); + _ = RegisterClientIfEnabled("console-scopes-resources", explicitStart: true); + _ = RegisterClientIfEnabled("console-code", explicitStart: true); + _ = RegisterClientIfEnabled("console-resource-indicators", explicitStart: true); } bool ClientIsEnabled(string name) @@ -196,10 +196,10 @@ IResourceBuilder? RegisterClientIfEnabled(string name, bool var resourceBuilder = useLaunchProfile ? builder.AddProject(name) : builder.AddProject(name, launchProfileName: null); - resourceBuilder.AddIdentityAndApiReferences(projectRegistry); + _ = resourceBuilder.AddIdentityAndApiReferences(projectRegistry); if (explicitStart) { - resourceBuilder.WithExplicitStart(); + _ = resourceBuilder.WithExplicitStart(); } return resourceBuilder; diff --git a/identity-server/aspire/AppHosts/Dev/Dev.csproj b/identity-server/aspire/AppHosts/Dev/Dev.csproj index 20251a32c..59f8dfe85 100644 --- a/identity-server/aspire/AppHosts/Dev/Dev.csproj +++ b/identity-server/aspire/AppHosts/Dev/Dev.csproj @@ -1,12 +1,10 @@ - + Exe - net10.0 - enable enable true - true + diff --git a/identity-server/aspire/Directory.Build.props b/identity-server/aspire/Directory.Build.props new file mode 100644 index 000000000..de7b79c33 --- /dev/null +++ b/identity-server/aspire/Directory.Build.props @@ -0,0 +1,6 @@ + + + + None + + diff --git a/identity-server/aspire/ServiceDefaults/Extensions.cs b/identity-server/aspire/ServiceDefaults/Extensions.cs index 5c5d31796..561fdbcea 100644 --- a/identity-server/aspire/ServiceDefaults/Extensions.cs +++ b/identity-server/aspire/ServiceDefaults/Extensions.cs @@ -18,45 +18,45 @@ public static class Extensions { public static IHostApplicationBuilder AddServiceDefaults(this IHostApplicationBuilder builder) { - builder.ConfigureOpenTelemetry(); + _ = builder.ConfigureOpenTelemetry(); - builder.AddDefaultHealthChecks(); + _ = builder.AddDefaultHealthChecks(); - builder.Services.AddServiceDiscovery(); + _ = builder.Services.AddServiceDiscovery(); - builder.Services.ConfigureHttpClientDefaults(http => + _ = builder.Services.ConfigureHttpClientDefaults(http => { // Turn on resilience by default - http.AddStandardResilienceHandler(); + _ = http.AddStandardResilienceHandler(); // Turn on service discovery by default - http.AddServiceDiscovery(); + _ = http.AddServiceDiscovery(); }); - builder.Configuration.Add(new FallbackNonAspireContextConfigurationSource()); + _ = builder.Configuration.Add(new FallbackNonAspireContextConfigurationSource()); return builder; } public static IHostApplicationBuilder ConfigureOpenTelemetry(this IHostApplicationBuilder builder) { - builder.Logging.AddOpenTelemetry(logging => + _ = builder.Logging.AddOpenTelemetry(logging => { logging.IncludeFormattedMessage = true; logging.IncludeScopes = true; }); - builder.Services.AddOpenTelemetry() + _ = builder.Services.AddOpenTelemetry() .WithMetrics(metrics => { - metrics.AddAspNetCoreInstrumentation() + _ = metrics.AddAspNetCoreInstrumentation() .AddHttpClientInstrumentation() .AddRuntimeInstrumentation() .AddMeter(Duende.IdentityServer.Telemetry.ServiceName); }) .WithTracing(tracing => { - tracing + _ = tracing .AddSource(IdentityServerConstants.Tracing.Basic) .AddSource(IdentityServerConstants.Tracing.Cache) .AddSource(IdentityServerConstants.Tracing.Services) @@ -67,7 +67,7 @@ public static class Extensions .AddHttpClientInstrumentation(); }); - builder.AddOpenTelemetryExporters(); + _ = builder.AddOpenTelemetryExporters(); return builder; } @@ -78,7 +78,7 @@ public static class Extensions if (useOtlpExporter) { - builder.Services.AddOpenTelemetry().UseOtlpExporter(); + _ = builder.Services.AddOpenTelemetry().UseOtlpExporter(); } // Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package) @@ -93,7 +93,7 @@ public static class Extensions public static IHostApplicationBuilder AddDefaultHealthChecks(this IHostApplicationBuilder builder) { - builder.Services.AddHealthChecks() + _ = builder.Services.AddHealthChecks() // Add a default liveness check to ensure app is responsive .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]); @@ -107,11 +107,11 @@ public static class Extensions return builder; } - builder.Services.ConfigureOpenTelemetryMeterProvider(provider => + _ = builder.Services.ConfigureOpenTelemetryMeterProvider(provider => { foreach (var meterName in meterNames) { - provider.AddMeter(meterName); + _ = provider.AddMeter(meterName); } }); diff --git a/identity-server/aspire/ServiceDefaults/SerilogExtensions.cs b/identity-server/aspire/ServiceDefaults/SerilogExtensions.cs index ec0fb116c..590c6d0f4 100644 --- a/identity-server/aspire/ServiceDefaults/SerilogExtensions.cs +++ b/identity-server/aspire/ServiceDefaults/SerilogExtensions.cs @@ -13,7 +13,7 @@ public static class SerilogExtensions public static void ConfigureSerilogDefaults(this WebApplicationBuilder builder) => builder.Services.AddSerilog((services, configuration) => { - configuration + _ = configuration .ReadFrom.Configuration(builder.Configuration) .ReadFrom.Services(services) .Enrich.FromLogContext() @@ -24,7 +24,7 @@ public static class SerilogExtensions .MinimumLevel.Override("System", LogEventLevel.Warning) .WriteTo.Logger(fileLogger => { - fileLogger.WriteTo.File("./diagnostics/diagnostic.log", + _ = fileLogger.WriteTo.File("./diagnostics/diagnostic.log", rollingInterval: RollingInterval.Day, fileSizeLimitBytes: 1024 * 1024 * 10, // 10 MB rollOnFileSizeLimit: true, @@ -34,7 +34,7 @@ public static class SerilogExtensions }) .WriteTo.Logger(consoleLogger => { - consoleLogger.WriteTo + _ = consoleLogger.WriteTo .Console( outputTemplate: "[{Timestamp:HH:mm:ss} {Level} {EventId}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}") diff --git a/identity-server/aspire/ServiceDefaults/ServiceDefaults.csproj b/identity-server/aspire/ServiceDefaults/ServiceDefaults.csproj index cb225dd46..0c0e1e443 100644 --- a/identity-server/aspire/ServiceDefaults/ServiceDefaults.csproj +++ b/identity-server/aspire/ServiceDefaults/ServiceDefaults.csproj @@ -1,12 +1,8 @@ - net10.0 - enable enable true - false - true diff --git a/identity-server/build.cs b/identity-server/build.cs new file mode 100644 index 000000000..7548c485d --- /dev/null +++ b/identity-server/build.cs @@ -0,0 +1,31 @@ +#:project ../.github/build/BuildHelpers.csproj + +using BuildHelpers; +using static Bullseye.Targets; + +var repoRoot = Repo.FindRoot(); + +Targets.Shared(repoRoot, "identity-server/identity-server.slnf"); + +const string TestsIdentityServerUnitTests = "tests-identity-server-unit-tests"; +const string TestsIdentityServerIntegrationTests = "tests-identity-server-integration-tests"; +const string TestsIdentityServerEndToEndTests = "tests-identity-server-end-to-end-tests"; + +Targets.Test(TestsIdentityServerUnitTests, "identity-server/test/IdentityServer.UnitTests", repoRoot); +Targets.Test(TestsIdentityServerIntegrationTests, "identity-server/test/IdentityServer.IntegrationTests", repoRoot); +Targets.Test(TestsIdentityServerEndToEndTests, "identity-server/test/IdentityServer.EndToEndTests", repoRoot); + +Target(SharedTargets.Default, [ + SharedTargets.CheckSolutions, + SharedTargets.CheckUnusedPackages, + SharedTargets.CheckSortedRefs, + SharedTargets.VerifyFormatting, + SharedTargets.Clean, + SharedTargets.VerifyNoChanges, + SharedTargets.DotnetDevCerts, + TestsIdentityServerUnitTests, + TestsIdentityServerIntegrationTests, + TestsIdentityServerEndToEndTests +]); + +await RunTargetsAndExitAsync(args); diff --git a/identity-server/clients/Directory.Build.props b/identity-server/clients/Directory.Build.props index be300d23b..8a89ceed6 100644 --- a/identity-server/clients/Directory.Build.props +++ b/identity-server/clients/Directory.Build.props @@ -1,8 +1,8 @@ - - + - net10.0 + None true + false diff --git a/identity-server/clients/src/APIs/DPoPApi/Program.cs b/identity-server/clients/src/APIs/DPoPApi/Program.cs index 39cc70afe..c5a6e2d20 100644 --- a/identity-server/clients/src/APIs/DPoPApi/Program.cs +++ b/identity-server/clients/src/APIs/DPoPApi/Program.cs @@ -14,14 +14,14 @@ try Log.Information("{EnvironmentApplicationName} Starting up", builder.Environment.ApplicationName); builder.ConfigureSerilogDefaults(); - builder.AddServiceDefaults(); + _ = builder.AddServiceDefaults(); - builder.Services.AddControllers(); - builder.Services.AddCors(); - builder.Services.AddDistributedMemoryCache(); + _ = builder.Services.AddControllers(); + _ = builder.Services.AddCors(); + _ = builder.Services.AddDistributedMemoryCache(); // this API will accept any access token from the authority - builder.Services.AddAuthentication("token") + _ = builder.Services.AddAuthentication("token") .AddJwtBearer("token", options => { options.Authority = builder.Configuration["is-host"]; @@ -30,7 +30,7 @@ try options.TokenValidationParameters.ValidTypes = ["at+jwt"]; }); - builder.Services.ConfigureDPoPTokensForScheme("token", options => + _ = builder.Services.ConfigureDPoPTokensForScheme("token", options => { options.AllowBearerTokens = true; options.EnableReplayDetection = true; @@ -38,21 +38,21 @@ try var app = builder.Build(); - app.UseSerilogRequestLogging(); + _ = app.UseSerilogRequestLogging(); - app.UseCors(policy => + _ = app.UseCors(policy => { - policy.WithOrigins("https://localhost:44300"); - policy.AllowAnyHeader(); - policy.AllowAnyMethod(); - policy.WithExposedHeaders("WWW-Authenticate"); + _ = policy.WithOrigins("https://localhost:44300"); + _ = policy.AllowAnyHeader(); + _ = policy.AllowAnyMethod(); + _ = policy.WithExposedHeaders("WWW-Authenticate"); }); - app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); + _ = app.UseRouting(); + _ = app.UseAuthentication(); + _ = app.UseAuthorization(); - app.MapControllers().RequireAuthorization(); + _ = app.MapControllers().RequireAuthorization(); app.Run(); } diff --git a/identity-server/clients/src/APIs/MtlsApi/Program.cs b/identity-server/clients/src/APIs/MtlsApi/Program.cs index cf7d551ef..d1fdf8013 100644 --- a/identity-server/clients/src/APIs/MtlsApi/Program.cs +++ b/identity-server/clients/src/APIs/MtlsApi/Program.cs @@ -16,13 +16,13 @@ try Log.Information("{EnvironmentApplicationName} Starting up", builder.Environment.ApplicationName); builder.ConfigureSerilogDefaults(); - builder.AddServiceDefaults(); + _ = builder.AddServiceDefaults(); - builder.Services.AddControllers(); - builder.Services.AddCors(); + _ = builder.Services.AddControllers(); + _ = builder.Services.AddCors(); // this API will accept any access token from the authority - builder.Services.AddAuthentication("token") + _ = builder.Services.AddAuthentication("token") .AddJwtBearer("token", options => { options.Authority = builder.Configuration["is-host"]; @@ -31,7 +31,7 @@ try options.TokenValidationParameters.ValidTypes = ["at+jwt"]; }); - builder.Services.Configure(options => + _ = builder.Services.Configure(options => { options.ConfigureHttpsDefaults(https => { @@ -42,22 +42,22 @@ try var app = builder.Build(); - app.UseSerilogRequestLogging(); + _ = app.UseSerilogRequestLogging(); - app.UseCors(policy => + _ = app.UseCors(policy => { - policy.WithOrigins("https://localhost:44300"); - policy.AllowAnyHeader(); - policy.AllowAnyMethod(); - policy.WithExposedHeaders("WWW-Authenticate"); + _ = policy.WithOrigins("https://localhost:44300"); + _ = policy.AllowAnyHeader(); + _ = policy.AllowAnyMethod(); + _ = policy.WithExposedHeaders("WWW-Authenticate"); }); - app.UseRouting(); - app.UseAuthentication(); - app.UseConfirmationValidation(); - app.UseAuthorization(); + _ = app.UseRouting(); + _ = app.UseAuthentication(); + _ = app.UseConfirmationValidation(); + _ = app.UseAuthorization(); - app.MapControllers().RequireAuthorization(); + _ = app.MapControllers().RequireAuthorization(); app.Run(); } diff --git a/identity-server/clients/src/APIs/ResourceBasedApi/Program.cs b/identity-server/clients/src/APIs/ResourceBasedApi/Program.cs index 2680c4a2f..37eeb4527 100644 --- a/identity-server/clients/src/APIs/ResourceBasedApi/Program.cs +++ b/identity-server/clients/src/APIs/ResourceBasedApi/Program.cs @@ -14,12 +14,12 @@ try Log.Information("{EnvironmentApplicationName} Starting up", builder.Environment.ApplicationName); builder.ConfigureSerilogDefaults(); - builder.AddServiceDefaults(); + _ = builder.AddServiceDefaults(); - builder.Services.AddControllers(); - builder.Services.AddCors(); + _ = builder.Services.AddControllers(); + _ = builder.Services.AddCors(); - builder.Services.AddAuthentication("token") + _ = builder.Services.AddAuthentication("token") // JWT tokens .AddJwtBearer("token", options => { @@ -42,21 +42,21 @@ try var app = builder.Build(); - app.UseSerilogRequestLogging(); + _ = app.UseSerilogRequestLogging(); - app.UseCors(policy => + _ = app.UseCors(policy => { - policy.WithOrigins("https://localhost:44300"); - policy.AllowAnyHeader(); - policy.AllowAnyMethod(); - policy.WithExposedHeaders("WWW-Authenticate"); + _ = policy.WithOrigins("https://localhost:44300"); + _ = policy.AllowAnyHeader(); + _ = policy.AllowAnyMethod(); + _ = policy.WithExposedHeaders("WWW-Authenticate"); }); - app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); + _ = app.UseRouting(); + _ = app.UseAuthentication(); + _ = app.UseAuthorization(); - app.MapControllers().RequireAuthorization(); + _ = app.MapControllers().RequireAuthorization(); app.Run(); } diff --git a/identity-server/clients/src/APIs/SimpleApi/Program.cs b/identity-server/clients/src/APIs/SimpleApi/Program.cs index e31cdcb5e..92b90f5bc 100644 --- a/identity-server/clients/src/APIs/SimpleApi/Program.cs +++ b/identity-server/clients/src/APIs/SimpleApi/Program.cs @@ -13,13 +13,13 @@ try Log.Information("{EnvironmentApplicationName} Starting up", builder.Environment.ApplicationName); builder.ConfigureSerilogDefaults(); - builder.AddServiceDefaults(); + _ = builder.AddServiceDefaults(); - builder.Services.AddControllers(); - builder.Services.AddCors(); + _ = builder.Services.AddControllers(); + _ = builder.Services.AddCors(); // this API will accept any access token from the authority - builder.Services.AddAuthentication("token") + _ = builder.Services.AddAuthentication("token") .AddJwtBearer("token", options => { options.Authority = builder.Configuration["is-host"]; @@ -30,21 +30,21 @@ try var app = builder.Build(); - app.UseSerilogRequestLogging(); + _ = app.UseSerilogRequestLogging(); - app.UseCors(policy => + _ = app.UseCors(policy => { - policy.WithOrigins("https://localhost:44300"); - policy.AllowAnyHeader(); - policy.AllowAnyMethod(); - policy.WithExposedHeaders("WWW-Authenticate"); + _ = policy.WithOrigins("https://localhost:44300"); + _ = policy.AllowAnyHeader(); + _ = policy.AllowAnyMethod(); + _ = policy.WithExposedHeaders("WWW-Authenticate"); }); - app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); + _ = app.UseRouting(); + _ = app.UseAuthentication(); + _ = app.UseAuthorization(); - app.MapControllers().RequireAuthorization(); + _ = app.MapControllers().RequireAuthorization(); app.Run(); } diff --git a/identity-server/clients/src/ConsoleCode/Program.cs b/identity-server/clients/src/ConsoleCode/Program.cs index 35e81accf..209e48f58 100644 --- a/identity-server/clients/src/ConsoleCode/Program.cs +++ b/identity-server/clients/src/ConsoleCode/Program.cs @@ -12,7 +12,7 @@ using Serilog; var builder = Host.CreateApplicationBuilder(args); // Add ServiceDefaults from Aspire -builder.AddServiceDefaults(); +_ = builder.AddServiceDefaults(); // Register a named HttpClient with service discovery support. // The AddServiceDiscovery extension enables Aspire to resolve the actual endpoint at runtime. @@ -63,7 +63,7 @@ async Task SignIn() .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message}{NewLine}{Exception}{NewLine}") .CreateLogger(); - options.LoggerFactory.AddSerilog(serilog); + _ = options.LoggerFactory.AddSerilog(serilog); _oidcClient = new OidcClient(options); var result = await _oidcClient.LoginAsync(new LoginRequest()); diff --git a/identity-server/clients/src/ConsoleCode/SystemBrowser.cs b/identity-server/clients/src/ConsoleCode/SystemBrowser.cs index f636ccbf7..5ed557912 100644 --- a/identity-server/clients/src/ConsoleCode/SystemBrowser.cs +++ b/identity-server/clients/src/ConsoleCode/SystemBrowser.cs @@ -76,7 +76,7 @@ public class SystemBrowser : IBrowser { try { - Process.Start(url); + _ = Process.Start(url); } catch { @@ -84,15 +84,15 @@ public class SystemBrowser : IBrowser if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { url = url.Replace("&", "^&"); - Process.Start(new ProcessStartInfo("cmd", $"/c start {url}") { CreateNoWindow = true }); + _ = Process.Start(new ProcessStartInfo("cmd", $"/c start {url}") { CreateNoWindow = true }); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { - Process.Start("xdg-open", url); + _ = Process.Start("xdg-open", url); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { - Process.Start("open", url); + _ = Process.Start("open", url); } else { @@ -130,11 +130,11 @@ public class LoopbackHttpListener : IDisposable _host.Start(); } - public void Dispose() => Task.Run(async () => - { - await Task.Delay(500); - _host.Dispose(); - }); + public void Dispose() => _ = Task.Run(async () => + { + await Task.Delay(500); + _host.Dispose(); + }); private void Configure(IApplicationBuilder app) => app.Run(async ctx => { @@ -172,7 +172,7 @@ public class LoopbackHttpListener : IDisposable await ctx.Response.WriteAsync("

You can now return to the application.

"); await ctx.Response.Body.FlushAsync(); - _source.TrySetResult(value); + _ = _source.TrySetResult(value); } catch (Exception ex) { @@ -186,10 +186,10 @@ public class LoopbackHttpListener : IDisposable public Task WaitForCallbackAsync(int timeoutInSeconds = DefaultTimeout) { - Task.Run(async () => + _ = Task.Run(async () => { await Task.Delay(timeoutInSeconds * 1000); - _source.TrySetCanceled(); + _ = _source.TrySetCanceled(); }); return _source.Task; diff --git a/identity-server/clients/src/ConsoleDeviceFlow/Program.cs b/identity-server/clients/src/ConsoleDeviceFlow/Program.cs index 15e7aeb2a..c2483fe68 100644 --- a/identity-server/clients/src/ConsoleDeviceFlow/Program.cs +++ b/identity-server/clients/src/ConsoleDeviceFlow/Program.cs @@ -11,7 +11,7 @@ using Microsoft.Extensions.Hosting; var builder = Host.CreateApplicationBuilder(args); // Add ServiceDefaults from Aspire -builder.AddServiceDefaults(); +_ = builder.AddServiceDefaults(); // Register named HttpClient with service discovery support. // The AddServiceDiscovery extension enables Aspire to resolve the actual endpoint at runtime. @@ -66,7 +66,7 @@ async Task RequestAuthorizationAsync() Console.WriteLine($"URL : {response.VerificationUri}"); Console.WriteLine($"Complete URL: {response.VerificationUriComplete}"); - Process.Start(new ProcessStartInfo(response.VerificationUriComplete) { UseShellExecute = true }); + _ = Process.Start(new ProcessStartInfo(response.VerificationUriComplete) { UseShellExecute = true }); return response; } diff --git a/identity-server/clients/src/ConsoleResourceIndicators/LoopbackHttpListener.cs b/identity-server/clients/src/ConsoleResourceIndicators/LoopbackHttpListener.cs index b4a1c8ab1..4cbb315dd 100644 --- a/identity-server/clients/src/ConsoleResourceIndicators/LoopbackHttpListener.cs +++ b/identity-server/clients/src/ConsoleResourceIndicators/LoopbackHttpListener.cs @@ -39,11 +39,11 @@ public class LoopbackHttpListener : IDisposable _host.Start(); } - public void Dispose() => Task.Run(async () => - { - await Task.Delay(500); - _host.Dispose(); - }); + public void Dispose() => _ = Task.Run(async () => + { + await Task.Delay(500); + _host.Dispose(); + }); private void Configure(IApplicationBuilder app) => app.Run(async ctx => { @@ -58,7 +58,7 @@ public class LoopbackHttpListener : IDisposable private async Task SetResultAsync(string value, HttpContext ctx) { - _source.TrySetResult(value); + _ = _source.TrySetResult(value); try { @@ -79,10 +79,10 @@ public class LoopbackHttpListener : IDisposable public Task WaitForCallbackAsync(int timeoutInSeconds = DefaultTimeout) { - Task.Run(async () => + _ = Task.Run(async () => { await Task.Delay(timeoutInSeconds * 1000); - _source.TrySetCanceled(); + _ = _source.TrySetCanceled(); }); return _source.Task; diff --git a/identity-server/clients/src/ConsoleResourceIndicators/Program.cs b/identity-server/clients/src/ConsoleResourceIndicators/Program.cs index 2cdd177a6..bae9005f6 100644 --- a/identity-server/clients/src/ConsoleResourceIndicators/Program.cs +++ b/identity-server/clients/src/ConsoleResourceIndicators/Program.cs @@ -8,7 +8,7 @@ using Spectre.Console; var builder = Host.CreateApplicationBuilder(args); // Add ServiceDefaults from Aspire -builder.AddServiceDefaults(); +_ = builder.AddServiceDefaults(); // Display banner AnsiConsole.Write(new Rule("[bold green]Resource Indicators Demo[/]").Centered()); @@ -87,9 +87,9 @@ var completed = testsToRun.Count(t => t.Enabled && t.Status == TestStatus.Comple var failed = testsToRun.Count(t => t.Enabled && t.Status == TestStatus.Failed); var total = testsToRun.Count(t => t.Enabled); -summary.AddRow("[green]Completed[/]", completed.ToString()); -summary.AddRow("[red]Failed[/]", failed.ToString()); -summary.AddRow("[cyan]Total[/]", total.ToString()); +_ = summary.AddRow("[green]Completed[/]", completed.ToString()); +_ = summary.AddRow("[red]Failed[/]", failed.ToString()); +_ = summary.AddRow("[cyan]Total[/]", total.ToString()); AnsiConsole.Write(summary); @@ -121,7 +121,7 @@ if (testsWithExpectedErrors.Any()) { var reason = "Resource not configured for this test"; - expectedErrorsTable.AddRow( + _ = expectedErrorsTable.AddRow( test.Id, error.Resource.Replace("urn:", ""), $"[yellow]{error.Error ?? "unknown"}[/]", @@ -168,7 +168,7 @@ if (mode == OutputMode.Table) ? $"{test.Result.RefreshResults.Count(r => r.Success)}/{test.Result.RefreshResults.Count} successful" : "-"; - detailsTable.AddRow( + _ = detailsTable.AddRow( test.Id, accessToken, refreshToken, @@ -185,7 +185,7 @@ if (Environment.UserInteractive && !Console.IsInputRedirected) { AnsiConsole.WriteLine(); AnsiConsole.Markup("[dim]Press Enter to exit...[/]"); - Console.ReadLine(); + _ = Console.ReadLine(); } else { diff --git a/identity-server/clients/src/ConsoleResourceIndicators/SystemBrowser.cs b/identity-server/clients/src/ConsoleResourceIndicators/SystemBrowser.cs index 32c0af430..84747f715 100644 --- a/identity-server/clients/src/ConsoleResourceIndicators/SystemBrowser.cs +++ b/identity-server/clients/src/ConsoleResourceIndicators/SystemBrowser.cs @@ -68,7 +68,7 @@ public class SystemBrowser : IBrowser { try { - Process.Start(url); + _ = Process.Start(url); } catch { @@ -76,15 +76,15 @@ public class SystemBrowser : IBrowser if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { url = url.Replace("&", "^&"); - Process.Start(new ProcessStartInfo("cmd", $"/c start {url}") { CreateNoWindow = true }); + _ = Process.Start(new ProcessStartInfo("cmd", $"/c start {url}") { CreateNoWindow = true }); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { - Process.Start("xdg-open", url); + _ = Process.Start("xdg-open", url); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { - Process.Start("open", url); + _ = Process.Start("open", url); } else { diff --git a/identity-server/clients/src/ConsoleResourceIndicators/TestRunner.cs b/identity-server/clients/src/ConsoleResourceIndicators/TestRunner.cs index 6c1c1d961..443483860 100644 --- a/identity-server/clients/src/ConsoleResourceIndicators/TestRunner.cs +++ b/identity-server/clients/src/ConsoleResourceIndicators/TestRunner.cs @@ -107,7 +107,7 @@ internal class TestRunner(string authority, OutputMode outputMode) ? string.Concat(test.Scope.AsSpan(0, 37), "...") : test.Scope; - table.AddRow( + _ = table.AddRow( test.Id, status, scopeDisplay, diff --git a/identity-server/clients/src/JsOidc/Startup.cs b/identity-server/clients/src/JsOidc/Startup.cs index f63fd7407..181382b79 100644 --- a/identity-server/clients/src/JsOidc/Startup.cs +++ b/identity-server/clients/src/JsOidc/Startup.cs @@ -11,7 +11,7 @@ public class Startup public void Configure(IApplicationBuilder app) { - app.UseDefaultFiles(); + _ = app.UseDefaultFiles(); // enable to test w/ CSP //app.Use(async (ctx, next) => @@ -28,6 +28,6 @@ public class Startup // await next(); //}); - app.UseStaticFiles(); + _ = app.UseStaticFiles(); } } diff --git a/identity-server/clients/src/MvcAutomaticTokenManagement/Controllers/HomeController.cs b/identity-server/clients/src/MvcAutomaticTokenManagement/Controllers/HomeController.cs index 4e3fd3b6b..85e6cae20 100644 --- a/identity-server/clients/src/MvcAutomaticTokenManagement/Controllers/HomeController.cs +++ b/identity-server/clients/src/MvcAutomaticTokenManagement/Controllers/HomeController.cs @@ -21,7 +21,7 @@ public class HomeController : Controller public async Task Renew() { - await HttpContext.GetUserAccessTokenAsync(new UserTokenRequestParameters { ForceTokenRenewal = true }); + _ = await HttpContext.GetUserAccessTokenAsync(new UserTokenRequestParameters { ForceTokenRenewal = true }); return RedirectToAction(nameof(Secure)); } diff --git a/identity-server/clients/src/MvcAutomaticTokenManagement/HostingExtensions.cs b/identity-server/clients/src/MvcAutomaticTokenManagement/HostingExtensions.cs index 7d883f6c1..a62e7fa59 100644 --- a/identity-server/clients/src/MvcAutomaticTokenManagement/HostingExtensions.cs +++ b/identity-server/clients/src/MvcAutomaticTokenManagement/HostingExtensions.cs @@ -16,10 +16,10 @@ internal static class HostingExtensions var authority = builder.Configuration["is-host"]; // add MVC - builder.Services.AddControllersWithViews(); + _ = builder.Services.AddControllersWithViews(); // add cookie-based session management with OpenID Connect authentication - builder.Services.AddAuthentication(options => + _ = builder.Services.AddAuthentication(options => { options.DefaultScheme = "cookie"; options.DefaultChallengeScheme = "oidc"; @@ -80,10 +80,10 @@ internal static class HostingExtensions }); // add automatic token management - builder.Services.AddOpenIdConnectAccessTokenManagement(); + _ = builder.Services.AddOpenIdConnectAccessTokenManagement(); // add HTTP client to call protected API - builder.Services.AddUserAccessTokenHttpClient("client", configureClient: client => + _ = builder.Services.AddUserAccessTokenHttpClient("client", configureClient: client => { client.BaseAddress = new Uri("https://simple-api"); }).AddServiceDiscovery(); @@ -93,16 +93,16 @@ internal static class HostingExtensions public static WebApplication ConfigurePipeline(this WebApplication app) { - app.UseDeveloperExceptionPage(); - app.UseHttpsRedirection(); - app.UseStaticFiles(); + _ = app.UseDeveloperExceptionPage(); + _ = app.UseHttpsRedirection(); + _ = app.UseStaticFiles(); - app.UseRouting(); + _ = app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); + _ = app.UseAuthentication(); + _ = app.UseAuthorization(); - app.MapDefaultControllerRoute() + _ = app.MapDefaultControllerRoute() .RequireAuthorization(); return app; diff --git a/identity-server/clients/src/MvcAutomaticTokenManagement/MvcAutomaticTokenManagement.csproj b/identity-server/clients/src/MvcAutomaticTokenManagement/MvcAutomaticTokenManagement.csproj index efd6dfd02..eccf28741 100644 --- a/identity-server/clients/src/MvcAutomaticTokenManagement/MvcAutomaticTokenManagement.csproj +++ b/identity-server/clients/src/MvcAutomaticTokenManagement/MvcAutomaticTokenManagement.csproj @@ -1,9 +1,7 @@ - - + - @@ -11,12 +9,10 @@ + - - + - \ No newline at end of file diff --git a/identity-server/clients/src/MvcAutomaticTokenManagement/Program.cs b/identity-server/clients/src/MvcAutomaticTokenManagement/Program.cs index 4edd59109..b14a5a439 100644 --- a/identity-server/clients/src/MvcAutomaticTokenManagement/Program.cs +++ b/identity-server/clients/src/MvcAutomaticTokenManagement/Program.cs @@ -21,7 +21,7 @@ try var builder = WebApplication .CreateBuilder(args); - builder + _ = builder .AddServiceDefaults(); builder diff --git a/identity-server/clients/src/MvcCode/Controllers/HomeController.cs b/identity-server/clients/src/MvcCode/Controllers/HomeController.cs index 7da83c811..9fcf002ce 100644 --- a/identity-server/clients/src/MvcCode/Controllers/HomeController.cs +++ b/identity-server/clients/src/MvcCode/Controllers/HomeController.cs @@ -73,9 +73,9 @@ public class HomeController : Controller var info = await HttpContext.AuthenticateAsync("Cookies"); - info.Properties.UpdateTokenValue("refresh_token", newRefreshToken); - info.Properties.UpdateTokenValue("access_token", newAccessToken); - info.Properties.UpdateTokenValue("expires_at", expiresAt.ToString("o", CultureInfo.InvariantCulture)); + _ = info.Properties.UpdateTokenValue("refresh_token", newRefreshToken); + _ = info.Properties.UpdateTokenValue("access_token", newAccessToken); + _ = info.Properties.UpdateTokenValue("expires_at", expiresAt.ToString("o", CultureInfo.InvariantCulture)); await HttpContext.SignInAsync("Cookies", info.Principal, info.Properties); return Redirect("~/Home/Secure"); diff --git a/identity-server/clients/src/MvcCode/HostingExtensions.cs b/identity-server/clients/src/MvcCode/HostingExtensions.cs index 379f8b232..49d1e93d8 100644 --- a/identity-server/clients/src/MvcCode/HostingExtensions.cs +++ b/identity-server/clients/src/MvcCode/HostingExtensions.cs @@ -19,17 +19,17 @@ internal static class HostingExtensions JwtSecurityTokenHandler.DefaultMapInboundClaims = false; - builder.Services.AddControllersWithViews(); + _ = builder.Services.AddControllersWithViews(); - builder.Services.AddHttpClient(); + _ = builder.Services.AddHttpClient(); - builder.Services.AddSingleton(r => + _ = builder.Services.AddSingleton(r => { var factory = r.GetRequiredService(); return new DiscoveryCache(authority, () => factory.CreateClient()); }); - builder.Services.AddAuthentication(options => + _ = builder.Services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = "oidc"; @@ -77,7 +77,7 @@ internal static class HostingExtensions // Register a named HttpClient with service discovery support. // The AddServiceDiscovery extension enables Aspire to resolve the actual endpoint at runtime. - builder.Services.AddHttpClient("SimpleApi", client => + _ = builder.Services.AddHttpClient("SimpleApi", client => { client.BaseAddress = new Uri("https://simple-api"); }) @@ -88,16 +88,16 @@ internal static class HostingExtensions public static WebApplication ConfigurePipeline(this WebApplication app) { - app.UseDeveloperExceptionPage(); - app.UseHttpsRedirection(); - app.UseStaticFiles(); + _ = app.UseDeveloperExceptionPage(); + _ = app.UseHttpsRedirection(); + _ = app.UseStaticFiles(); - app.UseRouting(); + _ = app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); + _ = app.UseAuthentication(); + _ = app.UseAuthorization(); - app.MapDefaultControllerRoute() + _ = app.MapDefaultControllerRoute() .RequireAuthorization(); return app; diff --git a/identity-server/clients/src/MvcCode/MvcCode.csproj b/identity-server/clients/src/MvcCode/MvcCode.csproj index 4116c98a8..cfff59461 100644 --- a/identity-server/clients/src/MvcCode/MvcCode.csproj +++ b/identity-server/clients/src/MvcCode/MvcCode.csproj @@ -1,13 +1,11 @@ - - + fe28de52-854d-4c0f-a6b5-20f8dea1f70d - + + - - @@ -15,11 +13,6 @@ - - - + - - \ No newline at end of file diff --git a/identity-server/clients/src/MvcCode/Program.cs b/identity-server/clients/src/MvcCode/Program.cs index 3765bb39d..37c56b369 100644 --- a/identity-server/clients/src/MvcCode/Program.cs +++ b/identity-server/clients/src/MvcCode/Program.cs @@ -18,7 +18,7 @@ try var builder = WebApplication .CreateBuilder(args); - builder + _ = builder .AddServiceDefaults(); builder diff --git a/identity-server/clients/src/MvcDPoP/Controllers/HomeController.cs b/identity-server/clients/src/MvcDPoP/Controllers/HomeController.cs index 11603147b..51644ecd0 100644 --- a/identity-server/clients/src/MvcDPoP/Controllers/HomeController.cs +++ b/identity-server/clients/src/MvcDPoP/Controllers/HomeController.cs @@ -21,7 +21,7 @@ public class HomeController : Controller public async Task Renew() { - await HttpContext.GetUserAccessTokenAsync(new UserTokenRequestParameters { ForceTokenRenewal = true }); + _ = await HttpContext.GetUserAccessTokenAsync(new UserTokenRequestParameters { ForceTokenRenewal = true }); return RedirectToAction(nameof(Secure)); } diff --git a/identity-server/clients/src/MvcDPoP/HostingExtensions.cs b/identity-server/clients/src/MvcDPoP/HostingExtensions.cs index d065b75d3..e00b5ad35 100644 --- a/identity-server/clients/src/MvcDPoP/HostingExtensions.cs +++ b/identity-server/clients/src/MvcDPoP/HostingExtensions.cs @@ -19,10 +19,10 @@ internal static class HostingExtensions var authority = builder.Configuration["is-host"]; // add MVC - builder.Services.AddControllersWithViews(); + _ = builder.Services.AddControllersWithViews(); // add cookie-based session management with OpenID Connect authentication - builder.Services.AddAuthentication(options => + _ = builder.Services.AddAuthentication(options => { options.DefaultScheme = "cookie"; options.DefaultChallengeScheme = "oidc"; @@ -73,7 +73,7 @@ internal static class HostingExtensions }); // add automatic token management - builder.Services.AddOpenIdConnectAccessTokenManagement(options => + _ = builder.Services.AddOpenIdConnectAccessTokenManagement(options => { // add option to opt-in to jkt on authZ ep // create and configure a DPoP JWK @@ -84,7 +84,7 @@ internal static class HostingExtensions }); // add HTTP client to call protected API - builder.Services.AddUserAccessTokenHttpClient("client", configureClient: client => + _ = builder.Services.AddUserAccessTokenHttpClient("client", configureClient: client => { client.BaseAddress = new Uri("https://dpop-api"); // somehow allow this HttpClient to override the scheme (because it might be a legacy API still using Bearer) @@ -92,23 +92,23 @@ internal static class HostingExtensions .AddServiceDiscovery() .AddHttpMessageHandler(); - builder.Services.AddTransient(); + _ = builder.Services.AddTransient(); return builder.Build(); } public static WebApplication ConfigurePipeline(this WebApplication app) { - app.UseDeveloperExceptionPage(); - app.UseHttpsRedirection(); - app.UseStaticFiles(); + _ = app.UseDeveloperExceptionPage(); + _ = app.UseHttpsRedirection(); + _ = app.UseStaticFiles(); - app.UseRouting(); + _ = app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); + _ = app.UseAuthentication(); + _ = app.UseAuthorization(); - app.MapDefaultControllerRoute() + _ = app.MapDefaultControllerRoute() .RequireAuthorization(); return app; diff --git a/identity-server/clients/src/MvcDPoP/MvcDPoP.csproj b/identity-server/clients/src/MvcDPoP/MvcDPoP.csproj index 70b34805d..eccf28741 100644 --- a/identity-server/clients/src/MvcDPoP/MvcDPoP.csproj +++ b/identity-server/clients/src/MvcDPoP/MvcDPoP.csproj @@ -1,9 +1,7 @@ - - + - @@ -11,13 +9,10 @@ + - - + - - \ No newline at end of file diff --git a/identity-server/clients/src/MvcDPoP/Program.cs b/identity-server/clients/src/MvcDPoP/Program.cs index ee198abf5..76a8f6816 100644 --- a/identity-server/clients/src/MvcDPoP/Program.cs +++ b/identity-server/clients/src/MvcDPoP/Program.cs @@ -21,7 +21,7 @@ try var builder = WebApplication .CreateBuilder(args); - builder + _ = builder .AddServiceDefaults(); builder diff --git a/identity-server/clients/src/MvcHybridBackChannel/Controllers/HomeController.cs b/identity-server/clients/src/MvcHybridBackChannel/Controllers/HomeController.cs index 3c5abbebc..12287a998 100644 --- a/identity-server/clients/src/MvcHybridBackChannel/Controllers/HomeController.cs +++ b/identity-server/clients/src/MvcHybridBackChannel/Controllers/HomeController.cs @@ -72,9 +72,9 @@ public class HomeController : Controller var info = await HttpContext.AuthenticateAsync("Cookies"); - info.Properties.UpdateTokenValue("refresh_token", new_refresh_token); - info.Properties.UpdateTokenValue("access_token", new_access_token); - info.Properties.UpdateTokenValue("expires_at", expiresAt.ToString("o", CultureInfo.InvariantCulture)); + _ = info.Properties.UpdateTokenValue("refresh_token", new_refresh_token); + _ = info.Properties.UpdateTokenValue("access_token", new_access_token); + _ = info.Properties.UpdateTokenValue("expires_at", expiresAt.ToString("o", CultureInfo.InvariantCulture)); await HttpContext.SignInAsync("Cookies", info.Principal, info.Properties); return Redirect("~/Home/Secure"); diff --git a/identity-server/clients/src/MvcHybridBackChannel/HostingExtensions.cs b/identity-server/clients/src/MvcHybridBackChannel/HostingExtensions.cs index 51b8f034e..7437440e9 100644 --- a/identity-server/clients/src/MvcHybridBackChannel/HostingExtensions.cs +++ b/identity-server/clients/src/MvcHybridBackChannel/HostingExtensions.cs @@ -19,19 +19,19 @@ internal static class HostingExtensions var authority = builder.Configuration["is-host"]; - builder.Services.AddControllersWithViews(); - builder.Services.AddHttpClient(); + _ = builder.Services.AddControllersWithViews(); + _ = builder.Services.AddHttpClient(); - builder.Services.AddSingleton(r => + _ = builder.Services.AddSingleton(r => { var factory = r.GetRequiredService(); return new DiscoveryCache(authority, () => factory.CreateClient()); }); - builder.Services.AddTransient(); - builder.Services.AddSingleton(); + _ = builder.Services.AddTransient(); + _ = builder.Services.AddSingleton(); - builder.Services.AddAuthentication(options => + _ = builder.Services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = "oidc"; @@ -76,7 +76,7 @@ internal static class HostingExtensions // Register a named HttpClient with service discovery support. // The AddServiceDiscovery extension enables Aspire to resolve the actual endpoint at runtime. - builder.Services.AddHttpClient("SimpleApi", client => + _ = builder.Services.AddHttpClient("SimpleApi", client => { client.BaseAddress = new Uri("https://simple-api"); }) @@ -87,13 +87,13 @@ internal static class HostingExtensions public static WebApplication ConfigurePipeline(this WebApplication app) { - app.UseDeveloperExceptionPage(); - app.UseStaticFiles(); + _ = app.UseDeveloperExceptionPage(); + _ = app.UseStaticFiles(); - app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); - app.MapDefaultControllerRoute(); + _ = app.UseRouting(); + _ = app.UseAuthentication(); + _ = app.UseAuthorization(); + _ = app.MapDefaultControllerRoute(); return app; } diff --git a/identity-server/clients/src/MvcHybridBackChannel/Program.cs b/identity-server/clients/src/MvcHybridBackChannel/Program.cs index 06292b907..e89a9cc65 100644 --- a/identity-server/clients/src/MvcHybridBackChannel/Program.cs +++ b/identity-server/clients/src/MvcHybridBackChannel/Program.cs @@ -18,7 +18,7 @@ try var builder = WebApplication .CreateBuilder(args); - builder + _ = builder .AddServiceDefaults(); builder diff --git a/identity-server/clients/src/MvcJarJwt/Controllers/HomeController.cs b/identity-server/clients/src/MvcJarJwt/Controllers/HomeController.cs index 3c70b7e0d..c8e8ab2f3 100644 --- a/identity-server/clients/src/MvcJarJwt/Controllers/HomeController.cs +++ b/identity-server/clients/src/MvcJarJwt/Controllers/HomeController.cs @@ -33,7 +33,7 @@ public class HomeController : Controller public async Task RenewTokens() { - await HttpContext.GetUserAccessTokenAsync(new() { ForceTokenRenewal = true }); + _ = await HttpContext.GetUserAccessTokenAsync(new() { ForceTokenRenewal = true }); return RedirectToAction(nameof(Secure)); } } diff --git a/identity-server/clients/src/MvcJarJwt/HostingExtensions.cs b/identity-server/clients/src/MvcJarJwt/HostingExtensions.cs index a36eaea45..dfef27533 100644 --- a/identity-server/clients/src/MvcJarJwt/HostingExtensions.cs +++ b/identity-server/clients/src/MvcJarJwt/HostingExtensions.cs @@ -14,14 +14,14 @@ internal static class HostingExtensions var authority = builder.Configuration["is-host"]; var simpleApi = builder.Configuration["simple-api"]; - builder.Services.AddSingleton(); - builder.Services.AddTransient(); + _ = builder.Services.AddSingleton(); + _ = builder.Services.AddTransient(); // add MVC - builder.Services.AddControllersWithViews(); + _ = builder.Services.AddControllersWithViews(); // add cookie-based session management with OpenID Connect authentication - builder.Services.AddAuthentication(options => + _ = builder.Services.AddAuthentication(options => { options.DefaultScheme = "cookie"; options.DefaultChallengeScheme = "oidc"; @@ -74,11 +74,11 @@ internal static class HostingExtensions }); // add automatic token management - builder.Services.AddOpenIdConnectAccessTokenManagement(); - builder.Services.AddTransient(); + _ = builder.Services.AddOpenIdConnectAccessTokenManagement(); + _ = builder.Services.AddTransient(); // add HTTP client to call protected API - builder.Services.AddUserAccessTokenHttpClient("client", configureClient: client => + _ = builder.Services.AddUserAccessTokenHttpClient("client", configureClient: client => { client.BaseAddress = new Uri("https://simple-api"); }).AddServiceDiscovery(); @@ -88,16 +88,16 @@ internal static class HostingExtensions public static WebApplication ConfigurePipeline(this WebApplication app) { - app.UseDeveloperExceptionPage(); - app.UseHttpsRedirection(); - app.UseStaticFiles(); + _ = app.UseDeveloperExceptionPage(); + _ = app.UseHttpsRedirection(); + _ = app.UseStaticFiles(); - app.UseRouting(); + _ = app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); + _ = app.UseAuthentication(); + _ = app.UseAuthorization(); - app.MapDefaultControllerRoute() + _ = app.MapDefaultControllerRoute() .RequireAuthorization(); return app; diff --git a/identity-server/clients/src/MvcJarJwt/MvcJarJwt.csproj b/identity-server/clients/src/MvcJarJwt/MvcJarJwt.csproj index efd6dfd02..eccf28741 100644 --- a/identity-server/clients/src/MvcJarJwt/MvcJarJwt.csproj +++ b/identity-server/clients/src/MvcJarJwt/MvcJarJwt.csproj @@ -1,9 +1,7 @@ - - + - @@ -11,12 +9,10 @@ + - - + - \ No newline at end of file diff --git a/identity-server/clients/src/MvcJarJwt/Program.cs b/identity-server/clients/src/MvcJarJwt/Program.cs index a729c047d..d71e87006 100644 --- a/identity-server/clients/src/MvcJarJwt/Program.cs +++ b/identity-server/clients/src/MvcJarJwt/Program.cs @@ -18,7 +18,7 @@ try var builder = WebApplication .CreateBuilder(args); - builder + _ = builder .AddServiceDefaults(); builder diff --git a/identity-server/clients/src/MvcJarUriJwt/Controllers/HomeController.cs b/identity-server/clients/src/MvcJarUriJwt/Controllers/HomeController.cs index e5ec4eff0..c2a14aa8b 100644 --- a/identity-server/clients/src/MvcJarUriJwt/Controllers/HomeController.cs +++ b/identity-server/clients/src/MvcJarUriJwt/Controllers/HomeController.cs @@ -33,7 +33,7 @@ public class HomeController : Controller public async Task RenewTokens() { - await HttpContext.GetUserAccessTokenAsync(new() { ForceTokenRenewal = true }); + _ = await HttpContext.GetUserAccessTokenAsync(new() { ForceTokenRenewal = true }); return RedirectToAction(nameof(Secure)); } } diff --git a/identity-server/clients/src/MvcJarUriJwt/HostingExtensions.cs b/identity-server/clients/src/MvcJarUriJwt/HostingExtensions.cs index c9fae3a52..538ce667e 100644 --- a/identity-server/clients/src/MvcJarUriJwt/HostingExtensions.cs +++ b/identity-server/clients/src/MvcJarUriJwt/HostingExtensions.cs @@ -16,21 +16,21 @@ internal static class HostingExtensions var authority = builder.Configuration["is-host"]; var simpleApi = builder.Configuration["simple-api"]; - builder.Services.AddSingleton(r => + _ = builder.Services.AddSingleton(r => { var factory = r.GetRequiredService(); return new DiscoveryCache(authority, () => factory.CreateClient()); }); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - builder.Services.AddTransient(); + _ = builder.Services.AddSingleton(); + _ = builder.Services.AddSingleton(); + _ = builder.Services.AddTransient(); // add MVC - builder.Services.AddControllersWithViews(); + _ = builder.Services.AddControllersWithViews(); // add cookie-based session management with OpenID Connect authentication - builder.Services.AddAuthentication(options => + _ = builder.Services.AddAuthentication(options => { options.DefaultScheme = "cookie"; options.DefaultChallengeScheme = "oidc"; @@ -86,11 +86,11 @@ internal static class HostingExtensions }); // add automatic token management - builder.Services.AddOpenIdConnectAccessTokenManagement(); - builder.Services.AddTransient(); + _ = builder.Services.AddOpenIdConnectAccessTokenManagement(); + _ = builder.Services.AddTransient(); // add HTTP client to call protected API - builder.Services.AddUserAccessTokenHttpClient("client", configureClient: client => + _ = builder.Services.AddUserAccessTokenHttpClient("client", configureClient: client => { client.BaseAddress = new Uri(simpleApi); }).AddServiceDiscovery(); @@ -100,16 +100,16 @@ internal static class HostingExtensions public static WebApplication ConfigurePipeline(this WebApplication app) { - app.UseDeveloperExceptionPage(); - app.UseHttpsRedirection(); - app.UseStaticFiles(); + _ = app.UseDeveloperExceptionPage(); + _ = app.UseHttpsRedirection(); + _ = app.UseStaticFiles(); - app.UseRouting(); + _ = app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); + _ = app.UseAuthentication(); + _ = app.UseAuthorization(); - app.MapDefaultControllerRoute() + _ = app.MapDefaultControllerRoute() .RequireAuthorization(); return app; diff --git a/identity-server/clients/src/MvcJarUriJwt/MvcJarUriJwt.csproj b/identity-server/clients/src/MvcJarUriJwt/MvcJarUriJwt.csproj index efd6dfd02..eccf28741 100644 --- a/identity-server/clients/src/MvcJarUriJwt/MvcJarUriJwt.csproj +++ b/identity-server/clients/src/MvcJarUriJwt/MvcJarUriJwt.csproj @@ -1,9 +1,7 @@ - - + - @@ -11,12 +9,10 @@ + - - + - \ No newline at end of file diff --git a/identity-server/clients/src/MvcJarUriJwt/Program.cs b/identity-server/clients/src/MvcJarUriJwt/Program.cs index 07780a015..2954338f2 100644 --- a/identity-server/clients/src/MvcJarUriJwt/Program.cs +++ b/identity-server/clients/src/MvcJarUriJwt/Program.cs @@ -18,7 +18,7 @@ try var builder = WebApplication .CreateBuilder(args); - builder + _ = builder .AddServiceDefaults(); builder diff --git a/identity-server/clients/src/MvcJarUriJwt/RequestUriService.cs b/identity-server/clients/src/MvcJarUriJwt/RequestUriService.cs index 9eb82cc4c..ab7b1f12d 100644 --- a/identity-server/clients/src/MvcJarUriJwt/RequestUriService.cs +++ b/identity-server/clients/src/MvcJarUriJwt/RequestUriService.cs @@ -12,7 +12,7 @@ public class RequestUriService public string Set(string value) { var id = Guid.NewGuid().ToString(); - _requestObjects.TryAdd(id, value); + _ = _requestObjects.TryAdd(id, value); return id; } diff --git a/identity-server/clients/src/MvcSaml/HostingExtensions.cs b/identity-server/clients/src/MvcSaml/HostingExtensions.cs index 134fcbcc7..8dc45e899 100644 --- a/identity-server/clients/src/MvcSaml/HostingExtensions.cs +++ b/identity-server/clients/src/MvcSaml/HostingExtensions.cs @@ -24,11 +24,11 @@ internal static class HostingExtensions var idpBaseUrl = builder.Configuration["is-host"] ?? throw new InvalidOperationException("is-host configuration is required"); - builder.Services.AddControllersWithViews(); + _ = builder.Services.AddControllersWithViews(); var spCert = LoadSpCertificate(); - builder.Services.AddAuthentication(options => + _ = builder.Services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = Saml2Defaults.Scheme; @@ -70,23 +70,23 @@ internal static class HostingExtensions }); }); - builder.Services.AddAuthorization(); + _ = builder.Services.AddAuthorization(); return builder.Build(); } public static WebApplication ConfigurePipeline(this WebApplication app) { - app.UseDeveloperExceptionPage(); - app.UseHttpsRedirection(); - app.UseStaticFiles(); + _ = app.UseDeveloperExceptionPage(); + _ = app.UseHttpsRedirection(); + _ = app.UseStaticFiles(); - app.UseRouting(); + _ = app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); + _ = app.UseAuthentication(); + _ = app.UseAuthorization(); - app.MapDefaultControllerRoute() + _ = app.MapDefaultControllerRoute() .RequireAuthorization(); return app; diff --git a/identity-server/clients/src/MvcSaml/MvcSaml.csproj b/identity-server/clients/src/MvcSaml/MvcSaml.csproj index 6544cf0eb..ce099944b 100644 --- a/identity-server/clients/src/MvcSaml/MvcSaml.csproj +++ b/identity-server/clients/src/MvcSaml/MvcSaml.csproj @@ -1,19 +1,15 @@ - 3a8b2c1d-4e5f-6a7b-8c9d-0e1f2a3b4c5d - PreserveNewest - - - - + + @@ -21,9 +17,7 @@ - - - + + - diff --git a/identity-server/clients/src/MvcSaml/Program.cs b/identity-server/clients/src/MvcSaml/Program.cs index ff53ab8ef..f62d75381 100644 --- a/identity-server/clients/src/MvcSaml/Program.cs +++ b/identity-server/clients/src/MvcSaml/Program.cs @@ -17,7 +17,7 @@ try var builder = WebApplication .CreateBuilder(args); - builder + _ = builder .AddServiceDefaults(); builder diff --git a/identity-server/clients/src/Web/Pages/Secure.cshtml.cs b/identity-server/clients/src/Web/Pages/Secure.cshtml.cs index 5e383e689..c73362e16 100644 --- a/identity-server/clients/src/Web/Pages/Secure.cshtml.cs +++ b/identity-server/clients/src/Web/Pages/Secure.cshtml.cs @@ -17,7 +17,7 @@ public class SecureModel : PageModel public async Task OnGetRenewTokensAsync() { - await HttpContext.GetUserAccessTokenAsync(new UserTokenRequestParameters { ForceTokenRenewal = true }); + _ = await HttpContext.GetUserAccessTokenAsync(new UserTokenRequestParameters { ForceTokenRenewal = true }); return RedirectToPage(); } } diff --git a/identity-server/clients/src/Web/Program.cs b/identity-server/clients/src/Web/Program.cs index 6f465b198..099c85cdb 100644 --- a/identity-server/clients/src/Web/Program.cs +++ b/identity-server/clients/src/Web/Program.cs @@ -10,11 +10,11 @@ using Microsoft.IdentityModel.Tokens; using Web; var builder = WebApplication.CreateBuilder(args); -builder.AddServiceDefaults(); +_ = builder.AddServiceDefaults(); var authority = builder.Configuration["is-host"]; // Add services to the container. -builder.Services.AddRazorPages(); +_ = builder.Services.AddRazorPages(); AddAuthentication(); AddAccessTokenManagement(); ConfigureBackChannelLogout(); @@ -24,27 +24,27 @@ var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { - app.UseExceptionHandler("/Error"); + _ = app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. - app.UseHsts(); + _ = app.UseHsts(); } -app.UseHttpsRedirection(); +_ = app.UseHttpsRedirection(); -app.UseRouting(); +_ = app.UseRouting(); -app.UseAuthentication(); -app.UseAuthorization(); +_ = app.UseAuthentication(); +_ = app.UseAuthorization(); -app.MapStaticAssets(); -app.MapRazorPages() +_ = app.MapStaticAssets(); +_ = app.MapRazorPages() .WithStaticAssets(); app.Run(); void AddAccessTokenManagement() { - builder.Services.AddOpenIdConnectAccessTokenManagement(options => + _ = builder.Services.AddOpenIdConnectAccessTokenManagement(options => { // add option to opt-in to jkt on authZ ep // create and configure a DPoP JWK @@ -53,18 +53,18 @@ void AddAccessTokenManagement() jwk.Alg = "PS256"; options.DPoPJsonWebKey = DPoPProofKey.Parse(JsonSerializer.Serialize(jwk)); }); - builder.Services.AddUserAccessTokenHttpClient("client", configureClient: client => + _ = builder.Services.AddUserAccessTokenHttpClient("client", configureClient: client => { client.BaseAddress = new Uri("https://dpop-api"); }).AddServiceDiscovery(); - builder.Services.AddTransient(); - builder.Services.AddSingleton(); + _ = builder.Services.AddTransient(); + _ = builder.Services.AddSingleton(); } void AddAuthentication() { - builder.Services.AddAuthentication(options => + _ = builder.Services.AddAuthentication(options => { options.DefaultScheme = "cookie"; options.DefaultChallengeScheme = "oidc"; @@ -98,11 +98,11 @@ void AddAuthentication() }; options.DisableTelemetry = true; }); - builder.Services.ConfigureOptions(); + _ = builder.Services.ConfigureOptions(); } void ConfigureBackChannelLogout() { - builder.Services.AddTransient(); - builder.Services.AddSingleton(); + _ = builder.Services.AddTransient(); + _ = builder.Services.AddSingleton(); } diff --git a/identity-server/clients/src/Web/Web.csproj b/identity-server/clients/src/Web/Web.csproj index 32e6ba1dd..9677e06ee 100644 --- a/identity-server/clients/src/Web/Web.csproj +++ b/identity-server/clients/src/Web/Web.csproj @@ -1,14 +1,11 @@ - - + enable enable - - @@ -16,12 +13,10 @@ + - - + - \ No newline at end of file diff --git a/identity-server/clients/src/WindowsConsoleSystemBrowser/Program.cs b/identity-server/clients/src/WindowsConsoleSystemBrowser/Program.cs index 3043990a7..f8d65da77 100644 --- a/identity-server/clients/src/WindowsConsoleSystemBrowser/Program.cs +++ b/identity-server/clients/src/WindowsConsoleSystemBrowser/Program.cs @@ -56,12 +56,12 @@ internal class Program Console.WriteLine("+-----------------------+"); Console.WriteLine(""); Console.WriteLine("Press any key to sign in..."); - Console.ReadKey(); + _ = Console.ReadKey(); var p = new Program(); await p.SignIn(); - Console.ReadKey(); + _ = Console.ReadKey(); } private async Task SignIn() @@ -84,7 +84,7 @@ internal class Program .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message}{NewLine}{Exception}{NewLine}") .CreateLogger(); - options.LoggerFactory.AddSerilog(serilog); + _ = options.LoggerFactory.AddSerilog(serilog); var client = new OidcClient(options); var state = await client.PrepareLoginAsync(); @@ -99,7 +99,7 @@ internal class Program FileName = state.StartUrl, UseShellExecute = true }; - Process.Start(psi); + _ = Process.Start(psi); Console.WriteLine("Running callback manager"); var response = await callbackManager.RunServer(); @@ -153,7 +153,7 @@ internal class Program [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetForegroundWindow(IntPtr hWnd); - public void BringConsoleToFront() => SetForegroundWindow(GetConsoleWindow()); + public void BringConsoleToFront() => _ = SetForegroundWindow(GetConsoleWindow()); public static string GetRequestPostData(HttpListenerRequest request) { diff --git a/identity-server/hosts/AspNetIdentity10/Host.AspNetIdentity10.csproj b/identity-server/hosts/AspNetIdentity10/Host.AspNetIdentity10.csproj index 4669b33db..97c68e120 100644 --- a/identity-server/hosts/AspNetIdentity10/Host.AspNetIdentity10.csproj +++ b/identity-server/hosts/AspNetIdentity10/Host.AspNetIdentity10.csproj @@ -3,7 +3,6 @@ IdentityServerHost enable - all diff --git a/identity-server/hosts/Directory.Build.props b/identity-server/hosts/Directory.Build.props index bcb57e184..82ddc82ec 100644 --- a/identity-server/hosts/Directory.Build.props +++ b/identity-server/hosts/Directory.Build.props @@ -1,9 +1,9 @@ - - + - net10.0 + None true + false diff --git a/identity-server/hosts/EntityFramework10/Host.EntityFramework10.csproj b/identity-server/hosts/EntityFramework10/Host.EntityFramework10.csproj index 8f3b7119e..b2e6fbd19 100644 --- a/identity-server/hosts/EntityFramework10/Host.EntityFramework10.csproj +++ b/identity-server/hosts/EntityFramework10/Host.EntityFramework10.csproj @@ -3,7 +3,6 @@ IdentityServerHost enable - all true enable diff --git a/identity-server/hosts/Main10/Host.Main10.csproj b/identity-server/hosts/Main10/Host.Main10.csproj index 466803aca..fc0a473d2 100644 --- a/identity-server/hosts/Main10/Host.Main10.csproj +++ b/identity-server/hosts/Main10/Host.Main10.csproj @@ -5,7 +5,6 @@ IdentityServerHost e60c119c-8b86-4016-9d44-80e25948dbba enable - all
diff --git a/identity-server/migrations/AspNetIdentityDb/Migrations/.editorconfig b/identity-server/migrations/AspNetIdentityDb/Migrations/.editorconfig new file mode 100644 index 000000000..98e806338 --- /dev/null +++ b/identity-server/migrations/AspNetIdentityDb/Migrations/.editorconfig @@ -0,0 +1,2 @@ +[*.cs] +dotnet_diagnostic.IDE0058.severity = none diff --git a/identity-server/migrations/AspNetIdentityDb/Startup.cs b/identity-server/migrations/AspNetIdentityDb/Startup.cs index 9e0c5e640..0f88ae1c8 100644 --- a/identity-server/migrations/AspNetIdentityDb/Startup.cs +++ b/identity-server/migrations/AspNetIdentityDb/Startup.cs @@ -17,12 +17,12 @@ public class Startup public void ConfigureServices(IServiceCollection services) { var cn = Configuration.GetConnectionString("DefaultConnection"); - services.AddDbContext(options => + _ = services.AddDbContext(options => { - options.UseSqlServer(cn, dbOpts => dbOpts.MigrationsAssembly(typeof(Startup).Assembly.FullName)); + _ = options.UseSqlServer(cn, dbOpts => dbOpts.MigrationsAssembly(typeof(Startup).Assembly.FullName)); }); - services.AddIdentity(opt => + _ = services.AddIdentity(opt => { opt.Password.RequireDigit = false; opt.Password.RequireLowercase = false; diff --git a/identity-server/migrations/Directory.Build.props b/identity-server/migrations/Directory.Build.props index be300d23b..8a89ceed6 100644 --- a/identity-server/migrations/Directory.Build.props +++ b/identity-server/migrations/Directory.Build.props @@ -1,8 +1,8 @@ - - + - net10.0 + None true + false diff --git a/identity-server/migrations/IdentityServerDb/Migrations/.editorconfig b/identity-server/migrations/IdentityServerDb/Migrations/.editorconfig new file mode 100644 index 000000000..98e806338 --- /dev/null +++ b/identity-server/migrations/IdentityServerDb/Migrations/.editorconfig @@ -0,0 +1,2 @@ +[*.cs] +dotnet_diagnostic.IDE0058.severity = none diff --git a/identity-server/migrations/IdentityServerDb/SeedData.cs b/identity-server/migrations/IdentityServerDb/SeedData.cs index 17576f391..0cafeedd2 100644 --- a/identity-server/migrations/IdentityServerDb/SeedData.cs +++ b/identity-server/migrations/IdentityServerDb/SeedData.cs @@ -36,9 +36,9 @@ public class SeedData Console.WriteLine("Clients being populated"); foreach (var client in TestClients.Get()) { - context.Clients.Add(client.ToEntity()); + _ = context.Clients.Add(client.ToEntity()); } - context.SaveChanges(); + _ = context.SaveChanges(); } else { @@ -50,9 +50,9 @@ public class SeedData Console.WriteLine("IdentityResources being populated"); foreach (var resource in TestResources.IdentityResources) { - context.IdentityResources.Add(resource.ToEntity()); + _ = context.IdentityResources.Add(resource.ToEntity()); } - context.SaveChanges(); + _ = context.SaveChanges(); } else { @@ -64,9 +64,9 @@ public class SeedData Console.WriteLine("ApiResources being populated"); foreach (var resource in TestResources.ApiResources) { - context.ApiResources.Add(resource.ToEntity()); + _ = context.ApiResources.Add(resource.ToEntity()); } - context.SaveChanges(); + _ = context.SaveChanges(); } else { @@ -78,9 +78,9 @@ public class SeedData Console.WriteLine("Scopes being populated"); foreach (var resource in TestResources.ApiScopes) { - context.ApiScopes.Add(resource.ToEntity()); + _ = context.ApiScopes.Add(resource.ToEntity()); } - context.SaveChanges(); + _ = context.SaveChanges(); } else { @@ -90,7 +90,7 @@ public class SeedData if (!context.IdentityProviders.Any()) { Console.WriteLine("OidcIdentityProviders being populated"); - context.IdentityProviders.Add(new OidcProvider + _ = context.IdentityProviders.Add(new OidcProvider { Scheme = "demoidsrv", DisplayName = "IdentityServer (Seeded)", @@ -98,7 +98,7 @@ public class SeedData ClientId = "login", }.ToEntity()); - context.SaveChanges(); + _ = context.SaveChanges(); } else { diff --git a/identity-server/migrations/IdentityServerDb/Startup.cs b/identity-server/migrations/IdentityServerDb/Startup.cs index 9e0bdc75e..dd7707771 100644 --- a/identity-server/migrations/IdentityServerDb/Startup.cs +++ b/identity-server/migrations/IdentityServerDb/Startup.cs @@ -17,13 +17,13 @@ public class Startup { var cn = Configuration.GetConnectionString("DefaultConnection"); - services.AddOperationalDbContext(options => + _ = services.AddOperationalDbContext(options => { options.ConfigureDbContext = b => b.UseSqlServer(cn, dbOpts => dbOpts.MigrationsAssembly(typeof(Startup).Assembly.FullName)); }); - services.AddConfigurationDbContext(options => + _ = services.AddConfigurationDbContext(options => { options.ConfigureDbContext = b => b.UseSqlServer(cn, dbOpts => dbOpts.MigrationsAssembly(typeof(Startup).Assembly.FullName)); diff --git a/identity-server/perf/Directory.Build.props b/identity-server/perf/Directory.Build.props new file mode 100644 index 000000000..de7b79c33 --- /dev/null +++ b/identity-server/perf/Directory.Build.props @@ -0,0 +1,6 @@ + + + + None + + diff --git a/identity-server/perf/IdentityServer.PerfTests/IdentityServer.PerfTests.csproj b/identity-server/perf/IdentityServer.PerfTests/IdentityServer.PerfTests.csproj index 4182df96c..3bb191299 100644 --- a/identity-server/perf/IdentityServer.PerfTests/IdentityServer.PerfTests.csproj +++ b/identity-server/perf/IdentityServer.PerfTests/IdentityServer.PerfTests.csproj @@ -3,6 +3,7 @@ Exe net10.0 + false diff --git a/identity-server/perf/IdentityServer.PerfTests/Infrastructure/DebugLoggerProvider.cs b/identity-server/perf/IdentityServer.PerfTests/Infrastructure/DebugLoggerProvider.cs index fff4de199..aa779dc76 100644 --- a/identity-server/perf/IdentityServer.PerfTests/Infrastructure/DebugLoggerProvider.cs +++ b/identity-server/perf/IdentityServer.PerfTests/Infrastructure/DebugLoggerProvider.cs @@ -1,29 +1,15 @@ // Copyright (c) Duende Software. All rights reserved. // See LICENSE in the project root for license information. - -using System; -using System.Collections.Generic; using Microsoft.Extensions.Logging; namespace IdentityServer.PerfTest.Infrastructure; public class DebugLoggerProvider : List, ILoggerProvider { - public class DebugLogger : ILogger, IDisposable + public class DebugLogger(DebugLoggerProvider parent, string category) : ILogger, IDisposable { - private readonly DebugLoggerProvider _parent; - private readonly string _category; - - public DebugLogger(DebugLoggerProvider parent, string category) - { - _parent = parent; - _category = category; - } - - public void Dispose() - { - } + public void Dispose() { } public IDisposable BeginScope(TState state) => this; @@ -31,8 +17,8 @@ public class DebugLoggerProvider : List, ILoggerProvider public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) { - var msg = $"[{logLevel}] {_category} : {formatter(state, exception)}"; - _parent.Log(msg); + var msg = $"[{logLevel}] {category} : {formatter(state, exception)}"; + parent.Log(msg); } } diff --git a/identity-server/perf/IdentityServer.PerfTests/Infrastructure/IdentityServerContainer.cs b/identity-server/perf/IdentityServer.PerfTests/Infrastructure/IdentityServerContainer.cs index ab041882c..694aacd76 100644 --- a/identity-server/perf/IdentityServer.PerfTests/Infrastructure/IdentityServerContainer.cs +++ b/identity-server/perf/IdentityServer.PerfTests/Infrastructure/IdentityServerContainer.cs @@ -1,11 +1,6 @@ // Copyright (c) Duende Software. All rights reserved. // See LICENSE in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Net.Http; -using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.TestHost; @@ -74,11 +69,11 @@ public class IdentityServerContainer : IDisposable var hostBuilder = new HostBuilder() .ConfigureWebHost(builder => { - builder.UseTestServer(); - builder.UseSetting("Environment", "Production"); + _ = builder.UseTestServer(); + _ = builder.UseSetting("Environment", "Production"); - builder.ConfigureServices(ConfigureServices); - builder.Configure(ConfigureApp); + _ = builder.ConfigureServices(ConfigureServices); + _ = builder.Configure(ConfigureApp); }); // Build and start the IHost @@ -113,12 +108,12 @@ public class IdentityServerContainer : IDisposable { var logging = services.AddLogging(options => { - options.SetMinimumLevel(DefaultLogLevel); - options.AddProvider(Logger); + _ = options.SetMinimumLevel(DefaultLogLevel); + _ = options.AddProvider(Logger); foreach (var item in LogFilters) { - options.AddFilter(item.Key, item.Value); + _ = options.AddFilter(item.Key, item.Value); } }); diff --git a/identity-server/perf/IdentityServer.PerfTests/Infrastructure/InMemoryIdentityServerContainer.cs b/identity-server/perf/IdentityServer.PerfTests/Infrastructure/InMemoryIdentityServerContainer.cs index 194054b46..80aef4027 100644 --- a/identity-server/perf/IdentityServer.PerfTests/Infrastructure/InMemoryIdentityServerContainer.cs +++ b/identity-server/perf/IdentityServer.PerfTests/Infrastructure/InMemoryIdentityServerContainer.cs @@ -1,9 +1,6 @@ // Copyright (c) Duende Software. All rights reserved. // See LICENSE in the project root for license information. - -using System; -using System.Collections.Generic; using Duende.IdentityServer.Configuration; using Duende.IdentityServer.Models; using Microsoft.AspNetCore.Builder; @@ -26,7 +23,7 @@ public class InMemoryIdentityServerContainer : IdentityServerContainer { OnConfigureServices += services => { - services.AddIdentityServer(OnConfigureIdentityServerOptions) + _ = services.AddIdentityServer(OnConfigureIdentityServerOptions!) .AddInMemoryClients(Clients) .AddInMemoryIdentityResources(IdentityResources) .AddInMemoryApiScopes(ApiScopes) @@ -35,7 +32,7 @@ public class InMemoryIdentityServerContainer : IdentityServerContainer OnConfigure += app => { - app.UseIdentityServer(); + _ = app.UseIdentityServer(); }; } } diff --git a/identity-server/perf/IdentityServer.PerfTests/Infrastructure/TestBase.cs b/identity-server/perf/IdentityServer.PerfTests/Infrastructure/TestBase.cs index 0760b1238..8bdc532c6 100644 --- a/identity-server/perf/IdentityServer.PerfTests/Infrastructure/TestBase.cs +++ b/identity-server/perf/IdentityServer.PerfTests/Infrastructure/TestBase.cs @@ -1,8 +1,6 @@ // Copyright (c) Duende Software. All rights reserved. // See LICENSE in the project root for license information. - -using System.IO; using System.Security.Cryptography.X509Certificates; using BenchmarkDotNet.Attributes; diff --git a/identity-server/perf/IdentityServer.PerfTests/Services/DefaultTokenServiceTest.cs b/identity-server/perf/IdentityServer.PerfTests/Services/DefaultTokenServiceTest.cs index dfaad3882..9771b66a3 100644 --- a/identity-server/perf/IdentityServer.PerfTests/Services/DefaultTokenServiceTest.cs +++ b/identity-server/perf/IdentityServer.PerfTests/Services/DefaultTokenServiceTest.cs @@ -1,9 +1,7 @@ // Copyright (c) Duende Software. All rights reserved. // See LICENSE in the project root for license information. - using System.Security.Claims; -using System.Threading.Tasks; using BenchmarkDotNet.Attributes; using Duende.IdentityServer; using Duende.IdentityServer.Models; diff --git a/identity-server/src/Directory.Build.props b/identity-server/src/Directory.Build.props index e7c2fe3f6..0bb39d74c 100644 --- a/identity-server/src/Directory.Build.props +++ b/identity-server/src/Directory.Build.props @@ -1,11 +1,8 @@ - - + - - All OAuth 2.0;OpenID Connect;Security;Identity;IdentityServer;ASP.NET Core Duende IdentityServer true @@ -13,15 +10,15 @@ 8.0 true - - + $(NoWarn);RS0026 - Currently all existing warnings are suppressed. We will remove them as we address them. But this configuration - allows us to prevent new warnings from being introduced while we work on the existing ones. - --> - $(NoWarn);CA1002;CA1008;CA1031;CA1034;CA1040;CA1051;CA1054;CA1055;CA1056;CA1062;CA1716;CA1724;CA1725;CA1727;CA1819;CA1848;CA1851;CA2201;CA2007;CA2208;CA2227;CA2234 + + $(NoWarn);RS0027 + + diff --git a/identity-server/src/Directory.Build.targets b/identity-server/src/Directory.Build.targets new file mode 100644 index 000000000..acbac1881 --- /dev/null +++ b/identity-server/src/Directory.Build.targets @@ -0,0 +1,4 @@ + + + + diff --git a/identity-server/src/EntityFramework.Storage/DbContexts/ConfigurationDbContext.cs b/identity-server/src/EntityFramework.Storage/DbContexts/ConfigurationDbContext.cs index e2b062f93..dcc7eff09 100644 --- a/identity-server/src/EntityFramework.Storage/DbContexts/ConfigurationDbContext.cs +++ b/identity-server/src/EntityFramework.Storage/DbContexts/ConfigurationDbContext.cs @@ -102,14 +102,6 @@ public class ConfigurationDbContext : DbContext, IConfigurationDbConte /// public DbSet IdentityProviders { get; set; } - /// - /// Gets or sets the SAML service providers. - /// - /// - /// The SAML service providers. - /// - public DbSet SamlServiceProviders { get; set; } - /// /// Override this method to further configure the model that was discovered by convention from the entity types /// exposed in properties on your derived context. The resulting model may be cached @@ -138,7 +130,6 @@ public class ConfigurationDbContext : DbContext, IConfigurationDbConte modelBuilder.ConfigureClientContext(StoreOptions); modelBuilder.ConfigureResourcesContext(StoreOptions); modelBuilder.ConfigureIdentityProviderContext(StoreOptions); - modelBuilder.ConfigureSamlServiceProviderContext(StoreOptions); base.OnModelCreating(modelBuilder); } diff --git a/identity-server/src/EntityFramework.Storage/Entities/SamlServiceProvider.cs b/identity-server/src/EntityFramework.Storage/Entities/SamlServiceProvider.cs deleted file mode 100644 index 57bb85669..000000000 --- a/identity-server/src/EntityFramework.Storage/Entities/SamlServiceProvider.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -#pragma warning disable 1591 - -namespace Duende.IdentityServer.EntityFramework.Entities; - -public class SamlServiceProvider -{ - public int Id { get; set; } - public string EntityId { get; set; } - public string DisplayName { get; set; } - public string Description { get; set; } - public bool Enabled { get; set; } = true; - - // TimeSpan? stored as ticks - public long? ClockSkewTicks { get; set; } - public long? RequestMaxAgeTicks { get; set; } - - // ACS binding (enum stored as int) - public int AssertionConsumerServiceBinding { get; set; } - - // SLO endpoint (flattened from SamlEndpointType?) - public string SingleLogoutServiceUrl { get; set; } - public int? SingleLogoutServiceBinding { get; set; } - - public bool RequireSignedAuthnRequests { get; set; } - public bool EncryptAssertions { get; set; } - public bool RequireConsent { get; set; } - public bool AllowIdpInitiated { get; set; } - - public string DefaultNameIdFormat { get; set; } = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"; - public string DefaultPersistentNameIdentifierClaimType { get; set; } - - // SamlSigningBehavior? stored as int? - public int? SigningBehavior { get; set; } - - // Navigation properties - public List AssertionConsumerServiceUrls { get; set; } - public List SigningCertificates { get; set; } - public List EncryptionCertificates { get; set; } - public List ClaimMappings { get; set; } - - // Audit fields (matching Client entity pattern) - public DateTime Created { get; set; } = DateTime.UtcNow; - public DateTime? Updated { get; set; } - public DateTime? LastAccessed { get; set; } - public bool NonEditable { get; set; } -} diff --git a/identity-server/src/EntityFramework.Storage/Entities/SamlServiceProviderAssertionConsumerService.cs b/identity-server/src/EntityFramework.Storage/Entities/SamlServiceProviderAssertionConsumerService.cs deleted file mode 100644 index 9394410da..000000000 --- a/identity-server/src/EntityFramework.Storage/Entities/SamlServiceProviderAssertionConsumerService.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -#pragma warning disable 1591 - -namespace Duende.IdentityServer.EntityFramework.Entities; - -public class SamlServiceProviderAssertionConsumerService -{ - public int Id { get; set; } - public string Url { get; set; } - public int SamlServiceProviderId { get; set; } - public SamlServiceProvider SamlServiceProvider { get; set; } -} diff --git a/identity-server/src/EntityFramework.Storage/Entities/SamlServiceProviderClaimMapping.cs b/identity-server/src/EntityFramework.Storage/Entities/SamlServiceProviderClaimMapping.cs deleted file mode 100644 index 62c9cac81..000000000 --- a/identity-server/src/EntityFramework.Storage/Entities/SamlServiceProviderClaimMapping.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -#pragma warning disable 1591 - -namespace Duende.IdentityServer.EntityFramework.Entities; - -public class SamlServiceProviderClaimMapping -{ - public int Id { get; set; } - /// - /// The claim type (dictionary key). - /// - public string ClaimType { get; set; } - /// - /// The SAML attribute name (dictionary value). - /// - public string SamlAttributeName { get; set; } - public int SamlServiceProviderId { get; set; } - public SamlServiceProvider SamlServiceProvider { get; set; } -} diff --git a/identity-server/src/EntityFramework.Storage/Entities/SamlServiceProviderEncryptionCertificate.cs b/identity-server/src/EntityFramework.Storage/Entities/SamlServiceProviderEncryptionCertificate.cs deleted file mode 100644 index 63e80f794..000000000 --- a/identity-server/src/EntityFramework.Storage/Entities/SamlServiceProviderEncryptionCertificate.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -#pragma warning disable 1591 - -namespace Duende.IdentityServer.EntityFramework.Entities; - -public class SamlServiceProviderEncryptionCertificate -{ - public int Id { get; set; } - /// - /// Base64-encoded DER (raw bytes) of the X.509 certificate. - /// - public string Data { get; set; } - public int SamlServiceProviderId { get; set; } - public SamlServiceProvider SamlServiceProvider { get; set; } -} diff --git a/identity-server/src/EntityFramework.Storage/Entities/SamlServiceProviderSigningCertificate.cs b/identity-server/src/EntityFramework.Storage/Entities/SamlServiceProviderSigningCertificate.cs deleted file mode 100644 index 55af97cd4..000000000 --- a/identity-server/src/EntityFramework.Storage/Entities/SamlServiceProviderSigningCertificate.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -#pragma warning disable 1591 - -namespace Duende.IdentityServer.EntityFramework.Entities; - -public class SamlServiceProviderSigningCertificate -{ - public int Id { get; set; } - /// - /// Base64-encoded DER (raw bytes) of the X.509 certificate. - /// - public string Data { get; set; } - public int SamlServiceProviderId { get; set; } - public SamlServiceProvider SamlServiceProvider { get; set; } -} diff --git a/identity-server/src/EntityFramework.Storage/Extensions/ModelBuilderExtensions.cs b/identity-server/src/EntityFramework.Storage/Extensions/ModelBuilderExtensions.cs index 58abc1caa..2ace3ed17 100644 --- a/identity-server/src/EntityFramework.Storage/Extensions/ModelBuilderExtensions.cs +++ b/identity-server/src/EntityFramework.Storage/Extensions/ModelBuilderExtensions.cs @@ -391,76 +391,4 @@ public static class ModelBuilderExtensions entity.HasIndex(x => x.Scheme).IsUnique(); }); } - - /// - /// Configures the SAML service provider context. - /// - /// The model builder. - /// The store options. - public static void ConfigureSamlServiceProviderContext(this ModelBuilder modelBuilder, ConfigurationStoreOptions storeOptions) - { - if (!string.IsNullOrWhiteSpace(storeOptions.DefaultSchema)) - { - modelBuilder.HasDefaultSchema(storeOptions.DefaultSchema); - } - - modelBuilder.Entity(sp => - { - sp.ToTable(storeOptions.SamlServiceProvider); - sp.HasKey(x => x.Id); - - sp.Property(x => x.EntityId).HasMaxLength(200).IsRequired(); - sp.Property(x => x.DisplayName).HasMaxLength(200); - sp.Property(x => x.Description).HasMaxLength(1000); - sp.Property(x => x.DefaultNameIdFormat).HasMaxLength(500); - sp.Property(x => x.DefaultPersistentNameIdentifierClaimType).HasMaxLength(500); - sp.Property(x => x.SingleLogoutServiceUrl).HasMaxLength(2000); - - sp.HasIndex(x => x.EntityId).IsUnique(); - - sp.HasMany(x => x.AssertionConsumerServiceUrls) - .WithOne(x => x.SamlServiceProvider) - .HasForeignKey(x => x.SamlServiceProviderId).IsRequired().OnDelete(DeleteBehavior.Cascade); - sp.HasMany(x => x.SigningCertificates) - .WithOne(x => x.SamlServiceProvider) - .HasForeignKey(x => x.SamlServiceProviderId).IsRequired().OnDelete(DeleteBehavior.Cascade); - sp.HasMany(x => x.EncryptionCertificates) - .WithOne(x => x.SamlServiceProvider) - .HasForeignKey(x => x.SamlServiceProviderId).IsRequired().OnDelete(DeleteBehavior.Cascade); - sp.HasMany(x => x.ClaimMappings) - .WithOne(x => x.SamlServiceProvider) - .HasForeignKey(x => x.SamlServiceProviderId).IsRequired().OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity(acs => - { - acs.ToTable(storeOptions.SamlServiceProviderAssertionConsumerService); - acs.HasKey(x => x.Id); - acs.Property(x => x.Url).HasMaxLength(2000).IsRequired(); - acs.HasIndex(x => new { x.SamlServiceProviderId, x.Url }).IsUnique(); - }); - - modelBuilder.Entity(cert => - { - cert.ToTable(storeOptions.SamlServiceProviderSigningCertificate); - cert.HasKey(x => x.Id); - cert.Property(x => x.Data).HasMaxLength(4000).IsRequired(); - }); - - modelBuilder.Entity(cert => - { - cert.ToTable(storeOptions.SamlServiceProviderEncryptionCertificate); - cert.HasKey(x => x.Id); - cert.Property(x => x.Data).HasMaxLength(4000).IsRequired(); - }); - - modelBuilder.Entity(mapping => - { - mapping.ToTable(storeOptions.SamlServiceProviderClaimMapping); - mapping.HasKey(x => x.Id); - mapping.Property(x => x.ClaimType).HasMaxLength(250).IsRequired(); - mapping.Property(x => x.SamlAttributeName).HasMaxLength(250).IsRequired(); - mapping.HasIndex(x => new { x.SamlServiceProviderId, x.ClaimType }).IsUnique(); - }); - } } diff --git a/identity-server/src/EntityFramework.Storage/Interfaces/IConfigurationDbContext.cs b/identity-server/src/EntityFramework.Storage/Interfaces/IConfigurationDbContext.cs index d4555f3d7..710f39681 100644 --- a/identity-server/src/EntityFramework.Storage/Interfaces/IConfigurationDbContext.cs +++ b/identity-server/src/EntityFramework.Storage/Interfaces/IConfigurationDbContext.cs @@ -63,14 +63,6 @@ public interface IConfigurationDbContext : IDisposable /// DbSet IdentityProviders { get; set; } - /// - /// Gets or sets the SAML service providers. - /// - /// - /// The SAML service providers. - /// - DbSet SamlServiceProviders { get; set; } - /// /// Saves the changes. /// diff --git a/identity-server/src/EntityFramework.Storage/Mappers/SamlServiceProviderMappers.cs b/identity-server/src/EntityFramework.Storage/Mappers/SamlServiceProviderMappers.cs deleted file mode 100644 index c9c22f4f0..000000000 --- a/identity-server/src/EntityFramework.Storage/Mappers/SamlServiceProviderMappers.cs +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -using System.Security.Cryptography.X509Certificates; -using Duende.IdentityServer.EntityFramework.Entities; -using Duende.IdentityServer.Models; - -namespace Duende.IdentityServer.EntityFramework.Mappers; - -/// -/// Extension methods to map to/from entity/model for SAML service providers. -/// -public static class SamlServiceProviderMappers -{ - /// - /// Maps an entity to a model. - /// - /// The entity. - /// - public static Models.SamlServiceProvider ToModel(this Entities.SamlServiceProvider entity) => - new Models.SamlServiceProvider - { - EntityId = entity.EntityId, - DisplayName = entity.DisplayName, - Description = entity.Description, - Enabled = entity.Enabled, - ClockSkew = entity.ClockSkewTicks.HasValue - ? TimeSpan.FromTicks(entity.ClockSkewTicks.Value) : null, - RequestMaxAge = entity.RequestMaxAgeTicks.HasValue - ? TimeSpan.FromTicks(entity.RequestMaxAgeTicks.Value) : null, - AssertionConsumerServiceBinding = (SamlBinding)entity.AssertionConsumerServiceBinding, - AssertionConsumerServiceUrls = entity.AssertionConsumerServiceUrls? - .Select(a => new Uri(a.Url)).ToHashSet() ?? new HashSet(), - SingleLogoutServiceUrl = entity.SingleLogoutServiceUrl != null - ? new SamlEndpointType - { - Location = new Uri(entity.SingleLogoutServiceUrl), - Binding = (SamlBinding)entity.SingleLogoutServiceBinding!.Value - } : null, - RequireSignedAuthnRequests = entity.RequireSignedAuthnRequests, -#pragma warning disable SYSLIB0057 // Type or member is obsolete - // TODO - Use X509CertificateLoader in a future release (when we drop NET8 support) - SigningCertificates = entity.SigningCertificates? - .Select(c => new X509Certificate2(Convert.FromBase64String(c.Data))).ToList(), - EncryptionCertificates = entity.EncryptionCertificates? - .Select(c => new X509Certificate2(Convert.FromBase64String(c.Data))).ToList(), -#pragma warning restore SYSLIB0057 // Type or member is obsolete - EncryptAssertions = entity.EncryptAssertions, - RequireConsent = entity.RequireConsent, - AllowIdpInitiated = entity.AllowIdpInitiated, - ClaimMappings = entity.ClaimMappings? - .ToDictionary(m => m.ClaimType, m => m.SamlAttributeName) - ?? new Dictionary(), - DefaultNameIdFormat = entity.DefaultNameIdFormat, - DefaultPersistentNameIdentifierClaimType = entity.DefaultPersistentNameIdentifierClaimType, - SigningBehavior = entity.SigningBehavior.HasValue - ? (SamlSigningBehavior)entity.SigningBehavior.Value : null, - }; - - /// - /// Maps a model to an entity. - /// - /// The model. - /// - public static Entities.SamlServiceProvider ToEntity(this Models.SamlServiceProvider model) => - new Entities.SamlServiceProvider - { - EntityId = model.EntityId, - DisplayName = model.DisplayName, - Description = model.Description, - Enabled = model.Enabled, - ClockSkewTicks = model.ClockSkew?.Ticks, - RequestMaxAgeTicks = model.RequestMaxAge?.Ticks, - AssertionConsumerServiceBinding = (int)model.AssertionConsumerServiceBinding, - AssertionConsumerServiceUrls = model.AssertionConsumerServiceUrls? - .Select(u => new SamlServiceProviderAssertionConsumerService { Url = u.AbsoluteUri }) - .ToList() ?? new List(), - SingleLogoutServiceUrl = model.SingleLogoutServiceUrl?.Location.AbsoluteUri, - SingleLogoutServiceBinding = model.SingleLogoutServiceUrl != null - ? (int)model.SingleLogoutServiceUrl.Binding : null, - RequireSignedAuthnRequests = model.RequireSignedAuthnRequests, - SigningCertificates = model.SigningCertificates? - .Select(c => new SamlServiceProviderSigningCertificate - { - Data = Convert.ToBase64String(c.RawData) - }).ToList() ?? new List(), - EncryptionCertificates = model.EncryptionCertificates? - .Select(c => new SamlServiceProviderEncryptionCertificate - { - Data = Convert.ToBase64String(c.RawData) - }).ToList() ?? new List(), - EncryptAssertions = model.EncryptAssertions, - RequireConsent = model.RequireConsent, - AllowIdpInitiated = model.AllowIdpInitiated, - ClaimMappings = model.ClaimMappings? - .Select(kvp => new SamlServiceProviderClaimMapping - { - ClaimType = kvp.Key, - SamlAttributeName = kvp.Value - }).ToList() ?? new List(), - DefaultNameIdFormat = model.DefaultNameIdFormat, - DefaultPersistentNameIdentifierClaimType = model.DefaultPersistentNameIdentifierClaimType, - SigningBehavior = model.SigningBehavior.HasValue - ? (int)model.SigningBehavior.Value : null, - }; -} diff --git a/identity-server/src/EntityFramework.Storage/Options/ConfigurationStoreOptions.cs b/identity-server/src/EntityFramework.Storage/Options/ConfigurationStoreOptions.cs index 3602baccb..8b7d68987 100644 --- a/identity-server/src/EntityFramework.Storage/Options/ConfigurationStoreOptions.cs +++ b/identity-server/src/EntityFramework.Storage/Options/ConfigurationStoreOptions.cs @@ -213,35 +213,6 @@ public class ConfigurationStoreOptions /// public TableConfiguration IdentityProvider { get; set; } = new TableConfiguration("IdentityProviders"); - /// - /// Gets or sets the SAML service providers table configuration. - /// - public TableConfiguration SamlServiceProvider { get; set; } = new TableConfiguration("SamlServiceProviders"); - - /// - /// Gets or sets the SAML service provider assertion consumer services table configuration. - /// - public TableConfiguration SamlServiceProviderAssertionConsumerService { get; set; } = - new TableConfiguration("SamlServiceProviderAssertionConsumerServices"); - - /// - /// Gets or sets the SAML service provider signing certificates table configuration. - /// - public TableConfiguration SamlServiceProviderSigningCertificate { get; set; } = - new TableConfiguration("SamlServiceProviderSigningCertificates"); - - /// - /// Gets or sets the SAML service provider encryption certificates table configuration. - /// - public TableConfiguration SamlServiceProviderEncryptionCertificate { get; set; } = - new TableConfiguration("SamlServiceProviderEncryptionCertificates"); - - /// - /// Gets or sets the SAML service provider claim mappings table configuration. - /// - public TableConfiguration SamlServiceProviderClaimMapping { get; set; } = - new TableConfiguration("SamlServiceProviderClaimMappings"); - /// /// Gets or set if EF DbContext pooling is enabled. /// diff --git a/identity-server/src/EntityFramework.Storage/Stores/IdentityProviderStore.cs b/identity-server/src/EntityFramework.Storage/Stores/IdentityProviderStore.cs index 79f44d2a7..5f97f328a 100644 --- a/identity-server/src/EntityFramework.Storage/Stores/IdentityProviderStore.cs +++ b/identity-server/src/EntityFramework.Storage/Stores/IdentityProviderStore.cs @@ -40,7 +40,7 @@ public class IdentityProviderStore : IIdentityProviderStore } /// - public async Task> GetAllSchemeNamesAsync(Ct ct) + public async Task> GetAllSchemeNamesAsync(Ct ct) { using var activity = Tracing.StoreActivitySource.StartActivity("IdentityProviderStore.GetAllSchemeNames"); diff --git a/identity-server/src/EntityFramework.Storage/Stores/PersistedGrantStore.cs b/identity-server/src/EntityFramework.Storage/Stores/PersistedGrantStore.cs index 91f9ad22f..319288614 100644 --- a/identity-server/src/EntityFramework.Storage/Stores/PersistedGrantStore.cs +++ b/identity-server/src/EntityFramework.Storage/Stores/PersistedGrantStore.cs @@ -87,21 +87,19 @@ public class PersistedGrantStore : Duende.IdentityServer.Stores.IPersistedGrantS } /// - public virtual async Task> GetAllAsync(PersistedGrantFilter filter, Ct ct) + public virtual async Task> GetAllAsync(PersistedGrantFilter filter, Ct ct) { using var activity = Tracing.StoreActivitySource.StartActivity("PersistedGrantStore.GetAll"); filter.Validate(); var persistedGrants = await Filter(Context.PersistedGrants.AsQueryable(), filter) + .Select(x => x.ToModel()) .ToArrayAsync(ct); - persistedGrants = Filter(persistedGrants.AsQueryable(), filter).ToArray(); - - var model = persistedGrants.Select(x => x.ToModel()); Logger.LogDebug("{persistedGrantCount} persisted grants found for {@filter}", persistedGrants.Length, filter); - return model; + return persistedGrants; } /// diff --git a/identity-server/src/EntityFramework.Storage/Stores/ResourceStore.cs b/identity-server/src/EntityFramework.Storage/Stores/ResourceStore.cs index be024e192..967f6f6d7 100644 --- a/identity-server/src/EntityFramework.Storage/Stores/ResourceStore.cs +++ b/identity-server/src/EntityFramework.Storage/Stores/ResourceStore.cs @@ -46,7 +46,7 @@ public class ResourceStore : IResourceStore /// The names. /// The cancellation token. /// - public virtual async Task> FindApiResourcesByNameAsync(IEnumerable apiResourceNames, Ct ct) + public virtual async Task> FindApiResourcesByNameAsync(IEnumerable apiResourceNames, Ct ct) { using var activity = Tracing.StoreActivitySource.StartActivity("ResourceStore.FindApiResourcesByName"); activity?.SetTag(Tracing.Properties.ApiResourceNames, apiResourceNames.ToSpaceSeparatedString()); @@ -87,7 +87,7 @@ public class ResourceStore : IResourceStore /// /// The cancellation token. /// - public virtual async Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames, Ct ct) + public virtual async Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames, Ct ct) { using var activity = Tracing.StoreActivitySource.StartActivity("ResourceStore.FindApiResourcesByScopeName"); activity?.SetTag(Tracing.Properties.ScopeNames, scopeNames.ToSpaceSeparatedString()); @@ -121,7 +121,7 @@ public class ResourceStore : IResourceStore /// /// The cancellation token. /// - public virtual async Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames, Ct ct) + public virtual async Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames, Ct ct) { using var activity = Tracing.StoreActivitySource.StartActivity("ResourceStore.FindIdentityResourcesByScopeName"); activity?.SetTag(Tracing.Properties.ScopeNames, scopeNames.ToSpaceSeparatedString()); @@ -152,7 +152,7 @@ public class ResourceStore : IResourceStore /// /// The cancellation token. /// - public virtual async Task> FindApiScopesByNameAsync(IEnumerable scopeNames, Ct ct) + public virtual async Task> FindApiScopesByNameAsync(IEnumerable scopeNames, Ct ct) { using var activity = Tracing.StoreActivitySource.StartActivity("ResourceStore.FindApiScopesByName"); activity?.SetTag(Tracing.Properties.ScopeNames, scopeNames.ToSpaceSeparatedString()); diff --git a/identity-server/src/EntityFramework.Storage/Stores/SamlServiceProviderStore.cs b/identity-server/src/EntityFramework.Storage/Stores/SamlServiceProviderStore.cs deleted file mode 100644 index 88de701b8..000000000 --- a/identity-server/src/EntityFramework.Storage/Stores/SamlServiceProviderStore.cs +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -#nullable enable -using System.Runtime.CompilerServices; -using Duende.IdentityServer.EntityFramework.Interfaces; -using Duende.IdentityServer.EntityFramework.Mappers; -using Duende.IdentityServer.Stores; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Logging; - -namespace Duende.IdentityServer.EntityFramework.Stores; - -/// -/// Implementation of ISamlServiceProviderStore that uses EF. -/// -public class SamlServiceProviderStore : ISamlServiceProviderStore -{ - /// - /// The DbContext. - /// - protected readonly IConfigurationDbContext Context; - - /// - /// The logger. - /// - protected readonly ILogger Logger; - - /// - /// Initializes a new instance of the class. - /// - /// The context. - /// The logger. - public SamlServiceProviderStore( - IConfigurationDbContext context, - ILogger logger) - { - Context = context ?? throw new ArgumentNullException(nameof(context)); - Logger = logger; - } - - /// - public virtual async Task FindByEntityIdAsync(string entityId, Ct ct) - { - using var activity = Tracing.StoreActivitySource.StartActivity("SamlServiceProviderStore.FindByEntityId"); - activity?.SetTag(Tracing.Properties.SamlEntityId, entityId); - - var query = Context.SamlServiceProviders - .Where(x => x.EntityId == entityId) - .Include(x => x.AssertionConsumerServiceUrls) - .Include(x => x.SigningCertificates) - .Include(x => x.EncryptionCertificates) - .Include(x => x.ClaimMappings) - .AsNoTracking() - .AsSplitQuery(); - - var entity = (await query.ToArrayAsync(ct)) - .SingleOrDefault(x => x.EntityId == entityId); - if (entity == null) - { - return null; - } - - var model = entity.ToModel(); - Logger.LogDebug("{entityId} found in database: {found}", entityId, model != null); - return model; - } - - /// - public virtual async IAsyncEnumerable GetAllSamlServiceProvidersAsync([EnumeratorCancellation] Ct ct) - { - using var activity = Tracing.StoreActivitySource.StartActivity("SamlServiceProviderStore.GetAllSamlServiceProviders"); - - var query = Context.SamlServiceProviders - .Include(x => x.AssertionConsumerServiceUrls) - .Include(x => x.SigningCertificates) - .Include(x => x.EncryptionCertificates) - .Include(x => x.ClaimMappings) - .AsNoTracking() - .AsSplitQuery(); - - var count = 0; - await foreach (var entity in query.AsAsyncEnumerable() - .WithCancellation(ct)) - { - count++; - yield return entity.ToModel(); - } - - Logger.LogDebug("Retrieved {count} SAML service providers for enumeration", count); - } -} diff --git a/identity-server/src/EntityFramework.Storage/Stores/SigningKeyStore.cs b/identity-server/src/EntityFramework.Storage/Stores/SigningKeyStore.cs index fb574cf24..944fe79ac 100644 --- a/identity-server/src/EntityFramework.Storage/Stores/SigningKeyStore.cs +++ b/identity-server/src/EntityFramework.Storage/Stores/SigningKeyStore.cs @@ -46,23 +46,22 @@ public class SigningKeyStore : ISigningKeyStore /// /// The cancellation token. /// - public async Task> LoadKeysAsync(Ct ct) + public async Task> LoadKeysAsync(Ct ct) { using var activity = Tracing.StoreActivitySource.StartActivity("SigningKeyStore.LoadKeys"); - var entities = await Context.Keys.Where(x => x.Use == Use) + return await Context.Keys.Where(x => x.Use == Use) .AsNoTracking() - .ToArrayAsync(ct); - return entities.Select(key => new SerializedKey - { - Id = key.Id, - Created = key.Created, - Version = key.Version, - Algorithm = key.Algorithm, - Data = key.Data, - DataProtected = key.DataProtected, - IsX509Certificate = key.IsX509Certificate - }); + .Select(key => new SerializedKey + { + Id = key.Id, + Created = key.Created, + Version = key.Version, + Algorithm = key.Algorithm, + Data = key.Data, + DataProtected = key.DataProtected, + IsX509Certificate = key.IsX509Certificate + }).ToArrayAsync(ct); } /// diff --git a/identity-server/src/EntityFramework/IdentityServerEntityFrameworkBuilderExtensions.cs b/identity-server/src/EntityFramework/IdentityServerEntityFrameworkBuilderExtensions.cs index 0e3d42c3f..c96423139 100644 --- a/identity-server/src/EntityFramework/IdentityServerEntityFrameworkBuilderExtensions.cs +++ b/identity-server/src/EntityFramework/IdentityServerEntityFrameworkBuilderExtensions.cs @@ -49,7 +49,6 @@ public static class IdentityServerEntityFrameworkBuilderExtensions builder.AddResourceStore(); builder.AddCorsPolicyService(); builder.AddIdentityProviderStore(); - builder.AddSamlServiceProviderStore(); return builder; } @@ -69,7 +68,6 @@ public static class IdentityServerEntityFrameworkBuilderExtensions builder.AddResourceStoreCache(); builder.AddCorsPolicyCache(); builder.AddIdentityProviderStoreCache(); - builder.AddSamlServiceProviderStoreCache(); return builder; } diff --git a/identity-server/src/IdentityServer.ConformanceReport/IdentityServer.ConformanceReport.csproj b/identity-server/src/IdentityServer.ConformanceReport/IdentityServer.ConformanceReport.csproj index ae1394912..dc8b4f399 100644 --- a/identity-server/src/IdentityServer.ConformanceReport/IdentityServer.ConformanceReport.csproj +++ b/identity-server/src/IdentityServer.ConformanceReport/IdentityServer.ConformanceReport.csproj @@ -11,9 +11,12 @@ README.md + + + + - diff --git a/identity-server/src/IdentityServer/Configuration/DependencyInjection/BuilderExtensions/Core.cs b/identity-server/src/IdentityServer/Configuration/DependencyInjection/BuilderExtensions/Core.cs index b5bd1056c..b60d47643 100644 --- a/identity-server/src/IdentityServer/Configuration/DependencyInjection/BuilderExtensions/Core.cs +++ b/identity-server/src/IdentityServer/Configuration/DependencyInjection/BuilderExtensions/Core.cs @@ -374,7 +374,6 @@ public static class IdentityServerBuilderExtensionsCore builder.Services.TryAddTransient(); builder.Services.TryAddTransient(); builder.Services.TryAddTransient(); - builder.Services.TryAddTransient(); builder.Services.TryAddTransient(); builder.Services.TryAddTransient(); builder.Services.TryAddTransient(); diff --git a/identity-server/src/IdentityServer/Configuration/DependencyInjection/BuilderExtensions/Saml.cs b/identity-server/src/IdentityServer/Configuration/DependencyInjection/BuilderExtensions/Saml.cs index 409345681..402744c87 100644 --- a/identity-server/src/IdentityServer/Configuration/DependencyInjection/BuilderExtensions/Saml.cs +++ b/identity-server/src/IdentityServer/Configuration/DependencyInjection/BuilderExtensions/Saml.cs @@ -14,7 +14,6 @@ using Duende.IdentityServer.Internal.Saml.SingleSignin; using Duende.IdentityServer.Internal.Saml.SingleSignin.Models; using Duende.IdentityServer.Saml; using Duende.IdentityServer.Stores; -using Duende.IdentityServer.Validation; using Microsoft.Extensions.DependencyInjection.Extensions; using static Duende.IdentityServer.IdentityServerConstants; @@ -129,38 +128,7 @@ public static class IdentityServerBuilderExtensionsSaml public static IIdentityServerBuilder AddSamlServiceProviderStore(this IIdentityServerBuilder builder) where T : class, ISamlServiceProviderStore { - builder.Services.TryAddTransient(); - builder.Services.AddTransient>(); - return builder; - } - - /// - /// Adds the SAML service provider store cache. - /// - /// The type of the implementation. - /// The builder. - /// - public static IIdentityServerBuilder AddSamlServiceProviderStoreCache(this IIdentityServerBuilder builder) - where T : class, ISamlServiceProviderStore - { - builder.Services.TryAddTransient(); - builder.Services.AddTransient>(); - builder.Services.AddTransient>>(); - return builder; - } - - /// - /// Adds a SAML service provider configuration validator. - /// - /// The type of the implementation. - /// The builder. - /// - public static IIdentityServerBuilder AddSamlServiceProviderConfigurationValidator( - this IIdentityServerBuilder builder) - where T : class, ISamlServiceProviderConfigurationValidator - { - builder.Services.AddTransient(); + builder.Services.AddTransient(); return builder; } } diff --git a/identity-server/src/IdentityServer/Configuration/DependencyInjection/Options/CachingOptions.cs b/identity-server/src/IdentityServer/Configuration/DependencyInjection/Options/CachingOptions.cs index bc0e25c35..52f18f863 100644 --- a/identity-server/src/IdentityServer/Configuration/DependencyInjection/Options/CachingOptions.cs +++ b/identity-server/src/IdentityServer/Configuration/DependencyInjection/Options/CachingOptions.cs @@ -44,9 +44,4 @@ public class CachingOptions /// The timeout for concurrency locking in the default cache. /// public TimeSpan CacheLockTimeout { get; set; } = TimeSpan.FromSeconds(60); - - /// - /// Gets or sets the SAML service provider store expiration. - /// - public TimeSpan SamlServiceProviderStoreExpiration { get; set; } = Default; } diff --git a/identity-server/src/IdentityServer/Configuration/DependencyInjection/Options/PreviewFeatureOptions.cs b/identity-server/src/IdentityServer/Configuration/DependencyInjection/Options/PreviewFeatureOptions.cs index 6321a3c45..b013d655f 100644 --- a/identity-server/src/IdentityServer/Configuration/DependencyInjection/Options/PreviewFeatureOptions.cs +++ b/identity-server/src/IdentityServer/Configuration/DependencyInjection/Options/PreviewFeatureOptions.cs @@ -14,7 +14,7 @@ public class PreviewFeatureOptions public bool EnableDiscoveryDocumentCache { get; set; } /// - /// When clients authenticate with private_key_jwt assertions, validate the audience of the assertion strictly: the audience must be this IdentityServer's issuer identifier as a single string. + /// When clients authenticate with private_key_jwt assertions, validate the audience of the assertion strictly: the audience must be this IdentityServer's issuer identifier as the sole audience value (either a plain string or a single-element array). /// public bool StrictClientAssertionAudienceValidation { get; set; } diff --git a/identity-server/src/IdentityServer/Configuration/DependencyInjection/Options/SamlOptions.cs b/identity-server/src/IdentityServer/Configuration/DependencyInjection/Options/SamlOptions.cs index a3842537d..98bae4b35 100644 --- a/identity-server/src/IdentityServer/Configuration/DependencyInjection/Options/SamlOptions.cs +++ b/identity-server/src/IdentityServer/Configuration/DependencyInjection/Options/SamlOptions.cs @@ -100,6 +100,12 @@ public class SamlOptions /// public int MaxRelayStateLength { get; set; } = 80; + /// + /// Gets or sets the name of the cookie used to store the SAML sign-in state identifier. + /// Defaults to "__IdsSvr_SamlSigninState". + /// + public string SigninStateCookieName { get; set; } = "__IdsSvr_SamlSigninState"; + /// /// Gets or sets the user interaction options for SAML endpoints. /// diff --git a/identity-server/src/IdentityServer/Events/Infrastructure/EventIds.cs b/identity-server/src/IdentityServer/Events/Infrastructure/EventIds.cs index 1c152c887..0c6f71e56 100644 --- a/identity-server/src/IdentityServer/Events/Infrastructure/EventIds.cs +++ b/identity-server/src/IdentityServer/Events/Infrastructure/EventIds.cs @@ -44,7 +44,6 @@ public static class EventIds public const int UnhandledException = ErrorEventsStart + 0; public const int InvalidClientConfiguration = ErrorEventsStart + 1; public const int InvalidIdentityProviderConfiguration = ErrorEventsStart + 2; - public const int InvalidSamlServiceProviderConfiguration = ErrorEventsStart + 3; ////////////////////////////////////////////////////// /// Grants related events diff --git a/identity-server/src/IdentityServer/Events/InvalidSamlServiceProviderConfiguration.cs b/identity-server/src/IdentityServer/Events/InvalidSamlServiceProviderConfiguration.cs deleted file mode 100644 index 2709a833c..000000000 --- a/identity-server/src/IdentityServer/Events/InvalidSamlServiceProviderConfiguration.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -using Duende.IdentityServer.Models; - -namespace Duende.IdentityServer.Events; - -/// -/// Event for invalid SAML service provider configuration. -/// -public class InvalidSamlServiceProviderConfigurationEvent : Event -{ - /// - /// Initializes a new instance of the class. - /// - /// The SAML service provider. - /// The error message. - public InvalidSamlServiceProviderConfigurationEvent(SamlServiceProvider serviceProvider, string errorMessage) - : base(EventCategories.Error, - "Invalid SAML Service Provider Configuration", - EventTypes.Error, - EventIds.InvalidSamlServiceProviderConfiguration, - errorMessage) - { - EntityId = serviceProvider.EntityId; - DisplayName = serviceProvider.DisplayName ?? "unknown name"; - } - - /// - /// Gets or sets the entity ID of the SAML service provider. - /// - public string EntityId { get; set; } - - /// - /// Gets or sets the display name of the SAML service provider. - /// - public string DisplayName { get; set; } -} diff --git a/identity-server/src/IdentityServer/Extensions/HttpContextExtensions.cs b/identity-server/src/IdentityServer/Extensions/HttpContextExtensions.cs index 60724792a..2824e5e96 100644 --- a/identity-server/src/IdentityServer/Extensions/HttpContextExtensions.cs +++ b/identity-server/src/IdentityServer/Extensions/HttpContextExtensions.cs @@ -57,7 +57,7 @@ public static class HttpContextExtensions LogoutNotificationContext endSessionMsg = null; // if we have a logout message, then that take precedence over the current user - if (logoutMessage?.ClientIds?.Any() == true || logoutMessage?.SamlSessions?.Any() == true) + if (logoutMessage?.ClientIds?.Count > 0 || logoutMessage?.SamlSessions?.Count > 0) { var clientIds = logoutMessage.ClientIds ?? []; var samlSessions = logoutMessage.SamlSessions?.ToList() ?? []; @@ -65,7 +65,7 @@ public static class HttpContextExtensions // check if current user is same, since we might have new clients (albeit unlikely) if (currentSubId == logoutMessage.SubjectId) { - clientIds = clientIds.Union(await userSession.GetClientListAsync(context.RequestAborted)); + clientIds = clientIds.Union(await userSession.GetClientListAsync(context.RequestAborted)).ToArray(); var currentSamlSessions = await userSession.GetSamlSessionListAsync(context.RequestAborted); samlSessions = samlSessions.Union(currentSamlSessions).ToList(); } @@ -89,8 +89,8 @@ public static class HttpContextExtensions var samlSessions = await userSession.GetSamlSessionListAsync(context.RequestAborted); var samlEntityIds = samlSessions.Select(s => s.EntityId); - if ((clientIds.Any() && await AnyClientHasFrontChannelLogout(clientIds)) || - (samlEntityIds.Any() && await AnySamlServiceProviderHasFrontChannelLogout(samlEntityIds, context.RequestAborted))) + if ((clientIds.Count > 0 && await AnyClientHasFrontChannelLogout(clientIds)) || + (samlSessions.Count > 0 && await AnySamlServiceProviderHasFrontChannelLogout(samlEntityIds, context.RequestAborted))) { endSessionMsg = new LogoutNotificationContext { diff --git a/identity-server/src/IdentityServer/Extensions/IResourceStoreExtensions.cs b/identity-server/src/IdentityServer/Extensions/IResourceStoreExtensions.cs index fada564ac..aa44f7e9a 100644 --- a/identity-server/src/IdentityServer/Extensions/IResourceStoreExtensions.cs +++ b/identity-server/src/IdentityServer/Extensions/IResourceStoreExtensions.cs @@ -114,7 +114,7 @@ public static class IResourceStoreExtensions /// The scope names. /// The cancellation token. /// - public static async Task> FindEnabledIdentityResourcesByScopeAsync(this IResourceStore store, IEnumerable scopeNames, Ct ct) => (await store.FindIdentityResourcesByScopeNameAsync(scopeNames, ct)).Where(x => x.Enabled).ToArray(); + public static async Task> FindEnabledIdentityResourcesByScopeAsync(this IResourceStore store, IEnumerable scopeNames, Ct ct) => (await store.FindIdentityResourcesByScopeNameAsync(scopeNames, ct)).Where(x => x.Enabled).ToArray(); /// /// Finds the enabled API resources by name. @@ -122,5 +122,5 @@ public static class IResourceStoreExtensions /// The store. /// The resource names. /// The cancellation token. - public static async Task> FindEnabledApiResourcesByNameAsync(this IResourceStore store, IEnumerable resourceNames, Ct ct) => (await store.FindApiResourcesByNameAsync(resourceNames, ct)).Where(x => x.Enabled).ToArray(); + public static async Task> FindEnabledApiResourcesByNameAsync(this IResourceStore store, IEnumerable resourceNames, Ct ct) => (await store.FindApiResourcesByNameAsync(resourceNames, ct)).Where(x => x.Enabled).ToArray(); } diff --git a/identity-server/src/IdentityServer/Extensions/ISamlServiceProviderStoreExtensions.cs b/identity-server/src/IdentityServer/Extensions/ISamlServiceProviderStoreExtensions.cs deleted file mode 100644 index c172bbeea..000000000 --- a/identity-server/src/IdentityServer/Extensions/ISamlServiceProviderStoreExtensions.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -#nullable enable -using Duende.IdentityServer.Models; - -namespace Duende.IdentityServer.Stores; - -/// -/// Extension methods for ISamlServiceProviderStore -/// -public static class ISamlServiceProviderStoreExtensions -{ - /// - /// Finds an enabled SAML service provider by entity ID. - /// - public static async Task FindEnabledSamlServiceProviderByEntityIdAsync( - this ISamlServiceProviderStore store, string entityId, Ct ct) - { - var sp = await store.FindByEntityIdAsync(entityId, ct); - if (sp != null && sp.Enabled) - { - return sp; - } - return null; - } -} diff --git a/identity-server/src/IdentityServer/Hosting/DynamicProviders/Store/CachingIdentityProviderStore.cs b/identity-server/src/IdentityServer/Hosting/DynamicProviders/Store/CachingIdentityProviderStore.cs index 8d4baa2a0..626dcaa64 100644 --- a/identity-server/src/IdentityServer/Hosting/DynamicProviders/Store/CachingIdentityProviderStore.cs +++ b/identity-server/src/IdentityServer/Hosting/DynamicProviders/Store/CachingIdentityProviderStore.cs @@ -21,7 +21,7 @@ public class CachingIdentityProviderStore : IIdentityProviderStore { private readonly IIdentityProviderStore _inner; private readonly ICache _cache; - private readonly ICache> _allCache; + private readonly ICache> _allCache; private readonly IdentityServerOptions _options; private readonly IHttpContextAccessor _httpContextAccessor; private readonly ILogger> _logger; @@ -37,7 +37,7 @@ public class CachingIdentityProviderStore : IIdentityProviderStore /// public CachingIdentityProviderStore(T inner, ICache cache, - ICache> allCache, + ICache> allCache, IdentityServerOptions options, IHttpContextAccessor httpContextAccessor, ILogger> logger) @@ -51,7 +51,7 @@ public class CachingIdentityProviderStore : IIdentityProviderStore } /// - public async Task> GetAllSchemeNamesAsync(Ct ct) + public async Task> GetAllSchemeNamesAsync(Ct ct) { using var activity = Tracing.StoreActivitySource.StartActivity("CachingIdentityProviderStore.GetAllSchemeNames"); diff --git a/identity-server/src/IdentityServer/Hosting/DynamicProviders/Store/InMemoryIdentityProviderStore.cs b/identity-server/src/IdentityServer/Hosting/DynamicProviders/Store/InMemoryIdentityProviderStore.cs index 4b44a4418..543ad9c58 100644 --- a/identity-server/src/IdentityServer/Hosting/DynamicProviders/Store/InMemoryIdentityProviderStore.cs +++ b/identity-server/src/IdentityServer/Hosting/DynamicProviders/Store/InMemoryIdentityProviderStore.cs @@ -13,7 +13,7 @@ internal class InMemoryIdentityProviderStore : IIdentityProviderStore public InMemoryIdentityProviderStore(IEnumerable providers) => _providers = providers; - public Task> GetAllSchemeNamesAsync(Ct ct) + public Task> GetAllSchemeNamesAsync(Ct ct) { using var activity = Tracing.StoreActivitySource.StartActivity("InMemoryOidcProviderStore.GetAllSchemeNames"); @@ -22,9 +22,9 @@ internal class InMemoryIdentityProviderStore : IIdentityProviderStore Enabled = x.Enabled, DisplayName = x.DisplayName, Scheme = x.Scheme - }); + }).ToArray(); - return Task.FromResult(items); + return Task.FromResult>(items); } public Task GetBySchemeAsync(string scheme, Ct ct) diff --git a/identity-server/src/IdentityServer/Hosting/DynamicProviders/Store/NonCachingIdentityProviderStore.cs b/identity-server/src/IdentityServer/Hosting/DynamicProviders/Store/NonCachingIdentityProviderStore.cs index f25f55a72..da9009119 100644 --- a/identity-server/src/IdentityServer/Hosting/DynamicProviders/Store/NonCachingIdentityProviderStore.cs +++ b/identity-server/src/IdentityServer/Hosting/DynamicProviders/Store/NonCachingIdentityProviderStore.cs @@ -38,7 +38,7 @@ public class NonCachingIdentityProviderStore : IIdentityProviderStore } /// - public Task> GetAllSchemeNamesAsync(Ct ct) => _inner.GetAllSchemeNamesAsync(ct); + public Task> GetAllSchemeNamesAsync(Ct ct) => _inner.GetAllSchemeNamesAsync(ct); /// public async Task GetBySchemeAsync(string scheme, Ct ct) diff --git a/identity-server/src/IdentityServer/Hosting/DynamicProviders/Store/NopIdentityProviderStore.cs b/identity-server/src/IdentityServer/Hosting/DynamicProviders/Store/NopIdentityProviderStore.cs index 3dfc07139..db823d5fa 100644 --- a/identity-server/src/IdentityServer/Hosting/DynamicProviders/Store/NopIdentityProviderStore.cs +++ b/identity-server/src/IdentityServer/Hosting/DynamicProviders/Store/NopIdentityProviderStore.cs @@ -9,7 +9,7 @@ namespace Duende.IdentityServer.Hosting.DynamicProviders; internal class NopIdentityProviderStore : IIdentityProviderStore { - public Task> GetAllSchemeNamesAsync(Ct _) => Task.FromResult(Enumerable.Empty()); + public Task> GetAllSchemeNamesAsync(Ct _) => Task.FromResult>(Array.Empty()); public Task GetBySchemeAsync(string scheme, Ct _) => Task.FromResult(null); } diff --git a/identity-server/src/IdentityServer/Hosting/DynamicProviders/Store/ValidatingIdentityProviderStore.cs b/identity-server/src/IdentityServer/Hosting/DynamicProviders/Store/ValidatingIdentityProviderStore.cs index 1185ec479..2d4d2d8c4 100644 --- a/identity-server/src/IdentityServer/Hosting/DynamicProviders/Store/ValidatingIdentityProviderStore.cs +++ b/identity-server/src/IdentityServer/Hosting/DynamicProviders/Store/ValidatingIdentityProviderStore.cs @@ -38,7 +38,7 @@ public class ValidatingIdentityProviderStore : IIdentityProviderStore } /// - public Task> GetAllSchemeNamesAsync(Ct ct) => _inner.GetAllSchemeNamesAsync(ct); + public Task> GetAllSchemeNamesAsync(Ct ct) => _inner.GetAllSchemeNamesAsync(ct); /// public async Task GetBySchemeAsync(string scheme, Ct ct) diff --git a/identity-server/src/IdentityServer/Internal/Saml/EmptySamlServiceProviderStore.cs b/identity-server/src/IdentityServer/Internal/Saml/EmptySamlServiceProviderStore.cs index 6d58feed4..989159e2d 100644 --- a/identity-server/src/IdentityServer/Internal/Saml/EmptySamlServiceProviderStore.cs +++ b/identity-server/src/IdentityServer/Internal/Saml/EmptySamlServiceProviderStore.cs @@ -1,8 +1,6 @@ // Copyright (c) Duende Software. All rights reserved. // See LICENSE in the project root for license information. -#nullable enable -using System.Runtime.CompilerServices; using Duende.IdentityServer.Models; using Duende.IdentityServer.Stores; @@ -10,13 +8,5 @@ namespace Duende.IdentityServer.Internal.Saml; internal class EmptySamlServiceProviderStore : ISamlServiceProviderStore { - public Task FindByEntityIdAsync(string entityId, Ct _) => Task.FromResult(null); - -#if NET10_0_OR_GREATER - public async IAsyncEnumerable GetAllSamlServiceProvidersAsync([EnumeratorCancellation] Ct _) - { - await Task.CompletedTask; - yield break; - } -#endif + public Task FindByEntityIdAsync(string entityId, Ct ct) => Task.FromResult(null); } diff --git a/identity-server/src/IdentityServer/Internal/Saml/NopSamlLogoutNotificationService.cs b/identity-server/src/IdentityServer/Internal/Saml/NopSamlLogoutNotificationService.cs index 97a2fb983..8976433cd 100644 --- a/identity-server/src/IdentityServer/Internal/Saml/NopSamlLogoutNotificationService.cs +++ b/identity-server/src/IdentityServer/Internal/Saml/NopSamlLogoutNotificationService.cs @@ -10,6 +10,6 @@ namespace Duende.IdentityServer.Internal.Saml; internal class NopSamlLogoutNotificationService : ISamlLogoutNotificationService { - public Task> GetSamlFrontChannelLogoutsAsync(LogoutNotificationContext context, Ct ct) => - Task.FromResult(Enumerable.Empty()); + public Task> GetSamlFrontChannelLogoutsAsync(LogoutNotificationContext context, Ct ct) => + Task.FromResult>(Array.Empty()); } diff --git a/identity-server/src/IdentityServer/Internal/Saml/SingleLogout/SamlLogoutNotificationService.cs b/identity-server/src/IdentityServer/Internal/Saml/SingleLogout/SamlLogoutNotificationService.cs index 2e48c1ded..08b9181cf 100644 --- a/identity-server/src/IdentityServer/Internal/Saml/SingleLogout/SamlLogoutNotificationService.cs +++ b/identity-server/src/IdentityServer/Internal/Saml/SingleLogout/SamlLogoutNotificationService.cs @@ -15,13 +15,13 @@ internal class SamlLogoutNotificationService( SamlFrontChannelLogoutRequestBuilder frontChannelLogoutRequestBuilder, ILogger logger) : ISamlLogoutNotificationService { - public async Task> GetSamlFrontChannelLogoutsAsync(LogoutNotificationContext context, Ct ct) + public async Task> GetSamlFrontChannelLogoutsAsync(LogoutNotificationContext context, Ct ct) { using var activity = Tracing.ServiceActivitySource.StartActivity("LogoutNotificationService.GetSamlFrontChannelLogoutUrls"); var logoutUrls = new List(); - if (!context.SamlSessions.Any()) + if (context.SamlSessions.Count == 0) { logger.NoSamlServiceProvidersToNotifyForLogout(LogLevel.Debug); return logoutUrls; diff --git a/identity-server/src/IdentityServer/Internal/Saml/SingleSignin/AuthNRequestParser.cs b/identity-server/src/IdentityServer/Internal/Saml/SingleSignin/AuthNRequestParser.cs index 33aefc0f9..cb7172348 100644 --- a/identity-server/src/IdentityServer/Internal/Saml/SingleSignin/AuthNRequestParser.cs +++ b/identity-server/src/IdentityServer/Internal/Saml/SingleSignin/AuthNRequestParser.cs @@ -115,7 +115,7 @@ internal class AuthNRequestParser : SamlProtocolMessageParser } // Parse Comparison attribute (defaults to "exact" per spec) - var comparisonAttr = requestedAuthnContextElement.Attribute(RequestedAuthnContext.AttributeNames.Comparison)?.Value; + var comparisonAttr = requestedAuthnContextElement.Attribute(RequestedAuthnContext.AttributeNames.Comparison!)?.Value; var comparison = AuthnContextComparisonExtensions.Parse(comparisonAttr); var assertionNs = XNamespace.Get(SamlConstants.Namespaces.Assertion); diff --git a/identity-server/src/IdentityServer/Internal/Saml/SingleSignin/SamlSigninStateIdCookie.cs b/identity-server/src/IdentityServer/Internal/Saml/SingleSignin/SamlSigninStateIdCookie.cs index 4b8aca936..b4b31129c 100644 --- a/identity-server/src/IdentityServer/Internal/Saml/SingleSignin/SamlSigninStateIdCookie.cs +++ b/identity-server/src/IdentityServer/Internal/Saml/SingleSignin/SamlSigninStateIdCookie.cs @@ -2,14 +2,16 @@ // See LICENSE in the project root for license information. using System.Diagnostics.CodeAnalysis; +using Duende.IdentityServer.Configuration; using Duende.IdentityServer.Internal.Saml.SingleSignin.Models; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Options; namespace Duende.IdentityServer.Internal.Saml.SingleSignin; -internal class SamlSigninStateIdCookie(IHttpContextAccessor httpContextAccessor) +internal sealed class SamlSigninStateIdCookie(IHttpContextAccessor httpContextAccessor, IOptions options) { - private const string CookieName = "__Host-idsrv.SamlSigninState"; + private readonly string _cookieName = options.Value.SigninStateCookieName; private static readonly TimeSpan CookieLifetime = TimeSpan.FromMinutes(5); private HttpContext HttpContext => httpContextAccessor.HttpContext @@ -27,14 +29,14 @@ internal class SamlSigninStateIdCookie(IHttpContextAccessor httpContextAccessor) Expires = DateTimeOffset.UtcNow.Add(CookieLifetime) }; - HttpContext.Response.Cookies.Append(CookieName, stateId.Value.ToString(), cookieOptions); + HttpContext.Response.Cookies.Append(_cookieName, stateId.Value.ToString(), cookieOptions); } internal bool TryGetSamlSigninStateId([NotNullWhen(true)] out StateId? stateId) { stateId = null; - if (!HttpContext.Request.Cookies.TryGetValue(CookieName, out var rawStateId) || string.IsNullOrEmpty(rawStateId)) + if (!HttpContext.Request.Cookies.TryGetValue(_cookieName, out var rawStateId) || string.IsNullOrEmpty(rawStateId)) { return false; } @@ -57,7 +59,7 @@ internal class SamlSigninStateIdCookie(IHttpContextAccessor httpContextAccessor) } } - internal void ClearAuthenticationState() => HttpContext.Response.Cookies.Delete(CookieName, new CookieOptions + internal void ClearAuthenticationState() => HttpContext.Response.Cookies.Delete(_cookieName, new CookieOptions { HttpOnly = true, Secure = true, diff --git a/identity-server/src/IdentityServer/Licensing/V2/Diagnostics/DiagnosticEntries/RegisteredImplementationsDiagnosticEntry.cs b/identity-server/src/IdentityServer/Licensing/V2/Diagnostics/DiagnosticEntries/RegisteredImplementationsDiagnosticEntry.cs index a8a18f5de..29aab2a64 100644 --- a/identity-server/src/IdentityServer/Licensing/V2/Diagnostics/DiagnosticEntries/RegisteredImplementationsDiagnosticEntry.cs +++ b/identity-server/src/IdentityServer/Licensing/V2/Diagnostics/DiagnosticEntries/RegisteredImplementationsDiagnosticEntry.cs @@ -160,7 +160,6 @@ internal class RegisteredImplementationsDiagnosticEntry(ServiceCollectionAccesso new(typeof(IRedirectUriValidator), [typeof(StrictRedirectUriValidator)]), new(typeof(IResourceOwnerPasswordValidator), [typeof(NotSupportedResourceOwnerPasswordValidator)]), new(typeof(IResourceValidator), [typeof(DefaultResourceValidator)]), - new(typeof(ISamlServiceProviderConfigurationValidator), [typeof(DefaultSamlServiceProviderConfigurationValidator)]), new(typeof(IScopeParser), [typeof(DefaultScopeParser)]), new(typeof(ISecretParser), [typeof(BasicAuthenticationSecretParser), typeof(PostBodySecretParser)]), new(typeof(ISecretsListParser), [typeof(SecretParser)]), diff --git a/identity-server/src/IdentityServer/Models/Contexts/LogoutNotificationContext.cs b/identity-server/src/IdentityServer/Models/Contexts/LogoutNotificationContext.cs index d2cfacee4..2b53143af 100644 --- a/identity-server/src/IdentityServer/Models/Contexts/LogoutNotificationContext.cs +++ b/identity-server/src/IdentityServer/Models/Contexts/LogoutNotificationContext.cs @@ -31,14 +31,14 @@ public class LogoutNotificationContext /// /// The list of client Ids that the user has authenticated to. /// - public IEnumerable ClientIds { get; set; } = default!; + public IReadOnlyCollection ClientIds { get; set; } = default!; /// /// The SAML Service Provider sessions that the user has authenticated to. /// Contains full session data including NameId, SessionIndex, and NameIdFormat /// required to construct logout requests. /// - public IEnumerable SamlSessions { get; set; } = []; + public IReadOnlyCollection SamlSessions { get; set; } = []; /// /// Indicates why the user's session ended, if known. diff --git a/identity-server/src/IdentityServer/Models/Messages/LogoutRequest.cs b/identity-server/src/IdentityServer/Models/Messages/LogoutRequest.cs index b65e06b32..026e3f1a7 100644 --- a/identity-server/src/IdentityServer/Models/Messages/LogoutRequest.cs +++ b/identity-server/src/IdentityServer/Models/Messages/LogoutRequest.cs @@ -90,7 +90,7 @@ public class LogoutMessage /// /// Ids of clients known to have an authentication session for user at end session time /// - public IEnumerable? ClientIds { get; set; } + public IReadOnlyCollection? ClientIds { get; set; } /// /// Gets or sets the EntityId of the SAML Service Provider that initiated logout. @@ -114,7 +114,7 @@ public class LogoutMessage /// SAML Service Provider sessions for the user at logout time. /// Contains full session data required for logout notifications. /// - public IEnumerable? SamlSessions { get; set; } + public IReadOnlyCollection? SamlSessions { get; set; } /// /// The UI locales. @@ -130,9 +130,9 @@ public class LogoutMessage /// Flag to indicate if the payload contains useful information or not to avoid serialization. /// internal bool ContainsPayload => ClientId.IsPresent() - || ClientIds?.Any() == true + || ClientIds?.Count > 0 || SamlServiceProviderEntityId.IsPresent() - || SamlSessions?.Any() == true; + || SamlSessions?.Count > 0; } /// @@ -194,7 +194,7 @@ public class LogoutRequest /// /// Ids of clients known to have an authentication session for user at end session time /// - public IEnumerable? ClientIds { get; set; } + public IReadOnlyCollection? ClientIds { get; set; } /// /// Gets or sets the EntityId of the SAML Service Provider that initiated logout. @@ -218,7 +218,7 @@ public class LogoutRequest /// SAML Service Provider sessions for the user at logout time. /// Contains full session data required for logout notifications. /// - public IEnumerable? SamlSessions { get; set; } + public IReadOnlyCollection? SamlSessions { get; set; } /// /// The UI locales. diff --git a/identity-server/src/IdentityServer/ResponseHandling/Default/DiscoveryResponseGenerator.cs b/identity-server/src/IdentityServer/ResponseHandling/Default/DiscoveryResponseGenerator.cs index 4aa17934d..aafefb147 100644 --- a/identity-server/src/IdentityServer/ResponseHandling/Default/DiscoveryResponseGenerator.cs +++ b/identity-server/src/IdentityServer/ResponseHandling/Default/DiscoveryResponseGenerator.cs @@ -107,7 +107,7 @@ public class DiscoveryResponseGenerator : IDiscoveryResponseGenerator // jwks if (Options.Discovery.ShowKeySet) { - if ((await Keys.GetValidationKeysAsync(ct)).Any()) + if ((await Keys.GetValidationKeysAsync(ct)).Count > 0) { entries.Add(OidcConstants.Discovery.JwksUri, baseUrl + ProtocolRoutePaths.DiscoveryWebKeys); } @@ -344,7 +344,7 @@ public class DiscoveryResponseGenerator : IDiscoveryResponseGenerator } var signingCredentials = await Keys.GetAllSigningCredentialsAsync(ct); - if (signingCredentials.Any()) + if (signingCredentials.Count > 0) { var signingAlgorithms = signingCredentials.Select(c => c.Algorithm).Distinct(); entries.Add(OidcConstants.Discovery.IdTokenSigningAlgorithmsSupported, signingAlgorithms); @@ -460,7 +460,7 @@ public class DiscoveryResponseGenerator : IDiscoveryResponseGenerator /// Creates the JWK document. /// /// The cancellation token. - public virtual async Task> CreateJwkDocumentAsync(Ct ct) + public virtual async Task> CreateJwkDocumentAsync(Ct ct) { using var activity = Tracing.BasicActivitySource.StartActivity("DiscoveryResponseGenerator.CreateJwkDocument"); diff --git a/identity-server/src/IdentityServer/ResponseHandling/IDiscoveryResponseGenerator.cs b/identity-server/src/IdentityServer/ResponseHandling/IDiscoveryResponseGenerator.cs index 365c6b5df..3fb1d3bab 100644 --- a/identity-server/src/IdentityServer/ResponseHandling/IDiscoveryResponseGenerator.cs +++ b/identity-server/src/IdentityServer/ResponseHandling/IDiscoveryResponseGenerator.cs @@ -23,5 +23,5 @@ public interface IDiscoveryResponseGenerator /// Creates the JWK document. /// /// The cancellation token. - Task> CreateJwkDocumentAsync(Ct ct); + Task> CreateJwkDocumentAsync(Ct ct); } diff --git a/identity-server/src/IdentityServer/Saml/ISamlClaimsMapper.cs b/identity-server/src/IdentityServer/Saml/ISamlClaimsMapper.cs index a6c4749ee..c85b78b72 100644 --- a/identity-server/src/IdentityServer/Saml/ISamlClaimsMapper.cs +++ b/identity-server/src/IdentityServer/Saml/ISamlClaimsMapper.cs @@ -19,5 +19,5 @@ public interface ISamlClaimsMapper /// /// Context with information about the authentication request for which claims need to be mapped /// The mapped SAML attributes - Task> MapClaimsAsync(SamlClaimsMappingContext claimsMappingContext); + Task> MapClaimsAsync(SamlClaimsMappingContext claimsMappingContext); } diff --git a/identity-server/src/IdentityServer/Saml/ISamlLogoutNotificationService.cs b/identity-server/src/IdentityServer/Saml/ISamlLogoutNotificationService.cs index 3d0f8b5bf..4b524041f 100644 --- a/identity-server/src/IdentityServer/Saml/ISamlLogoutNotificationService.cs +++ b/identity-server/src/IdentityServer/Saml/ISamlLogoutNotificationService.cs @@ -12,5 +12,5 @@ public interface ISamlLogoutNotificationService /// /// The context for the logout notification. /// The cancellation token. - Task> GetSamlFrontChannelLogoutsAsync(LogoutNotificationContext context, Ct ct); + Task> GetSamlFrontChannelLogoutsAsync(LogoutNotificationContext context, Ct ct); } diff --git a/identity-server/src/IdentityServer/Services/Default/DefaultBackChannelLogoutService.cs b/identity-server/src/IdentityServer/Services/Default/DefaultBackChannelLogoutService.cs index 2906510cb..2c44b94a2 100644 --- a/identity-server/src/IdentityServer/Services/Default/DefaultBackChannelLogoutService.cs +++ b/identity-server/src/IdentityServer/Services/Default/DefaultBackChannelLogoutService.cs @@ -80,7 +80,7 @@ public class DefaultBackChannelLogoutService : IBackChannelLogoutService using var activity = Tracing.ServiceActivitySource.StartActivity("DefaultBackChannelLogoutService.SendLogoutNotifications"); var backChannelRequests = await LogoutNotificationService.GetBackChannelLogoutNotificationsAsync(context, ct); - if (backChannelRequests.Any()) + if (backChannelRequests.Count > 0) { await SendLogoutNotificationsAsync(backChannelRequests, ct); } diff --git a/identity-server/src/IdentityServer/Services/Default/DefaultBackchannelAuthenticationInteractionService.cs b/identity-server/src/IdentityServer/Services/Default/DefaultBackchannelAuthenticationInteractionService.cs index a5ef7f062..25e5e4b56 100644 --- a/identity-server/src/IdentityServer/Services/Default/DefaultBackchannelAuthenticationInteractionService.cs +++ b/identity-server/src/IdentityServer/Services/Default/DefaultBackchannelAuthenticationInteractionService.cs @@ -88,7 +88,7 @@ public class DefaultBackchannelAuthenticationInteractionService : IBackchannelAu } /// - public async Task> GetPendingLoginRequestsForCurrentUserAsync(Ct ct) + public async Task> GetPendingLoginRequestsForCurrentUserAsync(Ct ct) { using var activity = Tracing.ServiceActivitySource.StartActivity("DefaultBackchannelAuthenticationInteractionService.GetPendingLoginRequestsForCurrentUser"); diff --git a/identity-server/src/IdentityServer/Services/Default/DefaultClaimsService.cs b/identity-server/src/IdentityServer/Services/Default/DefaultClaimsService.cs index c19f45fd1..a045a97c3 100644 --- a/identity-server/src/IdentityServer/Services/Default/DefaultClaimsService.cs +++ b/identity-server/src/IdentityServer/Services/Default/DefaultClaimsService.cs @@ -39,7 +39,7 @@ public class DefaultClaimsService : IClaimsService } /// - public virtual async Task> GetIdentityTokenClaimsAsync(ClaimsPrincipal subject, ResourceValidationResult resources, bool includeAllIdentityClaims, ValidatedRequest request, Ct ct) + public virtual async Task> GetIdentityTokenClaimsAsync(ClaimsPrincipal subject, ResourceValidationResult resources, bool includeAllIdentityClaims, ValidatedRequest request, Ct ct) { using var activity = Tracing.ServiceActivitySource.StartActivity("DefaultClaimsService.GetIdentityTokenClaims"); @@ -93,7 +93,7 @@ public class DefaultClaimsService : IClaimsService } /// - public virtual async Task> GetAccessTokenClaimsAsync(ClaimsPrincipal subject, ResourceValidationResult resourceResult, ValidatedRequest request, Ct ct) + public virtual async Task> GetAccessTokenClaimsAsync(ClaimsPrincipal subject, ResourceValidationResult resourceResult, ValidatedRequest request, Ct ct) { using var activity = Tracing.ServiceActivitySource.StartActivity("DefaultClaimsService.GetAccessTokenClaims"); diff --git a/identity-server/src/IdentityServer/Services/Default/DefaultIdentityServerInteractionService.cs b/identity-server/src/IdentityServer/Services/Default/DefaultIdentityServerInteractionService.cs index 31bca16ea..d9c9ebd6b 100644 --- a/identity-server/src/IdentityServer/Services/Default/DefaultIdentityServerInteractionService.cs +++ b/identity-server/src/IdentityServer/Services/Default/DefaultIdentityServerInteractionService.cs @@ -83,7 +83,7 @@ internal class DefaultIdentityServerInteractionService : IIdentityServerInteract { var clientIds = await _userSession.GetClientListAsync(ct); var samlSessions = await _userSession.GetSamlSessionListAsync(ct); - if (clientIds.Any() || samlSessions.Any()) + if (clientIds.Count > 0 || samlSessions.Count > 0) { var sid = await _userSession.GetSessionIdAsync(ct); var msg = new Message(new LogoutMessage @@ -178,7 +178,7 @@ internal class DefaultIdentityServerInteractionService : IIdentityServerInteract } /// - public async Task> GetAllUserGrantsAsync(Ct ct) + public async Task> GetAllUserGrantsAsync(Ct ct) { using var activity = Tracing.ServiceActivitySource.StartActivity("DefaultIdentityServerInteractionService.GetAllUserGrants"); @@ -189,7 +189,7 @@ internal class DefaultIdentityServerInteractionService : IIdentityServerInteract return await _grants.GetAllGrantsAsync(subject, ct); } - return Enumerable.Empty(); + return Array.Empty(); } /// diff --git a/identity-server/src/IdentityServer/Services/Default/DefaultKeyMaterialService.cs b/identity-server/src/IdentityServer/Services/Default/DefaultKeyMaterialService.cs index fd09251fa..f0d6377bc 100644 --- a/identity-server/src/IdentityServer/Services/Default/DefaultKeyMaterialService.cs +++ b/identity-server/src/IdentityServer/Services/Default/DefaultKeyMaterialService.cs @@ -74,7 +74,7 @@ public class DefaultKeyMaterialService : IKeyMaterialService } /// - public async Task> GetAllSigningCredentialsAsync(Ct ct) + public async Task> GetAllSigningCredentialsAsync(Ct ct) { using var activity = Tracing.ServiceActivitySource.StartActivity("DefaultKeyMaterialService.GetAllSigningCredentials"); @@ -99,14 +99,14 @@ public class DefaultKeyMaterialService : IKeyMaterialService } /// - public async Task> GetValidationKeysAsync(Ct ct) + public async Task> GetValidationKeysAsync(Ct ct) { using var activity = Tracing.ServiceActivitySource.StartActivity("DefaultKeyMaterialService.GetValidationKeys"); var keys = new List(); var automaticSigningKeys = await _keyManagerKeyStore.GetValidationKeysAsync(ct); - if (automaticSigningKeys?.Any() == true) + if (automaticSigningKeys?.Count > 0) { keys.AddRange(automaticSigningKeys); } diff --git a/identity-server/src/IdentityServer/Services/Default/DefaultPersistedGrantService.cs b/identity-server/src/IdentityServer/Services/Default/DefaultPersistedGrantService.cs index 8e8e203f9..ca75de6f8 100644 --- a/identity-server/src/IdentityServer/Services/Default/DefaultPersistedGrantService.cs +++ b/identity-server/src/IdentityServer/Services/Default/DefaultPersistedGrantService.cs @@ -34,7 +34,7 @@ public class DefaultPersistedGrantService : IPersistedGrantService } /// - public async Task> GetAllGrantsAsync(string subjectId, Ct ct) + public async Task> GetAllGrantsAsync(string subjectId, Ct ct) { using var activity = Tracing.ServiceActivitySource.StartActivity("DefaultPersistedGrantService.GetAllGrants"); @@ -128,7 +128,7 @@ public class DefaultPersistedGrantService : IPersistedGrantService _logger.LogError(ex, "Failed processing results from grant store."); } - return Enumerable.Empty(); + return Array.Empty(); } private static List Join(IEnumerable first, IEnumerable second) diff --git a/identity-server/src/IdentityServer/Services/Default/DefaultSessionManagementService.cs b/identity-server/src/IdentityServer/Services/Default/DefaultSessionManagementService.cs index d7ac96fe7..b6622103d 100644 --- a/identity-server/src/IdentityServer/Services/Default/DefaultSessionManagementService.cs +++ b/identity-server/src/IdentityServer/Services/Default/DefaultSessionManagementService.cs @@ -100,7 +100,7 @@ public class DefaultSessionManagementService : ISessionManagementService SubjectId = session.SubjectId, SessionId = session.SessionId, Issuer = session.Issuer, - ClientIds = session.ClientIds.Where(x => context.ClientIds == null || context.ClientIds.Contains(x)), + ClientIds = session.ClientIds.Where(x => context.ClientIds == null || context.ClientIds.Contains(x)).ToArray(), LogoutReason = LogoutNotificationReason.Terminated }, ct); } diff --git a/identity-server/src/IdentityServer/Services/Default/DefaultUserSession.cs b/identity-server/src/IdentityServer/Services/Default/DefaultUserSession.cs index 34e577641..cd88dbcb9 100644 --- a/identity-server/src/IdentityServer/Services/Default/DefaultUserSession.cs +++ b/identity-server/src/IdentityServer/Services/Default/DefaultUserSession.cs @@ -327,7 +327,7 @@ public class DefaultUserSession : IUserSession /// /// The cancellation token. /// - public virtual async Task> GetClientListAsync(Ct ct) + public virtual async Task> GetClientListAsync(Ct ct) { await AuthenticateAsync(); @@ -335,7 +335,7 @@ public class DefaultUserSession : IUserSession { try { - return Properties.GetClientList(); + return Properties.GetClientList().ToArray(); } catch (Exception ex) { @@ -346,7 +346,7 @@ public class DefaultUserSession : IUserSession } } - return Enumerable.Empty(); + return Array.Empty(); } // client list helpers @@ -377,7 +377,7 @@ public class DefaultUserSession : IUserSession } /// - public virtual async Task> GetSamlSessionListAsync(Ct ct) + public virtual async Task> GetSamlSessionListAsync(Ct ct) { await AuthenticateAsync(); @@ -385,7 +385,7 @@ public class DefaultUserSession : IUserSession { try { - return Properties.GetSamlSessionList(); + return Properties.GetSamlSessionList().ToArray(); } catch (Exception ex) { diff --git a/identity-server/src/IdentityServer/Services/Default/KeyManagement/AutomaticKeyManagerKeyStore.cs b/identity-server/src/IdentityServer/Services/Default/KeyManagement/AutomaticKeyManagerKeyStore.cs index 5115e65aa..ccd28c5e7 100644 --- a/identity-server/src/IdentityServer/Services/Default/KeyManagement/AutomaticKeyManagerKeyStore.cs +++ b/identity-server/src/IdentityServer/Services/Default/KeyManagement/AutomaticKeyManagerKeyStore.cs @@ -19,7 +19,7 @@ public interface IAutomaticKeyManagerKeyStore : IValidationKeysStore, ISigningCr /// /// The cancellation token. /// - Task> GetAllSigningCredentialsAsync(Ct ct); + Task> GetAllSigningCredentialsAsync(Ct ct); } /// @@ -31,10 +31,10 @@ internal class NopAutomaticKeyManagerKeyStore : IAutomaticKeyManagerKeyStore public Task GetSigningCredentialsAsync(Ct _) => Task.FromResult(null); /// - public Task> GetAllSigningCredentialsAsync(Ct _) => Task.FromResult(Enumerable.Empty()); + public Task> GetAllSigningCredentialsAsync(Ct _) => Task.FromResult>(Array.Empty()); /// - public Task> GetValidationKeysAsync(Ct _) => Task.FromResult(Enumerable.Empty()); + public Task> GetValidationKeysAsync(Ct _) => Task.FromResult>(Array.Empty()); } /// @@ -71,24 +71,24 @@ public class AutomaticKeyManagerKeyStore : IAutomaticKeyManagerKeyStore } /// - public async Task> GetAllSigningCredentialsAsync(Ct ct) + public async Task> GetAllSigningCredentialsAsync(Ct ct) { if (!_options.Enabled) { - return Enumerable.Empty(); + return Array.Empty(); } var keyContainers = await _keyManager.GetCurrentKeysAsync(ct); var credentials = keyContainers.Select(x => new SigningCredentials(x.ToSecurityKey(), x.Algorithm)); - return credentials; + return credentials.ToArray(); } /// - public async Task> GetValidationKeysAsync(Ct ct) + public async Task> GetValidationKeysAsync(Ct ct) { if (!_options.Enabled) { - return Enumerable.Empty(); + return Array.Empty(); } var containers = await _keyManager.GetAllKeysAsync(ct); diff --git a/identity-server/src/IdentityServer/Services/Default/KeyManagement/FileSystemKeyStore.cs b/identity-server/src/IdentityServer/Services/Default/KeyManagement/FileSystemKeyStore.cs index 506fad503..8929929c2 100644 --- a/identity-server/src/IdentityServer/Services/Default/KeyManagement/FileSystemKeyStore.cs +++ b/identity-server/src/IdentityServer/Services/Default/KeyManagement/FileSystemKeyStore.cs @@ -46,7 +46,7 @@ public class FileSystemKeyStore : ISigningKeyStore /// /// The cancellation token. /// - public async Task> LoadKeysAsync(Ct ct) + public async Task> LoadKeysAsync(Ct ct) { var list = new List(); diff --git a/identity-server/src/IdentityServer/Services/Default/KeyManagement/IKeyManager.cs b/identity-server/src/IdentityServer/Services/Default/KeyManagement/IKeyManager.cs index 787da7dd2..dd95493b3 100644 --- a/identity-server/src/IdentityServer/Services/Default/KeyManagement/IKeyManager.cs +++ b/identity-server/src/IdentityServer/Services/Default/KeyManagement/IKeyManager.cs @@ -14,12 +14,12 @@ public interface IKeyManager /// /// The cancellation token. /// - Task> GetCurrentKeysAsync(Ct ct); + Task> GetCurrentKeysAsync(Ct ct); /// /// Returns all the validation keys. /// /// The cancellation token. /// - Task> GetAllKeysAsync(Ct ct); + Task> GetAllKeysAsync(Ct ct); } diff --git a/identity-server/src/IdentityServer/Services/Default/KeyManagement/IKeyStoreCache.cs b/identity-server/src/IdentityServer/Services/Default/KeyManagement/IKeyStoreCache.cs index 60b561c1b..ffb29a573 100644 --- a/identity-server/src/IdentityServer/Services/Default/KeyManagement/IKeyStoreCache.cs +++ b/identity-server/src/IdentityServer/Services/Default/KeyManagement/IKeyStoreCache.cs @@ -1,6 +1,7 @@ // Copyright (c) Duende Software. All rights reserved. // See LICENSE in the project root for license information. +#nullable enable namespace Duende.IdentityServer.Services.KeyManagement; @@ -14,7 +15,7 @@ public interface ISigningKeyStoreCache /// /// The cancellation token. /// - Task> GetKeysAsync(Ct ct); + Task?> GetKeysAsync(Ct ct); /// /// Caches keys for duration. @@ -23,5 +24,5 @@ public interface ISigningKeyStoreCache /// /// The cancellation token. /// - Task StoreKeysAsync(IEnumerable keys, TimeSpan duration, Ct ct); + Task StoreKeysAsync(IReadOnlyCollection keys, TimeSpan duration, Ct ct); } diff --git a/identity-server/src/IdentityServer/Services/Default/KeyManagement/InMemoryKeyStoreCache.cs b/identity-server/src/IdentityServer/Services/Default/KeyManagement/InMemoryKeyStoreCache.cs index 42c24f9e7..86693fc32 100644 --- a/identity-server/src/IdentityServer/Services/Default/KeyManagement/InMemoryKeyStoreCache.cs +++ b/identity-server/src/IdentityServer/Services/Default/KeyManagement/InMemoryKeyStoreCache.cs @@ -1,6 +1,7 @@ // Copyright (c) Duende Software. All rights reserved. // See LICENSE in the project root for license information. +#nullable enable namespace Duende.IdentityServer.Services.KeyManagement; @@ -14,7 +15,7 @@ internal class InMemoryKeyStoreCache : ISigningKeyStoreCache private object _lock = new object(); private DateTime _expires = DateTime.MinValue; - private IEnumerable _cache; + private IReadOnlyCollection? _cache; /// /// Constructor for InMemoryKeyStoreCache. @@ -26,10 +27,10 @@ internal class InMemoryKeyStoreCache : ISigningKeyStoreCache /// Returns cached keys. /// /// - public Task> GetKeysAsync(Ct ct) + public Task?> GetKeysAsync(Ct ct) { DateTime expires; - IEnumerable keys; + IReadOnlyCollection? keys; lock (_lock) { @@ -39,10 +40,10 @@ internal class InMemoryKeyStoreCache : ISigningKeyStoreCache if (keys != null && expires >= _timeProvider.GetUtcNow().UtcDateTime) { - return Task.FromResult(keys); + return Task.FromResult?>(keys); } - return Task.FromResult>(null); + return Task.FromResult?>(null); } /// @@ -52,7 +53,7 @@ internal class InMemoryKeyStoreCache : ISigningKeyStoreCache /// /// The cancellation token. /// - public Task StoreKeysAsync(IEnumerable keys, TimeSpan duration, Ct ct) + public Task StoreKeysAsync(IReadOnlyCollection keys, TimeSpan duration, Ct ct) { lock (_lock) { diff --git a/identity-server/src/IdentityServer/Services/Default/KeyManagement/KeyManager.cs b/identity-server/src/IdentityServer/Services/Default/KeyManagement/KeyManager.cs index 60e40efdd..1c4c74684 100644 --- a/identity-server/src/IdentityServer/Services/Default/KeyManagement/KeyManager.cs +++ b/identity-server/src/IdentityServer/Services/Default/KeyManagement/KeyManager.cs @@ -60,7 +60,7 @@ public class KeyManager : IKeyManager } /// - public async Task> GetCurrentKeysAsync(Ct ct) + public async Task> GetCurrentKeysAsync(Ct ct) { using var activity = Tracing.ServiceActivitySource.StartActivity("KeyManager.GetCurrentKeys"); @@ -83,7 +83,7 @@ public class KeyManager : IKeyManager } /// - public async Task> GetAllKeysAsync(Ct ct) + public async Task> GetAllKeysAsync(Ct ct) { using var activity = Tracing.ServiceActivitySource.StartActivity("KeyManager.GetAllKeys"); @@ -95,18 +95,18 @@ public class KeyManager : IKeyManager - internal async Task<(IEnumerable allKeys, IEnumerable signingKeys)> GetAllKeysInternalAsync(Ct ct) + internal async Task<(IReadOnlyCollection allKeys, IReadOnlyCollection signingKeys)> GetAllKeysInternalAsync(Ct ct) { var cached = true; var keys = await GetAllKeysFromCacheAsync(ct); - if (!keys.Any()) + if (keys.Count == 0) { cached = false; keys = await GetAllKeysFromStoreAsync(ct); } // ensure we have all of our active signing keys - IEnumerable signingKeys; + IReadOnlyCollection signingKeys; var signingKeysSuccess = TryGetAllCurrentSigningKeys(keys, out signingKeys); // if we loaded from cache, see if DB has updated key @@ -196,7 +196,7 @@ public class KeyManager : IKeyManager } } - if (!signingKeys.Any()) + if (signingKeys.Count == 0) { _logger.LogError("Failed to create and then load new keys."); throw new Exception("Failed to create and then load new keys."); @@ -205,9 +205,9 @@ public class KeyManager : IKeyManager return (keys, signingKeys); } - internal bool IsKeyRotationRequired(IEnumerable allKeys) + internal bool IsKeyRotationRequired(IReadOnlyCollection allKeys) { - if (allKeys == null || !allKeys.Any()) + if (allKeys == null || allKeys.Count == 0) { return true; } @@ -307,7 +307,7 @@ public class KeyManager : IKeyManager return container; } - internal async Task> GetAllKeysFromCacheAsync(Ct ct) + internal async Task> GetAllKeysFromCacheAsync(Ct ct) { var cachedKeys = await _cache.GetKeysAsync(ct); if (cachedKeys != null) @@ -317,10 +317,10 @@ public class KeyManager : IKeyManager } _logger.LogTrace("Cache miss when loading all keys."); - return Enumerable.Empty(); + return Array.Empty(); } - internal bool AreAllKeysWithinInitializationDuration(IEnumerable keys) + internal bool AreAllKeysWithinInitializationDuration(IReadOnlyCollection keys) { if (_options.KeyManagement.InitializationDuration == TimeSpan.Zero) { @@ -340,7 +340,7 @@ public class KeyManager : IKeyManager return result; } - internal async Task> FilterAndDeleteRetiredKeysAsync(IEnumerable keys, Ct ct) + internal async Task> FilterAndDeleteRetiredKeysAsync(IReadOnlyCollection keys, Ct ct) { var retired = keys .Where(x => @@ -373,9 +373,9 @@ public class KeyManager : IKeyManager return result; } - internal async Task DeleteKeysAsync(IEnumerable keys, Ct ct) + internal async Task DeleteKeysAsync(IReadOnlyCollection keys, Ct ct) { - if (keys == null || !keys.Any()) + if (keys == null || keys.Count == 0) { return; } @@ -386,7 +386,7 @@ public class KeyManager : IKeyManager } } - internal IEnumerable FilterExpiredKeys(IEnumerable keys) + internal IReadOnlyCollection FilterExpiredKeys(IReadOnlyCollection keys) { var result = keys .Where(x => @@ -394,14 +394,15 @@ public class KeyManager : IKeyManager var age = _timeProvider.GetAge(x.Created); var isExpired = _options.KeyManagement.IsExpired(age); return !isExpired; - }); + }) + .ToArray(); return result; } - internal async Task CacheKeysAsync(IEnumerable keys, Ct ct) + internal async Task CacheKeysAsync(IReadOnlyCollection keys, Ct ct) { - if (keys?.Any() == true) + if (keys?.Count > 0) { var duration = _options.KeyManagement.KeyCacheDuration; @@ -428,17 +429,17 @@ public class KeyManager : IKeyManager } } - internal async Task> GetAllKeysFromStoreAsync(Ct ct, bool cache = true) + internal async Task> GetAllKeysFromStoreAsync(Ct ct, bool cache = true) { _logger.LogTrace("Loading keys from store."); var protectedKeys = await _store.LoadKeysAsync(ct); - if (protectedKeys != null && protectedKeys.Any()) + if (protectedKeys != null && protectedKeys.Count > 0) { // retired keys are those that are beyond inclusion, thus we act as if they don't exist. - protectedKeys = await FilterAndDeleteRetiredKeysAsync(protectedKeys, ct); + var filteredKeys = await FilterAndDeleteRetiredKeysAsync(protectedKeys, ct); - var keys = protectedKeys.Select(x => + var keys = filteredKeys.Select(x => { try { @@ -460,55 +461,54 @@ public class KeyManager : IKeyManager return null; }) .Where(x => x != null) - .ToArray() - .AsEnumerable(); + .ToArray(); - if (_logger.IsEnabled(LogLevel.Trace) && keys.Any()) + if (_logger.IsEnabled(LogLevel.Trace) && keys.Length > 0) { var ids = keys.Select(x => x.Id).ToArray(); _logger.LogTrace("Loaded keys from store: {kids}", ids.Aggregate((x, y) => $"{x},{y}")); } - if (_logger.IsEnabled(LogLevel.Trace) && keys.Any()) + if (_logger.IsEnabled(LogLevel.Trace) && keys.Length > 0) { var ids = keys.Select(x => x.Id).ToArray(); _logger.LogTrace("Remaining keys after filter: {kids}", ids.Aggregate((x, y) => $"{x},{y}")); } // only use keys that are allowed - keys = keys.Where(x => _options.KeyManagement.AllowedSigningAlgorithmNames.Contains(x.Algorithm)).ToArray(); - if (_logger.IsEnabled(LogLevel.Trace) && keys.Any()) + var allowedKeys = keys.Where(x => _options.KeyManagement.AllowedSigningAlgorithmNames.Contains(x.Algorithm)).ToArray(); + if (_logger.IsEnabled(LogLevel.Trace) && allowedKeys.Length > 0) { - var ids = keys.Select(x => x.Id).ToArray(); + var ids = allowedKeys.Select(x => x.Id).ToArray(); _logger.LogTrace("Keys with allowed alg from store: {kids}", ids.Aggregate((x, y) => $"{x},{y}")); } - if (keys.Any()) + if (allowedKeys.Length > 0) { _logger.LogTrace("Keys successfully returned from store."); if (cache) { - await CacheKeysAsync(keys, ct); + await CacheKeysAsync(allowedKeys, ct); } - return keys; + return allowedKeys; } } _logger.LogTrace("No keys returned from store."); - return Enumerable.Empty(); + return Array.Empty(); } - internal async Task<(IEnumerable allKeys, IEnumerable activeKeys)> CreateNewKeysAndAddToCacheAsync(Ct ct) + internal async Task<(IReadOnlyCollection allKeys, IReadOnlyCollection activeKeys)> CreateNewKeysAndAddToCacheAsync(Ct ct) { var keys = new List(); - keys.AddRange(await _cache.GetKeysAsync(ct) ?? Enumerable.Empty()); + keys.AddRange(await _cache.GetKeysAsync(ct) ?? Array.Empty()); foreach (var alg in _options.KeyManagement.SigningAlgorithms) { @@ -546,21 +546,21 @@ public class KeyManager : IKeyManager return (keys, activeKeys); } - internal bool TryGetAllCurrentSigningKeys(IEnumerable keys, out IEnumerable signingKeys) + internal bool TryGetAllCurrentSigningKeys(IReadOnlyCollection keys, out IReadOnlyCollection signingKeys) { signingKeys = GetAllCurrentSigningKeys(keys); - var success = signingKeys.Count() == _options.KeyManagement.AllowedSigningAlgorithmNames.Count() && + var success = signingKeys.Count == _options.KeyManagement.AllowedSigningAlgorithmNames.Count() && signingKeys.All(x => _options.KeyManagement.AllowedSigningAlgorithmNames.Contains(x.Algorithm)); return success; } - internal IEnumerable GetAllCurrentSigningKeys(IEnumerable allKeys) + internal IReadOnlyCollection GetAllCurrentSigningKeys(IReadOnlyCollection allKeys) { - if (allKeys == null || !allKeys.Any()) + if (allKeys == null || allKeys.Count == 0) { - return Enumerable.Empty(); + return Array.Empty(); } _logger.LogTrace("Looking for active signing keys."); diff --git a/identity-server/src/IdentityServer/Services/Default/KeyManagement/NopKeyStoreCache.cs b/identity-server/src/IdentityServer/Services/Default/KeyManagement/NopKeyStoreCache.cs index f75a7eac8..86d89061e 100644 --- a/identity-server/src/IdentityServer/Services/Default/KeyManagement/NopKeyStoreCache.cs +++ b/identity-server/src/IdentityServer/Services/Default/KeyManagement/NopKeyStoreCache.cs @@ -1,6 +1,7 @@ // Copyright (c) Duende Software. All rights reserved. // See LICENSE in the project root for license information. +#nullable enable namespace Duende.IdentityServer.Services.KeyManagement; @@ -13,8 +14,8 @@ internal class NopKeyStoreCache : ISigningKeyStoreCache /// Returns null. /// /// - public Task> GetKeysAsync(Ct _) => Task.FromResult>(null); + public Task?> GetKeysAsync(Ct _) => Task.FromResult?>(null); /// - public Task StoreKeysAsync(IEnumerable keys, TimeSpan duration, Ct _) => Task.CompletedTask; + public Task StoreKeysAsync(IReadOnlyCollection keys, TimeSpan duration, Ct _) => Task.CompletedTask; } diff --git a/identity-server/src/IdentityServer/Services/Default/LogoutNotificationService.cs b/identity-server/src/IdentityServer/Services/Default/LogoutNotificationService.cs index 7523fd34c..d86bf6574 100644 --- a/identity-server/src/IdentityServer/Services/Default/LogoutNotificationService.cs +++ b/identity-server/src/IdentityServer/Services/Default/LogoutNotificationService.cs @@ -35,7 +35,7 @@ public class LogoutNotificationService : ILogoutNotificationService } /// - public async Task> GetFrontChannelLogoutNotificationsUrlsAsync(LogoutNotificationContext context, Ct ct) + public async Task> GetFrontChannelLogoutNotificationsUrlsAsync(LogoutNotificationContext context, Ct ct) { using var activity = Tracing.ServiceActivitySource.StartActivity("LogoutNotificationService.GetFrontChannelLogoutNotificationsUrls"); @@ -82,7 +82,7 @@ public class LogoutNotificationService : ILogoutNotificationService } /// - public async Task> GetBackChannelLogoutNotificationsAsync(LogoutNotificationContext context, Ct ct) + public async Task> GetBackChannelLogoutNotificationsAsync(LogoutNotificationContext context, Ct ct) { using var activity = Tracing.ServiceActivitySource.StartActivity("LogoutNotificationService.GetBackChannelLogoutNotifications"); diff --git a/identity-server/src/IdentityServer/Services/IBackchannelAuthenticationInteractionService.cs b/identity-server/src/IdentityServer/Services/IBackchannelAuthenticationInteractionService.cs index b895454f0..2aced96d0 100644 --- a/identity-server/src/IdentityServer/Services/IBackchannelAuthenticationInteractionService.cs +++ b/identity-server/src/IdentityServer/Services/IBackchannelAuthenticationInteractionService.cs @@ -17,7 +17,7 @@ public interface IBackchannelAuthenticationInteractionService /// /// Returns the pending login requests for the current user. /// - Task> GetPendingLoginRequestsForCurrentUserAsync(Ct ct); + Task> GetPendingLoginRequestsForCurrentUserAsync(Ct ct); /// /// Returns the login request for the id. diff --git a/identity-server/src/IdentityServer/Services/IClaimsService.cs b/identity-server/src/IdentityServer/Services/IClaimsService.cs index 8741aa0dc..973f151ce 100644 --- a/identity-server/src/IdentityServer/Services/IClaimsService.cs +++ b/identity-server/src/IdentityServer/Services/IClaimsService.cs @@ -25,7 +25,7 @@ public interface IClaimsService /// /// Claims for the identity token /// - Task> GetIdentityTokenClaimsAsync(ClaimsPrincipal subject, ResourceValidationResult resources, bool includeAllIdentityClaims, ValidatedRequest request, Ct ct); + Task> GetIdentityTokenClaimsAsync(ClaimsPrincipal subject, ResourceValidationResult resources, bool includeAllIdentityClaims, ValidatedRequest request, Ct ct); /// /// Returns claims for an access token. @@ -37,5 +37,5 @@ public interface IClaimsService /// /// Claims for the access token /// - Task> GetAccessTokenClaimsAsync(ClaimsPrincipal subject, ResourceValidationResult resources, ValidatedRequest request, Ct ct); + Task> GetAccessTokenClaimsAsync(ClaimsPrincipal subject, ResourceValidationResult resources, ValidatedRequest request, Ct ct); } diff --git a/identity-server/src/IdentityServer/Services/IIdentityServerInteractionService.cs b/identity-server/src/IdentityServer/Services/IIdentityServerInteractionService.cs index 2b34a3b7d..3bf1e2797 100644 --- a/identity-server/src/IdentityServer/Services/IIdentityServerInteractionService.cs +++ b/identity-server/src/IdentityServer/Services/IIdentityServerInteractionService.cs @@ -70,7 +70,7 @@ public interface IIdentityServerInteractionService /// Returns a collection representing all of the user's consents and grants. /// /// The cancellation token. - Task> GetAllUserGrantsAsync(Ct ct); + Task> GetAllUserGrantsAsync(Ct ct); /// /// Revokes all a user's consents and grants for a given client, or for all clients if clientId is null. diff --git a/identity-server/src/IdentityServer/Services/IKeyMaterialService.cs b/identity-server/src/IdentityServer/Services/IKeyMaterialService.cs index 57be8ff07..d6f4c4c27 100644 --- a/identity-server/src/IdentityServer/Services/IKeyMaterialService.cs +++ b/identity-server/src/IdentityServer/Services/IKeyMaterialService.cs @@ -19,7 +19,7 @@ public interface IKeyMaterialService /// /// The cancellation token. /// - Task> GetValidationKeysAsync(Ct ct); + Task> GetValidationKeysAsync(Ct ct); /// /// Gets the signing credentials. @@ -35,5 +35,5 @@ public interface IKeyMaterialService /// /// The cancellation token. /// - Task> GetAllSigningCredentialsAsync(Ct ct); + Task> GetAllSigningCredentialsAsync(Ct ct); } diff --git a/identity-server/src/IdentityServer/Services/ILogoutNotificationService.cs b/identity-server/src/IdentityServer/Services/ILogoutNotificationService.cs index 568756274..f6a12acd5 100644 --- a/identity-server/src/IdentityServer/Services/ILogoutNotificationService.cs +++ b/identity-server/src/IdentityServer/Services/ILogoutNotificationService.cs @@ -18,14 +18,14 @@ public interface ILogoutNotificationService /// /// The context for the logout notification. /// The cancellation token. - Task> GetFrontChannelLogoutNotificationsUrlsAsync(LogoutNotificationContext context, Ct ct); + Task> GetFrontChannelLogoutNotificationsUrlsAsync(LogoutNotificationContext context, Ct ct); /// /// Builds the http back-channel logout request data for the collection of clients. /// /// The context for the logout notification. /// The cancellation token. - Task> GetBackChannelLogoutNotificationsAsync(LogoutNotificationContext context, Ct ct); + Task> GetBackChannelLogoutNotificationsAsync(LogoutNotificationContext context, Ct ct); } /// diff --git a/identity-server/src/IdentityServer/Services/IPersistedGrantService.cs b/identity-server/src/IdentityServer/Services/IPersistedGrantService.cs index cf423617e..9e944d023 100644 --- a/identity-server/src/IdentityServer/Services/IPersistedGrantService.cs +++ b/identity-server/src/IdentityServer/Services/IPersistedGrantService.cs @@ -19,7 +19,7 @@ public interface IPersistedGrantService /// The subject identifier. /// The cancellation token. /// - Task> GetAllGrantsAsync(string subjectId, Ct ct); + Task> GetAllGrantsAsync(string subjectId, Ct ct); /// /// Removes all grants for a given subject id, and optionally client id and session id combination. diff --git a/identity-server/src/IdentityServer/Services/ISessionManagementService.cs b/identity-server/src/IdentityServer/Services/ISessionManagementService.cs index 20fb8bc51..577a8cc48 100644 --- a/identity-server/src/IdentityServer/Services/ISessionManagementService.cs +++ b/identity-server/src/IdentityServer/Services/ISessionManagementService.cs @@ -48,7 +48,7 @@ public class RemoveSessionsContext /// The client ids for which to trigger logout notification, or revoke tokens or consent. /// If not set, then all clients will be removed. /// - public IEnumerable? ClientIds { get; set; } + public IReadOnlyCollection? ClientIds { get; set; } /// /// Removes the server side session for the user's session. diff --git a/identity-server/src/IdentityServer/Services/IUserSession.cs b/identity-server/src/IdentityServer/Services/IUserSession.cs index c785dc836..d4bb8a2de 100644 --- a/identity-server/src/IdentityServer/Services/IUserSession.cs +++ b/identity-server/src/IdentityServer/Services/IUserSession.cs @@ -62,7 +62,7 @@ public interface IUserSession /// /// The cancellation token. /// - Task> GetClientListAsync(Ct ct); + Task> GetClientListAsync(Ct ct); /// /// Adds a SAML SP session to the user's session. @@ -80,7 +80,7 @@ public interface IUserSession /// Gets the list of SAML SP sessions for the user's session. /// /// The cancellation token. - Task> GetSamlSessionListAsync(Ct ct); + Task> GetSamlSessionListAsync(Ct ct); /// /// Removes a SAML SP session by EntityId. diff --git a/identity-server/src/IdentityServer/Stores/Caching/CachingResourceStore.cs b/identity-server/src/IdentityServer/Stores/Caching/CachingResourceStore.cs index 2eee090c6..08c6a624f 100644 --- a/identity-server/src/IdentityServer/Stores/Caching/CachingResourceStore.cs +++ b/identity-server/src/IdentityServer/Stores/Caching/CachingResourceStore.cs @@ -95,7 +95,7 @@ public class CachingResourceStore : IResourceStore } /// - public async Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames, Ct ct) + public async Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames, Ct ct) { using var activity = Tracing.StoreActivitySource.StartActivity("CachingResourceStore.FindApiResourcesByScopeName"); activity?.SetTag(Tracing.Properties.ScopeNames, scopeNames.ToSpaceSeparatedString()); @@ -166,7 +166,7 @@ public class CachingResourceStore : IResourceStore /// - public async Task> FindApiResourcesByNameAsync(IEnumerable apiResourceNames, Ct ct) + public async Task> FindApiResourcesByNameAsync(IEnumerable apiResourceNames, Ct ct) { using var activity = Tracing.StoreActivitySource.StartActivity("CachingResourceStore.FindApiResourcesByName"); activity?.SetTag(Tracing.Properties.ApiResourceNames, apiResourceNames.ToSpaceSeparatedString()); @@ -177,7 +177,7 @@ public class CachingResourceStore : IResourceStore } /// - public async Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames, Ct ct) + public async Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames, Ct ct) { using var activity = Tracing.StoreActivitySource.StartActivity("CachingResourceStore.FindIdentityResourcesByScopeName"); activity?.SetTag(Tracing.Properties.ScopeNames, scopeNames.ToSpaceSeparatedString()); @@ -188,7 +188,7 @@ public class CachingResourceStore : IResourceStore } /// - public async Task> FindApiScopesByNameAsync(IEnumerable scopeNames, Ct ct) + public async Task> FindApiScopesByNameAsync(IEnumerable scopeNames, Ct ct) { using var activity = Tracing.StoreActivitySource.StartActivity("CachingResourceStore.FindApiScopesByName"); activity?.SetTag(Tracing.Properties.ScopeNames, scopeNames.ToSpaceSeparatedString()); @@ -199,7 +199,7 @@ public class CachingResourceStore : IResourceStore } - private async Task> FindItemsAsync( + private async Task> FindItemsAsync( IEnumerable names, ICache cache, Func, Ct, Task> getResourcesFunc, diff --git a/identity-server/src/IdentityServer/Stores/Caching/CachingSamlServiceProviderStore.cs b/identity-server/src/IdentityServer/Stores/Caching/CachingSamlServiceProviderStore.cs deleted file mode 100644 index 00be416c5..000000000 --- a/identity-server/src/IdentityServer/Stores/Caching/CachingSamlServiceProviderStore.cs +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -#nullable enable -using Duende.IdentityServer.Configuration; -using Duende.IdentityServer.Models; -using Duende.IdentityServer.Services; - -namespace Duende.IdentityServer.Stores; - -/// -/// Cache decorator for ISamlServiceProviderStore -/// -/// -public class CachingSamlServiceProviderStore : ISamlServiceProviderStore - where T : ISamlServiceProviderStore -{ - private readonly IdentityServerOptions _options; - private readonly ICache _cache; - private readonly ISamlServiceProviderStore _inner; - - /// - /// Initializes a new instance of the class. - /// - /// The options. - /// The inner. - /// The cache. - public CachingSamlServiceProviderStore(IdentityServerOptions options, T inner, ICache cache) - { - _options = options; - _inner = inner; - _cache = cache; - } - - /// - public async Task FindByEntityIdAsync(string entityId, Ct ct) - { - using var activity = Tracing.StoreActivitySource.StartActivity( - "CachingSamlServiceProviderStore.FindByEntityId"); - activity?.SetTag(Tracing.Properties.SamlEntityId, entityId); - - var sp = await _cache.GetOrAddAsync(entityId, - _options.Caching.SamlServiceProviderStoreExpiration, -#pragma warning disable CS8603 // Possible null reference return. Returning a null is ok here based on the method signature, but ICache has not been updated for nullables - async () => await _inner.FindByEntityIdAsync(entityId, ct), -#pragma warning restore CS8603 // Possible null reference return. - ct); - return sp; - } - -#if NET10_0_OR_GREATER - /// - public IAsyncEnumerable GetAllSamlServiceProvidersAsync(Ct ct) - { - using var activity = Tracing.StoreActivitySource.StartActivity( - "CachingSamlServiceProviderStore.GetAllSamlServiceProviders"); - return _inner.GetAllSamlServiceProvidersAsync(ct); - } -#endif -} diff --git a/identity-server/src/IdentityServer/Stores/Default/DefaultBackChannelAuthenticationRequestStore.cs b/identity-server/src/IdentityServer/Stores/Default/DefaultBackChannelAuthenticationRequestStore.cs index e28e55dbc..f978a1c50 100644 --- a/identity-server/src/IdentityServer/Stores/Default/DefaultBackChannelAuthenticationRequestStore.cs +++ b/identity-server/src/IdentityServer/Stores/Default/DefaultBackChannelAuthenticationRequestStore.cs @@ -67,11 +67,11 @@ public class DefaultBackChannelAuthenticationRequestStore : DefaultGrantStore - public Task> GetLoginsForUserAsync(string subjectId, Ct ct, string clientId = null) + public async Task> GetLoginsForUserAsync(string subjectId, Ct ct, string clientId = null) { using var activity = Tracing.StoreActivitySource.StartActivity("DefaultBackChannelAuthenticationRequestStore.GetLoginsForUser"); - return GetAllAsync(new PersistedGrantFilter + return await GetAllAsync(new PersistedGrantFilter { SubjectId = subjectId, ClientId = clientId, diff --git a/identity-server/src/IdentityServer/Stores/Default/DefaultGrantStore.cs b/identity-server/src/IdentityServer/Stores/Default/DefaultGrantStore.cs index 390252a79..a006d0ac7 100644 --- a/identity-server/src/IdentityServer/Stores/Default/DefaultGrantStore.cs +++ b/identity-server/src/IdentityServer/Stores/Default/DefaultGrantStore.cs @@ -149,7 +149,7 @@ public class DefaultGrantStore /// /// The filter. /// The cancellation token. - protected virtual async Task> GetAllAsync(PersistedGrantFilter filter, Ct ct) + protected virtual async Task> GetAllAsync(PersistedGrantFilter filter, Ct ct) { filter.Type = GrantType; var items = await Store.GetAllAsync(filter, ct); diff --git a/identity-server/src/IdentityServer/Stores/Empty/EmptyResourceStore.cs b/identity-server/src/IdentityServer/Stores/Empty/EmptyResourceStore.cs index 9cb6d820c..cb50fdea6 100644 --- a/identity-server/src/IdentityServer/Stores/Empty/EmptyResourceStore.cs +++ b/identity-server/src/IdentityServer/Stores/Empty/EmptyResourceStore.cs @@ -8,13 +8,13 @@ namespace Duende.IdentityServer.Stores.Empty; internal class EmptyResourceStore : IResourceStore { - public Task> FindApiResourcesByNameAsync(IEnumerable apiResourceNames, Ct _) => Task.FromResult(Enumerable.Empty()); + public Task> FindApiResourcesByNameAsync(IEnumerable apiResourceNames, Ct _) => Task.FromResult>(Array.Empty()); - public Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames, Ct _) => Task.FromResult(Enumerable.Empty()); + public Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames, Ct _) => Task.FromResult>(Array.Empty()); - public Task> FindApiScopesByNameAsync(IEnumerable scopeNames, Ct _) => Task.FromResult(Enumerable.Empty()); + public Task> FindApiScopesByNameAsync(IEnumerable scopeNames, Ct _) => Task.FromResult>(Array.Empty()); - public Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames, Ct _) => Task.FromResult(Enumerable.Empty()); + public Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames, Ct _) => Task.FromResult>(Array.Empty()); public Task GetAllResourcesAsync(Ct _) => Task.FromResult(new Resources() { OfflineAccess = true }); } diff --git a/identity-server/src/IdentityServer/Stores/IValidationKeysStore.cs b/identity-server/src/IdentityServer/Stores/IValidationKeysStore.cs index 5e591823d..0d31e81ac 100644 --- a/identity-server/src/IdentityServer/Stores/IValidationKeysStore.cs +++ b/identity-server/src/IdentityServer/Stores/IValidationKeysStore.cs @@ -16,5 +16,5 @@ public interface IValidationKeysStore /// /// The cancellation token. /// - Task> GetValidationKeysAsync(Ct ct); + Task> GetValidationKeysAsync(Ct ct); } diff --git a/identity-server/src/IdentityServer/Stores/InMemory/InMemoryPersistedGrantStore.cs b/identity-server/src/IdentityServer/Stores/InMemory/InMemoryPersistedGrantStore.cs index 21b92349f..de6975786 100644 --- a/identity-server/src/IdentityServer/Stores/InMemory/InMemoryPersistedGrantStore.cs +++ b/identity-server/src/IdentityServer/Stores/InMemory/InMemoryPersistedGrantStore.cs @@ -39,7 +39,7 @@ public class InMemoryPersistedGrantStore : IPersistedGrantStore } /// - public Task> GetAllAsync(PersistedGrantFilter filter, Ct ct) + public Task> GetAllAsync(PersistedGrantFilter filter, Ct ct) { using var activity = Tracing.StoreActivitySource.StartActivity("InMemoryPersistedGrantStoreResponseGenerator.GetAll"); @@ -47,7 +47,7 @@ public class InMemoryPersistedGrantStore : IPersistedGrantStore var items = Filter(filter); - return Task.FromResult(items); + return Task.FromResult>(items); } /// @@ -77,7 +77,7 @@ public class InMemoryPersistedGrantStore : IPersistedGrantStore return Task.CompletedTask; } - private IEnumerable Filter(PersistedGrantFilter filter) + private PersistedGrant[] Filter(PersistedGrantFilter filter) { var query = from item in _repository @@ -120,7 +120,7 @@ public class InMemoryPersistedGrantStore : IPersistedGrantStore query = query.Where(x => x.Type == filter.Type); } - var items = query.ToArray().AsEnumerable(); + var items = query.ToArray(); return items; } } diff --git a/identity-server/src/IdentityServer/Stores/InMemory/InMemoryResourcesStore.cs b/identity-server/src/IdentityServer/Stores/InMemory/InMemoryResourcesStore.cs index c85e1df27..f4e08e933 100644 --- a/identity-server/src/IdentityServer/Stores/InMemory/InMemoryResourcesStore.cs +++ b/identity-server/src/IdentityServer/Stores/InMemory/InMemoryResourcesStore.cs @@ -54,7 +54,7 @@ public class InMemoryResourcesStore : IResourceStore } /// - public Task> FindApiResourcesByNameAsync(IEnumerable apiResourceNames, Ct ct) + public Task> FindApiResourcesByNameAsync(IEnumerable apiResourceNames, Ct ct) { ArgumentNullException.ThrowIfNull(apiResourceNames); using var activity = Tracing.StoreActivitySource.StartActivity("InMemoryResourceStore.FindApiResourcesByName"); @@ -63,11 +63,11 @@ public class InMemoryResourcesStore : IResourceStore var query = from a in _apiResources where apiResourceNames.Contains(a.Name) select a; - return Task.FromResult(query); + return Task.FromResult>(query.ToArray()); } /// - public Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames, Ct ct) + public Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames, Ct ct) { ArgumentNullException.ThrowIfNull(scopeNames); using var activity = Tracing.StoreActivitySource.StartActivity("InMemoryResourceStore.FindIdentityResourcesByScopeName"); @@ -77,11 +77,11 @@ public class InMemoryResourcesStore : IResourceStore where scopeNames.Contains(i.Name) select i; - return Task.FromResult(identity); + return Task.FromResult>(identity.ToArray()); } /// - public Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames, Ct ct) + public Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames, Ct ct) { ArgumentNullException.ThrowIfNull(scopeNames); using var activity = Tracing.StoreActivitySource.StartActivity("InMemoryResourceStore.FindApiResourcesByScopeName"); @@ -91,11 +91,11 @@ public class InMemoryResourcesStore : IResourceStore where a.Scopes.Any(x => scopeNames.Contains(x)) select a; - return Task.FromResult(query); + return Task.FromResult>(query.ToArray()); } /// - public Task> FindApiScopesByNameAsync(IEnumerable scopeNames, Ct ct) + public Task> FindApiScopesByNameAsync(IEnumerable scopeNames, Ct ct) { ArgumentNullException.ThrowIfNull(scopeNames); using var activity = Tracing.StoreActivitySource.StartActivity("InMemoryResourceStore.FindApiScopesByName"); @@ -106,6 +106,6 @@ public class InMemoryResourcesStore : IResourceStore where scopeNames.Contains(x.Name) select x; - return Task.FromResult(query); + return Task.FromResult>(query.ToArray()); } } diff --git a/identity-server/src/IdentityServer/Stores/InMemory/InMemorySamlServiceProviderStore.cs b/identity-server/src/IdentityServer/Stores/InMemory/InMemorySamlServiceProviderStore.cs index b4647c714..d5ce470e3 100644 --- a/identity-server/src/IdentityServer/Stores/InMemory/InMemorySamlServiceProviderStore.cs +++ b/identity-server/src/IdentityServer/Stores/InMemory/InMemorySamlServiceProviderStore.cs @@ -1,8 +1,6 @@ // Copyright (c) Duende Software. All rights reserved. // See LICENSE in the project root for license information. -#nullable enable -using System.Runtime.CompilerServices; using Duende.IdentityServer.Extensions; using Duende.IdentityServer.Models; @@ -32,9 +30,9 @@ public class InMemorySamlServiceProviderStore : ISamlServiceProviderStore /// Finds a SAML Service Provider by its entity identifier. /// /// The entity identifier of the Service Provider. - /// The cancellation token. + /// The cancellation token. /// The Service Provider, or null if not found. - public Task FindByEntityIdAsync(string entityId, Ct _) + public Task FindByEntityIdAsync(string entityId, Ct ct) { using var activity = Tracing.StoreActivitySource.StartActivity("InMemorySamlServiceProviderStore.FindByEntityId"); activity?.SetTag(Tracing.Properties.SamlEntityId, entityId); @@ -46,14 +44,4 @@ public class InMemorySamlServiceProviderStore : ISamlServiceProviderStore return Task.FromResult(query.SingleOrDefault()); } - - /// - public async IAsyncEnumerable GetAllSamlServiceProvidersAsync([EnumeratorCancellation] Ct _) - { - using var activity = Tracing.StoreActivitySource.StartActivity("InMemorySamlServiceProviderStore.GetAllSamlServiceProviders"); - foreach (var sp in _serviceProviders) - { - yield return sp; - } - } } diff --git a/identity-server/src/IdentityServer/Stores/InMemory/InMemoryValidationKeysStore.cs b/identity-server/src/IdentityServer/Stores/InMemory/InMemoryValidationKeysStore.cs index e015a60cf..114e6cbc9 100644 --- a/identity-server/src/IdentityServer/Stores/InMemory/InMemoryValidationKeysStore.cs +++ b/identity-server/src/IdentityServer/Stores/InMemory/InMemoryValidationKeysStore.cs @@ -12,20 +12,20 @@ namespace Duende.IdentityServer.Stores; /// public class InMemoryValidationKeysStore : IValidationKeysStore { - private readonly IEnumerable _keys; + private readonly IReadOnlyCollection _keys; /// /// Initializes a new instance of the class. /// /// The keys. /// keys - public InMemoryValidationKeysStore(IEnumerable keys) => _keys = keys ?? throw new ArgumentNullException(nameof(keys)); + public InMemoryValidationKeysStore(IEnumerable keys) => _keys = (keys ?? throw new ArgumentNullException(nameof(keys))).ToArray(); /// /// Gets all validation keys. /// /// - public Task> GetValidationKeysAsync(Ct ct) + public Task> GetValidationKeysAsync(Ct ct) { using var activity = Tracing.StoreActivitySource.StartActivity("InMemoryValidationKeysStore.GetValidationKeys"); diff --git a/identity-server/src/IdentityServer/Stores/ValidatingSamlServiceProviderStore.cs b/identity-server/src/IdentityServer/Stores/ValidatingSamlServiceProviderStore.cs deleted file mode 100644 index bf3a6560e..000000000 --- a/identity-server/src/IdentityServer/Stores/ValidatingSamlServiceProviderStore.cs +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -#nullable enable -using System.Runtime.CompilerServices; -using Duende.IdentityServer.Events; -using Duende.IdentityServer.Models; -using Duende.IdentityServer.Services; -using Duende.IdentityServer.Validation; -using Microsoft.Extensions.Logging; - -namespace Duende.IdentityServer.Stores; - -/// -/// SAML service provider store decorator for runtime configuration validation. -/// -public class ValidatingSamlServiceProviderStore : ISamlServiceProviderStore - where T : ISamlServiceProviderStore -{ - private readonly ISamlServiceProviderStore _inner; - private readonly ISamlServiceProviderConfigurationValidator _validator; - private readonly IEventService _events; - private readonly ILogger> _logger; - private readonly string _validatorType; - - /// - /// Initializes a new instance of the class. - /// - public ValidatingSamlServiceProviderStore( - T inner, - ISamlServiceProviderConfigurationValidator validator, - IEventService events, - ILogger> logger) - { - _inner = inner; - _validator = validator; - _events = events; - _logger = logger; - _validatorType = validator.GetType().FullName!; - } - - /// - public async Task FindByEntityIdAsync(string entityId, Ct ct) - { - using var activity = Tracing.StoreActivitySource.StartActivity( - "ValidatingSamlServiceProviderStore.FindByEntityId"); - - var sp = await _inner.FindByEntityIdAsync(entityId, ct); - - if (sp != null) - { - _logger.LogTrace("Calling into SAML SP configuration validator: {validatorType}", _validatorType); - var context = new SamlServiceProviderConfigurationValidationContext(sp); - await _validator.ValidateAsync(context); - - if (context.IsValid) - { - _logger.LogDebug("SAML SP configuration validation for {entityId} succeeded.", sp.EntityId); - Telemetry.Metrics.SamlServiceProviderValidation(entityId); - return sp; - } - - _logger.LogError("Invalid SAML SP configuration for {entityId}: {errorMessage}", - sp.EntityId, context.ErrorMessage); - Telemetry.Metrics.SamlServiceProviderValidationFailure(entityId, context.ErrorMessage); - await _events.RaiseAsync( - new InvalidSamlServiceProviderConfigurationEvent(sp, context.ErrorMessage), ct); - return null; - } - - Telemetry.Metrics.SamlServiceProviderValidationFailure(entityId, "Service provider not found"); - return null; - } - - /// - public async IAsyncEnumerable GetAllSamlServiceProvidersAsync([EnumeratorCancellation] Ct ct) - { - using var activity = Tracing.StoreActivitySource.StartActivity( - "ValidatingSamlServiceProviderStore.GetAllSamlServiceProviders"); - await foreach (var sp in _inner.GetAllSamlServiceProvidersAsync(ct)) - { - _logger.LogTrace("Calling into SAML SP configuration validator: {validatorType}", _validatorType); - var context = new SamlServiceProviderConfigurationValidationContext(sp); - await _validator.ValidateAsync(context); - if (context.IsValid) - { - _logger.LogDebug("SAML SP configuration validation for {entityId} succeeded.", sp.EntityId); - Telemetry.Metrics.SamlServiceProviderValidation(sp.EntityId); - yield return sp; - } - else - { - _logger.LogError("Invalid SAML SP configuration for {entityId}: {errorMessage}", - sp.EntityId, context.ErrorMessage); - Telemetry.Metrics.SamlServiceProviderValidationFailure(sp.EntityId, context.ErrorMessage); - await _events.RaiseAsync( - new InvalidSamlServiceProviderConfigurationEvent(sp, context.ErrorMessage), ct); - } - } - } -} diff --git a/identity-server/src/IdentityServer/Validation/Contexts/SamlServiceProviderConfigurationValidationContext.cs b/identity-server/src/IdentityServer/Validation/Contexts/SamlServiceProviderConfigurationValidationContext.cs deleted file mode 100644 index 588f77e4f..000000000 --- a/identity-server/src/IdentityServer/Validation/Contexts/SamlServiceProviderConfigurationValidationContext.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -#nullable enable - -using Duende.IdentityServer.Models; - -namespace Duende.IdentityServer.Validation; - -/// -/// Context for SAML service provider configuration validation. -/// -public class SamlServiceProviderConfigurationValidationContext -{ - public SamlServiceProvider ServiceProvider { get; } - public bool IsValid { get; set; } = true; - public string? ErrorMessage { get; set; } - - public SamlServiceProviderConfigurationValidationContext(SamlServiceProvider serviceProvider) - => ServiceProvider = serviceProvider; - - public void SetError(string message) - { - IsValid = false; - ErrorMessage = message; - } -} diff --git a/identity-server/src/IdentityServer/Validation/Default/ApiSecretValidator.cs b/identity-server/src/IdentityServer/Validation/Default/ApiSecretValidator.cs index 14ac2c949..a151c4297 100644 --- a/identity-server/src/IdentityServer/Validation/Default/ApiSecretValidator.cs +++ b/identity-server/src/IdentityServer/Validation/Default/ApiSecretValidator.cs @@ -67,7 +67,7 @@ public class ApiSecretValidator : IApiSecretValidator // load API resource var apis = await _resources.FindApiResourcesByNameAsync(new[] { parsedSecret.Id }, ct); - if (apis == null || !apis.Any()) + if (apis == null || apis.Count == 0) { await RaiseFailureEventAsync(parsedSecret.Id, "Unknown API resource", ct); @@ -75,7 +75,7 @@ public class ApiSecretValidator : IApiSecretValidator return fail; } - if (apis.Count() > 1) + if (apis.Count > 1) { await RaiseFailureEventAsync(parsedSecret.Id, "Invalid API resource", ct); diff --git a/identity-server/src/IdentityServer/Validation/Default/DefaultSamlServiceProviderConfigurationValidator.cs b/identity-server/src/IdentityServer/Validation/Default/DefaultSamlServiceProviderConfigurationValidator.cs deleted file mode 100644 index f6bba7a7b..000000000 --- a/identity-server/src/IdentityServer/Validation/Default/DefaultSamlServiceProviderConfigurationValidator.cs +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -namespace Duende.IdentityServer.Validation; - -/// -/// Default SAML service provider configuration validator. -/// -public class DefaultSamlServiceProviderConfigurationValidator : ISamlServiceProviderConfigurationValidator -{ - public async Task ValidateAsync(SamlServiceProviderConfigurationValidationContext context) - { - using var activity = Tracing.ValidationActivitySource.StartActivity( - "DefaultSamlServiceProviderConfigurationValidator.Validate"); - - await ValidateEntityIdAsync(context); - if (!context.IsValid) - { - return; - } - - await ValidateUriSchemesAsync(context); - if (!context.IsValid) - { - return; - } - - await ValidateEncryptionAsync(context); - } - - protected virtual Task ValidateEntityIdAsync(SamlServiceProviderConfigurationValidationContext context) - { - if (string.IsNullOrWhiteSpace(context.ServiceProvider.EntityId)) - { - context.SetError("EntityId is required."); - } - return Task.CompletedTask; - } - - protected virtual Task ValidateUriSchemesAsync(SamlServiceProviderConfigurationValidationContext context) - { - var sp = context.ServiceProvider; - - if (sp.AssertionConsumerServiceUrls != null) - { - foreach (var url in sp.AssertionConsumerServiceUrls) - { - if (!url.IsAbsoluteUri) - { - context.SetError($"Assertion Consumer Service URL '{url}' is not an absolute URI."); - return Task.CompletedTask; - } - - if (!string.Equals(url.Scheme, "https", StringComparison.OrdinalIgnoreCase)) - { - context.SetError($"Assertion Consumer Service URL '{url}' does not use HTTPS scheme."); - return Task.CompletedTask; - } - } - } - - if (sp.SingleLogoutServiceUrl?.Location != null) - { - if (!sp.SingleLogoutServiceUrl.Location.IsAbsoluteUri) - { - context.SetError($"Single Logout Service URL '{sp.SingleLogoutServiceUrl.Location}' is not an absolute URI."); - return Task.CompletedTask; - } - - if (!string.Equals(sp.SingleLogoutServiceUrl.Location.Scheme, "https", StringComparison.OrdinalIgnoreCase)) - { - context.SetError($"Single Logout Service URL '{sp.SingleLogoutServiceUrl.Location}' does not use HTTPS scheme."); - return Task.CompletedTask; - } - } - return Task.CompletedTask; - } - - protected virtual Task ValidateEncryptionAsync(SamlServiceProviderConfigurationValidationContext context) - { - if (context.ServiceProvider.EncryptAssertions && - (context.ServiceProvider.EncryptionCertificates == null || - context.ServiceProvider.EncryptionCertificates.Count == 0)) - { - context.SetError("Encryption certificates are required when EncryptAssertions is true."); - } - return Task.CompletedTask; - } -} diff --git a/identity-server/src/IdentityServer/Validation/Default/EndSessionRequestValidator.cs b/identity-server/src/IdentityServer/Validation/Default/EndSessionRequestValidator.cs index f00febfe0..80c968a8b 100644 --- a/identity-server/src/IdentityServer/Validation/Default/EndSessionRequestValidator.cs +++ b/identity-server/src/IdentityServer/Validation/Default/EndSessionRequestValidator.cs @@ -246,7 +246,7 @@ public class EndSessionRequestValidator : IEndSessionRequestValidator var endSessionId = parameters[Constants.UIConstants.DefaultRoutePathParams.EndSessionCallback]; var endSessionMessage = await EndSessionMessageStore.ReadAsync(endSessionId, ct); - if (endSessionMessage?.Data?.ClientIds?.Any() == true || endSessionMessage?.Data?.SamlSessions?.Any() == true) + if (endSessionMessage?.Data?.ClientIds?.Count > 0 || endSessionMessage?.Data?.SamlSessions?.Count > 0) { result.IsError = false; result.FrontChannelLogoutUrls = await LogoutNotificationService.GetFrontChannelLogoutNotificationsUrlsAsync(endSessionMessage.Data, ct); diff --git a/identity-server/src/IdentityServer/Validation/Default/NopSamlServiceProviderConfigurationValidator.cs b/identity-server/src/IdentityServer/Validation/Default/NopSamlServiceProviderConfigurationValidator.cs deleted file mode 100644 index aa3a3efff..000000000 --- a/identity-server/src/IdentityServer/Validation/Default/NopSamlServiceProviderConfigurationValidator.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -namespace Duende.IdentityServer.Validation; - -/// -/// No-op SAML service provider configuration validator. -/// -public class NopSamlServiceProviderConfigurationValidator : ISamlServiceProviderConfigurationValidator -{ - public Task ValidateAsync(SamlServiceProviderConfigurationValidationContext context) - { - context.IsValid = true; - return Task.CompletedTask; - } -} diff --git a/identity-server/src/IdentityServer/Validation/Default/PrivateKeyJwtSecretValidator.cs b/identity-server/src/IdentityServer/Validation/Default/PrivateKeyJwtSecretValidator.cs index cb43cdfe2..282de1f85 100644 --- a/identity-server/src/IdentityServer/Validation/Default/PrivateKeyJwtSecretValidator.cs +++ b/identity-server/src/IdentityServer/Validation/Default/PrivateKeyJwtSecretValidator.cs @@ -130,8 +130,9 @@ public class PrivateKeyJwtSecretValidator : ISecretValidator if (enforceStrictAud) { - // New strict audience validation requires that the audience be the issuer identifier, disallows multiple - // audiences in an array, and even disallows wrapping even a single audience in an array + // Strict audience validation requires that the audience be the issuer identifier as the sole audience + // value, per draft-ietf-oauth-rfc7523bis. A single-element array is permitted, but multi-element arrays + // are rejected. tokenValidationParameters.AudienceValidator = (audiences, token, parameters) => { // There isn't a particularly nice way to distinguish between a claim that is a single string wrapped in @@ -139,8 +140,12 @@ public class PrivateKeyJwtSecretValidator : ISecretValidator // collection both convert that into a string valued claim. However, GetPayloadValue does not do // any type inferencing, so we can call that, and then check if the result is actually a string var audValue = ((JsonWebToken)token).GetPayloadValue("aud"); - return audValue is string audString && - AudiencesMatch(audString, issuer); + return audValue switch + { + string audString => AudiencesMatch(audString, issuer), + List { Count: 1 } audList => AudiencesMatch(audList[0], issuer), + _ => false + }; }; // Strict audience validation requires that the token type be "client-authentication+jwt" diff --git a/identity-server/src/IdentityServer/Validation/ISamlServiceProviderConfigurationValidator.cs b/identity-server/src/IdentityServer/Validation/ISamlServiceProviderConfigurationValidator.cs deleted file mode 100644 index 568b1d826..000000000 --- a/identity-server/src/IdentityServer/Validation/ISamlServiceProviderConfigurationValidator.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -#nullable enable - -namespace Duende.IdentityServer.Validation; - -/// -/// Validator for SAML service provider configuration. -/// -public interface ISamlServiceProviderConfigurationValidator -{ - Task ValidateAsync(SamlServiceProviderConfigurationValidationContext context); -} diff --git a/identity-server/src/IdentityServer/Validation/Models/ValidatedEndSessionRequest.cs b/identity-server/src/IdentityServer/Validation/Models/ValidatedEndSessionRequest.cs index 9bfa8521a..3eb5d21e2 100644 --- a/identity-server/src/IdentityServer/Validation/Models/ValidatedEndSessionRequest.cs +++ b/identity-server/src/IdentityServer/Validation/Models/ValidatedEndSessionRequest.cs @@ -46,11 +46,11 @@ public class ValidatedEndSessionRequest : ValidatedRequest /// /// Ids of clients known to have an authentication session for user at end session time /// - public IEnumerable ClientIds { get; set; } + public IReadOnlyCollection ClientIds { get; set; } /// /// SAML Service Provider sessions for the user at end session time. /// Contains full session data including EntityIds, NameIds, and SessionIndexes required for logout notifications. /// - public IEnumerable SamlSessions { get; set; } = []; + public IReadOnlyCollection SamlSessions { get; set; } = []; } diff --git a/identity-server/src/Shared/Telemetry/Telemetry.cs b/identity-server/src/Shared/Telemetry/Telemetry.cs index 227d034c7..b28500383 100644 --- a/identity-server/src/Shared/Telemetry/Telemetry.cs +++ b/identity-server/src/Shared/Telemetry/Telemetry.cs @@ -45,7 +45,6 @@ public static class Telemetry public const string ResourceOwnerAuthentication = "tokenservice.resourceowner_authentication"; public const string Revocation = "tokenservice.revocation"; public const string TokenIssued = "tokenservice.token_issued"; - public const string SamlServiceProviderConfigValidation = "tokenservice.saml_sp.config_validation"; } /// @@ -72,7 +71,6 @@ public static class Telemetry public const string RefreshTokenIssued = "refresh_token_issued"; public const string ProofType = "proof_type"; public const string IdTokenIssued = "id_token_issued"; - public const string SamlEntityId = "saml_entity_id"; } /// @@ -246,33 +244,6 @@ public static class Telemetry ClientValidationCounter.Add(1, new(Tags.Client, clientId), new(Tags.Error, error)); } - /// - /// SAML Service Provider configuration validation - /// - public static readonly Counter SamlServiceProviderValidationCounter = - Meter.CreateCounter(Counters.SamlServiceProviderConfigValidation); - - /// - /// Helper method to increase - /// - /// SAML Service Provider Entity ID - public static void SamlServiceProviderValidation(string entityId) - { - Success(entityId); - SamlServiceProviderValidationCounter.Add(1, tag: new(Tags.SamlEntityId, entityId)); - } - - /// - /// Helper method to increase on errors - /// - /// SAML Service Provider Entity ID - /// Error - public static void SamlServiceProviderValidationFailure(string entityId, string error) - { - Failure(error, entityId); - SamlServiceProviderValidationCounter.Add(1, new(Tags.SamlEntityId, entityId), new(Tags.Error, error)); - } - /// /// Successful Client Secret validations /// diff --git a/identity-server/src/Storage/Stores/IBackChannelAuthenticationRequestStore.cs b/identity-server/src/Storage/Stores/IBackChannelAuthenticationRequestStore.cs index 1805939cc..d84a52488 100644 --- a/identity-server/src/Storage/Stores/IBackChannelAuthenticationRequestStore.cs +++ b/identity-server/src/Storage/Stores/IBackChannelAuthenticationRequestStore.cs @@ -26,7 +26,7 @@ public interface IBackChannelAuthenticationRequestStore /// The subject identifier. /// The cancellation token. /// The client identifier. - Task> GetLoginsForUserAsync(string subjectId, Ct ct, string? clientId = null); + Task> GetLoginsForUserAsync(string subjectId, Ct ct, string? clientId = null); /// /// Gets the request. diff --git a/identity-server/src/Storage/Stores/IIdentityProviderStore.cs b/identity-server/src/Storage/Stores/IIdentityProviderStore.cs index 5fedbf8bd..06a79d2c2 100644 --- a/identity-server/src/Storage/Stores/IIdentityProviderStore.cs +++ b/identity-server/src/Storage/Stores/IIdentityProviderStore.cs @@ -17,7 +17,7 @@ public interface IIdentityProviderStore /// Gets all identity providers name. /// /// The cancellation token. - Task> GetAllSchemeNamesAsync(Ct ct); + Task> GetAllSchemeNamesAsync(Ct ct); /// /// Gets the identity provider by scheme name. diff --git a/identity-server/src/Storage/Stores/IPersistedGrantStore.cs b/identity-server/src/Storage/Stores/IPersistedGrantStore.cs index b65f356a3..cbdf81da3 100644 --- a/identity-server/src/Storage/Stores/IPersistedGrantStore.cs +++ b/identity-server/src/Storage/Stores/IPersistedGrantStore.cs @@ -35,7 +35,7 @@ public interface IPersistedGrantStore /// The filter. /// The cancellation token. /// - Task> GetAllAsync(PersistedGrantFilter filter, Ct ct); + Task> GetAllAsync(PersistedGrantFilter filter, Ct ct); /// /// Removes the grant by key. diff --git a/identity-server/src/Storage/Stores/IResourceStore.cs b/identity-server/src/Storage/Stores/IResourceStore.cs index 7e0bee35a..551954ce5 100644 --- a/identity-server/src/Storage/Stores/IResourceStore.cs +++ b/identity-server/src/Storage/Stores/IResourceStore.cs @@ -18,28 +18,28 @@ public interface IResourceStore /// /// The scope names. /// The cancellation token. - Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames, Ct ct); + Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames, Ct ct); /// /// Gets API scopes by scope name. /// /// The scope names. /// The cancellation token. - Task> FindApiScopesByNameAsync(IEnumerable scopeNames, Ct ct); + Task> FindApiScopesByNameAsync(IEnumerable scopeNames, Ct ct); /// /// Gets API resources by scope name. /// /// The scope names. /// The cancellation token. - Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames, Ct ct); + Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames, Ct ct); /// /// Gets API resources by API resource name. /// /// The API resource names. /// The cancellation token. - Task> FindApiResourcesByNameAsync(IEnumerable apiResourceNames, Ct ct); + Task> FindApiResourcesByNameAsync(IEnumerable apiResourceNames, Ct ct); /// /// Gets all resources. diff --git a/identity-server/src/Storage/Stores/ISamlServiceProviderStore.cs b/identity-server/src/Storage/Stores/ISamlServiceProviderStore.cs index 8ab106d6a..5e6735297 100644 --- a/identity-server/src/Storage/Stores/ISamlServiceProviderStore.cs +++ b/identity-server/src/Storage/Stores/ISamlServiceProviderStore.cs @@ -19,9 +19,4 @@ public interface ISamlServiceProviderStore /// The cancellation token. /// The Service Provider, or null if not found. Task FindByEntityIdAsync(string entityId, Ct ct); - - /// - /// Returns all SAML service providers for enumeration purposes. - /// - IAsyncEnumerable GetAllSamlServiceProvidersAsync(Ct ct); } diff --git a/identity-server/src/Storage/Stores/ISigningKeyStore.cs b/identity-server/src/Storage/Stores/ISigningKeyStore.cs index f20a669f8..22360818d 100644 --- a/identity-server/src/Storage/Stores/ISigningKeyStore.cs +++ b/identity-server/src/Storage/Stores/ISigningKeyStore.cs @@ -18,7 +18,7 @@ public interface ISigningKeyStore /// /// The cancellation token. /// - Task> LoadKeysAsync(Ct ct); + Task> LoadKeysAsync(Ct ct); /// /// Persists new key in storage. diff --git a/identity-server/src/Storage/Stores/PersistedGrantFilter.cs b/identity-server/src/Storage/Stores/PersistedGrantFilter.cs index fc2f4a2c9..2b91d2d83 100644 --- a/identity-server/src/Storage/Stores/PersistedGrantFilter.cs +++ b/identity-server/src/Storage/Stores/PersistedGrantFilter.cs @@ -31,7 +31,7 @@ public class PersistedGrantFilter /// /// Client ids the grant was issued to. /// - public IEnumerable? ClientIds { get; set; } + public IReadOnlyCollection? ClientIds { get; set; } /// /// The type of grant. @@ -41,5 +41,5 @@ public class PersistedGrantFilter /// /// The types of grants. /// - public IEnumerable? Types { get; set; } + public IReadOnlyCollection? Types { get; set; } } diff --git a/identity-server/templates/src/Directory.Build.props b/identity-server/templates/src/Directory.Build.props index 6a623a56d..5890f30dd 100644 --- a/identity-server/templates/src/Directory.Build.props +++ b/identity-server/templates/src/Directory.Build.props @@ -1,7 +1,10 @@ + false true + false + None diff --git a/identity-server/templates/src/IdentityServer/Extensions/HostingExtensions.cs b/identity-server/templates/src/IdentityServer/Extensions/HostingExtensions.cs index efadfef14..0d09d0485 100644 --- a/identity-server/templates/src/IdentityServer/Extensions/HostingExtensions.cs +++ b/identity-server/templates/src/IdentityServer/Extensions/HostingExtensions.cs @@ -19,23 +19,23 @@ internal static class HostingExtensions { // Write most logs to the console but diagnostic data to a file. // See https://docs.duendesoftware.com/identityserver/diagnostics/data - builder.Services.AddSerilog(lc => + _ = builder.Services.AddSerilog(lc => { - lc.WriteTo.Logger(consoleLogger => + _ = lc.WriteTo.Logger(consoleLogger => { - consoleLogger.WriteTo.Console( + _ = consoleLogger.WriteTo.Console( outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", formatProvider: CultureInfo.InvariantCulture); if (builder.Environment.IsDevelopment()) { - consoleLogger.Filter.ByExcluding(Matching.FromSource("Duende.IdentityServer.Diagnostics.Summary")); + _ = consoleLogger.Filter.ByExcluding(Matching.FromSource("Duende.IdentityServer.Diagnostics.Summary")); } }); if (builder.Environment.IsDevelopment()) { - lc.WriteTo.Logger(fileLogger => + _ = lc.WriteTo.Logger(fileLogger => { - fileLogger + _ = fileLogger .WriteTo.File("./diagnostics/diagnostic.log", rollingInterval: RollingInterval.Day, fileSizeLimitBytes: 1024 * 1024 * 10, // 10 MB rollOnFileSizeLimit: true, @@ -51,9 +51,9 @@ internal static class HostingExtensions public static WebApplication ConfigureServices(this WebApplicationBuilder builder) { - builder.Services.AddHttpContextAccessor(); + _ = builder.Services.AddHttpContextAccessor(); - builder.Services.AddRazorPages() + _ = builder.Services.AddRazorPages() .AddRazorRuntimeCompilation(); var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); @@ -99,7 +99,7 @@ internal static class HostingExtensions .AddLicenseSummary(); // Adds configuration to use Duende's Demo IdentityServer instance. - builder.Services.AddAuthentication() + _ = builder.Services.AddAuthentication() .AddOpenIdConnect("oidc", "Duende Demo", options => { options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; @@ -126,41 +126,41 @@ internal static class HostingExtensions // this adds the necessary config for the simple admin/config pages { - builder.Services.AddAuthorization(options => + _ = builder.Services.AddAuthorization(options => { options.AddPolicy(Config.Policies.Admin, policy => policy.RequireClaim("role", "admin")); }); - builder.Services.AddTransient(); - builder.Services.AddTransient(); - builder.Services.AddTransient(); + _ = builder.Services.AddTransient(); + _ = builder.Services.AddTransient(); + _ = builder.Services.AddTransient(); } // this adds the necessary config for the portal page - builder.Services.AddTransient(); + _ = builder.Services.AddTransient(); return builder.Build(); } public static WebApplication ConfigurePipeline(this WebApplication app) { - app.UseSerilogRequestLogging(); + _ = app.UseSerilogRequestLogging(); if (app.Environment.IsDevelopment()) { - app.UseDeveloperExceptionPage(); + _ = app.UseDeveloperExceptionPage(); } // Content Security Policy options - app.Use(async (context, next) => + _ = app.Use(async (context, next) => { context.Response.Headers.Append("Content-Security-Policy", "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-src 'none';"); await next(); }); - app.UseStaticFiles(new StaticFileOptions + _ = app.UseStaticFiles(new StaticFileOptions { OnPrepareResponse = ctx => { @@ -177,13 +177,13 @@ internal static class HostingExtensions } }); - app.UseRouting(); - app.UseIdentityServer(); + _ = app.UseRouting(); + _ = app.UseIdentityServer(); - app.UseAuthentication(); - app.UseAuthorization(); + _ = app.UseAuthentication(); + _ = app.UseAuthorization(); - app.MapRazorPages() + _ = app.MapRazorPages() .RequireAuthorization(); return app; diff --git a/identity-server/templates/src/IdentityServer/IdentityServerTemplate.csproj b/identity-server/templates/src/IdentityServer/IdentityServerTemplate.csproj index 81ea4483c..45e228c27 100644 --- a/identity-server/templates/src/IdentityServer/IdentityServerTemplate.csproj +++ b/identity-server/templates/src/IdentityServer/IdentityServerTemplate.csproj @@ -1,31 +1,25 @@ - - + net10.0 enable enable IdentityServerTemplate - - - - - + all runtime; build; native; contentfiles; analyzers; buildtransitive + - - diff --git a/identity-server/templates/src/IdentityServer/Migrations/.editorconfig b/identity-server/templates/src/IdentityServer/Migrations/.editorconfig new file mode 100644 index 000000000..98e806338 --- /dev/null +++ b/identity-server/templates/src/IdentityServer/Migrations/.editorconfig @@ -0,0 +1,2 @@ +[*.cs] +dotnet_diagnostic.IDE0058.severity = none diff --git a/identity-server/templates/src/IdentityServer/Pages/Admin/ApiScopes/ApiScopeRepository.cs b/identity-server/templates/src/IdentityServer/Pages/Admin/ApiScopes/ApiScopeRepository.cs index 41365af3b..43bb923e5 100644 --- a/identity-server/templates/src/IdentityServer/Pages/Admin/ApiScopes/ApiScopeRepository.cs +++ b/identity-server/templates/src/IdentityServer/Pages/Admin/ApiScopes/ApiScopeRepository.cs @@ -116,9 +116,9 @@ public class ApiScopeRepository(ConfigurationDbContext context) // CA1849 Suppressed because AddAsync is only needed for value generators that // need async database access (e.g., HiLoValueGenerator), and we don't use those // generators - _context.ApiScopes.Add(scope.ToEntity()); + _ = _context.ApiScopes.Add(scope.ToEntity()); #pragma warning restore CA1849 // Call async methods when in an async method - await _context.SaveChangesAsync(); + _ = await _context.SaveChangesAsync(); } public async Task UpdateAsync(ApiScopeModel model) @@ -143,7 +143,7 @@ public class ApiScopeRepository(ConfigurationDbContext context) if (claimsToRemove.Length != 0) { - scope.UserClaims.RemoveAll(x => claimsToRemove.Contains(x.Type)); + _ = scope.UserClaims.RemoveAll(x => claimsToRemove.Contains(x.Type)); } if (claimsToAdd.Length != 0) { @@ -153,7 +153,7 @@ public class ApiScopeRepository(ConfigurationDbContext context) })); } - await _context.SaveChangesAsync(); + _ = await _context.SaveChangesAsync(); } public async Task DeleteAsync(string id) @@ -161,8 +161,8 @@ public class ApiScopeRepository(ConfigurationDbContext context) var scope = await _context.ApiScopes.SingleOrDefaultAsync(x => x.Name == id) ?? throw new ArgumentException("Invalid Api Scope"); - _context.ApiScopes.Remove(scope); - await _context.SaveChangesAsync(); + _ = _context.ApiScopes.Remove(scope); + _ = await _context.SaveChangesAsync(); } } diff --git a/identity-server/templates/src/IdentityServer/Pages/Admin/Clients/ClientRepository.cs b/identity-server/templates/src/IdentityServer/Pages/Admin/Clients/ClientRepository.cs index 9281ee5e0..722e346f8 100644 --- a/identity-server/templates/src/IdentityServer/Pages/Admin/Clients/ClientRepository.cs +++ b/identity-server/templates/src/IdentityServer/Pages/Admin/Clients/ClientRepository.cs @@ -171,7 +171,7 @@ public class ClientRepository(ConfigurationDbContext context) client.ClientSecrets.Clear(); client.ClientSecrets.Add(new ClientSecret { Value = secret.Sha256(), Description = description }); - await context.SaveChangesAsync(); + _ = await context.SaveChangesAsync(); } public async Task ClearClientSecret(string clientId) @@ -183,7 +183,7 @@ public class ClientRepository(ConfigurationDbContext context) .SingleOrDefaultAsync(x => x.ClientId == clientId) ?? throw new ArgumentException("Invalid Client Id"); client.ClientSecrets.Clear(); - await context.SaveChangesAsync(); + _ = await context.SaveChangesAsync(); } public async Task CreateAsync(CreateClientModel model) @@ -233,8 +233,8 @@ public class ClientRepository(ConfigurationDbContext context) frontChannelLogoutPath: "signout-oidc" ); - context.Clients.Add(client.ToEntity()); - await context.SaveChangesAsync(); + _ = context.Clients.Add(client.ToEntity()); + _ = await context.SaveChangesAsync(); } public async Task UpdateAsync(EditClientModel model) @@ -266,7 +266,7 @@ public class ClientRepository(ConfigurationDbContext context) if (toRemove.Count != 0) { - client.AllowedScopes.RemoveAll(x => toRemove.Contains(x.Scope)); + _ = client.AllowedScopes.RemoveAll(x => toRemove.Contains(x.Scope)); } if (toAdd.Count != 0) @@ -313,7 +313,7 @@ public class ClientRepository(ConfigurationDbContext context) client.BackChannelLogoutUri = model.BackChannelLogoutUri?.Trim(); } - await context.SaveChangesAsync(); + _ = await context.SaveChangesAsync(); } public async Task DeleteAsync(string clientId) @@ -321,8 +321,8 @@ public class ClientRepository(ConfigurationDbContext context) var client = await context.Clients.SingleOrDefaultAsync(x => x.ClientId == clientId) ?? throw new ArgumentException("Invalid Client Id"); - context.Clients.Remove(client); - await context.SaveChangesAsync(); + _ = context.Clients.Remove(client); + _ = await context.SaveChangesAsync(); } } diff --git a/identity-server/templates/src/IdentityServer/Pages/Admin/IdentityScopes/IdentityScopeRepository.cs b/identity-server/templates/src/IdentityServer/Pages/Admin/IdentityScopes/IdentityScopeRepository.cs index 6cd14dd3a..00747ef42 100644 --- a/identity-server/templates/src/IdentityServer/Pages/Admin/IdentityScopes/IdentityScopeRepository.cs +++ b/identity-server/templates/src/IdentityServer/Pages/Admin/IdentityScopes/IdentityScopeRepository.cs @@ -117,9 +117,9 @@ public class IdentityScopeRepository(ConfigurationDbContext context) // CA1849 Suppressed because AddAsync is only needed for value generators that // need async database access (e.g., HiLoValueGenerator), and we don't use those // generators - _context.IdentityResources.Add(scope.ToEntity()); + _ = _context.IdentityResources.Add(scope.ToEntity()); #pragma warning restore CA1849 - await _context.SaveChangesAsync(); + _ = await _context.SaveChangesAsync(); } public async Task UpdateAsync(IdentityScopeModel model) @@ -144,7 +144,7 @@ public class IdentityScopeRepository(ConfigurationDbContext context) if (claimsToRemove.Length != 0) { - scope.UserClaims.RemoveAll(x => claimsToRemove.Contains(x.Type)); + _ = scope.UserClaims.RemoveAll(x => claimsToRemove.Contains(x.Type)); } if (claimsToAdd.Length != 0) { @@ -154,7 +154,7 @@ public class IdentityScopeRepository(ConfigurationDbContext context) })); } - await _context.SaveChangesAsync(); + _ = await _context.SaveChangesAsync(); } public async Task DeleteAsync(string id) @@ -162,8 +162,8 @@ public class IdentityScopeRepository(ConfigurationDbContext context) var scope = await _context.IdentityResources.SingleOrDefaultAsync(x => x.Name == id) ?? throw new ArgumentException("Invalid Identity Scope"); - _context.IdentityResources.Remove(scope); - await _context.SaveChangesAsync(); + _ = _context.IdentityResources.Remove(scope); + _ = await _context.SaveChangesAsync(); } } diff --git a/identity-server/templates/src/IdentityServer/Pages/Device/Index.cshtml.cs b/identity-server/templates/src/IdentityServer/Pages/Device/Index.cshtml.cs index e3a67ad99..78e05157f 100644 --- a/identity-server/templates/src/IdentityServer/Pages/Device/Index.cshtml.cs +++ b/identity-server/templates/src/IdentityServer/Pages/Device/Index.cshtml.cs @@ -115,7 +115,7 @@ public class Index : PageModel if (grantedConsent != null) { // communicate outcome of consent back to identityserver - await _interaction.HandleRequestAsync(Input.UserCode, grantedConsent); + _ = await _interaction.HandleRequestAsync(Input.UserCode, grantedConsent); // indicate that's it ok to redirect back to authorization endpoint return RedirectToPage("/Device/Success"); diff --git a/identity-server/templates/src/IdentityServer/Pages/ExternalLogin/Callback.cshtml.cs b/identity-server/templates/src/IdentityServer/Pages/ExternalLogin/Callback.cshtml.cs index 377074891..224932787 100644 --- a/identity-server/templates/src/IdentityServer/Pages/ExternalLogin/Callback.cshtml.cs +++ b/identity-server/templates/src/IdentityServer/Pages/ExternalLogin/Callback.cshtml.cs @@ -74,7 +74,7 @@ public class Callback : PageModel // // remove the user id and name identifier claims so we don't include it as an extra claim if/when we provision the user var claims = externalUser.Claims.ToList(); - claims.RemoveAll(c => c.Type is JwtClaimTypes.Subject or ClaimTypes.NameIdentifier); + _ = claims.RemoveAll(c => c.Type is JwtClaimTypes.Subject or ClaimTypes.NameIdentifier); user = _users.AutoProvisionUser(provider, providerUserId, claims.ToList()); } diff --git a/identity-server/templates/src/IdentityServer/Program.cs b/identity-server/templates/src/IdentityServer/Program.cs index d1376f9f9..a05bb16b4 100644 --- a/identity-server/templates/src/IdentityServer/Program.cs +++ b/identity-server/templates/src/IdentityServer/Program.cs @@ -28,7 +28,7 @@ try if (app.Environment.IsDevelopment()) { - app.Lifetime.ApplicationStopping.Register(() => + _ = app.Lifetime.ApplicationStopping.Register(() => { var usage = app.Services.GetRequiredService(); Console.Write(Summary(usage)); @@ -50,12 +50,12 @@ finally static string Summary(LicenseUsageSummary usage) { var sb = new StringBuilder(); - sb.AppendLine("IdentityServer Usage Summary:"); - sb.AppendLine(CultureInfo.InvariantCulture, $" License: {usage.LicenseEdition}"); + _ = sb.AppendLine("IdentityServer Usage Summary:"); + _ = sb.AppendLine(CultureInfo.InvariantCulture, $" License: {usage.LicenseEdition}"); var features = usage.FeaturesUsed.Count > 0 ? string.Join(", ", usage.FeaturesUsed) : "None"; - sb.AppendLine(CultureInfo.InvariantCulture, $" Business and Enterprise Edition Features Used: {features}"); - sb.AppendLine(CultureInfo.InvariantCulture, $" {usage.ClientsUsed.Count} Client Id(s) Used"); - sb.AppendLine(CultureInfo.InvariantCulture, $" {usage.IssuersUsed.Count} Issuer(s) Used"); + _ = sb.AppendLine(CultureInfo.InvariantCulture, $" Business and Enterprise Edition Features Used: {features}"); + _ = sb.AppendLine(CultureInfo.InvariantCulture, $" {usage.ClientsUsed.Count} Client Id(s) Used"); + _ = sb.AppendLine(CultureInfo.InvariantCulture, $" {usage.IssuersUsed.Count} Issuer(s) Used"); return sb.ToString(); } diff --git a/identity-server/templates/src/IdentityServer/SeedData.cs b/identity-server/templates/src/IdentityServer/SeedData.cs index 09494fa6f..844c3c999 100644 --- a/identity-server/templates/src/IdentityServer/SeedData.cs +++ b/identity-server/templates/src/IdentityServer/SeedData.cs @@ -26,9 +26,9 @@ public class SeedData Log.Debug("IdentityResources being populated"); foreach (var resource in Config.IdentityResources.ToList()) { - context.IdentityResources.Add(resource.ToEntity()); + _ = context.IdentityResources.Add(resource.ToEntity()); } - context.SaveChanges(); + _ = context.SaveChanges(); } else { diff --git a/identity-server/templates/src/IdentityServerAspNetIdentity/Data/Migrations/.editorconfig b/identity-server/templates/src/IdentityServerAspNetIdentity/Data/Migrations/.editorconfig new file mode 100644 index 000000000..98e806338 --- /dev/null +++ b/identity-server/templates/src/IdentityServerAspNetIdentity/Data/Migrations/.editorconfig @@ -0,0 +1,2 @@ +[*.cs] +dotnet_diagnostic.IDE0058.severity = none diff --git a/identity-server/templates/src/IdentityServerAspNetIdentity/HostingExtensions.cs b/identity-server/templates/src/IdentityServerAspNetIdentity/HostingExtensions.cs index d6d289e5e..beba36508 100644 --- a/identity-server/templates/src/IdentityServerAspNetIdentity/HostingExtensions.cs +++ b/identity-server/templates/src/IdentityServerAspNetIdentity/HostingExtensions.cs @@ -16,23 +16,23 @@ internal static class HostingExtensions { // Write most logs to the console but diagnostic data to a file. // See https://docs.duendesoftware.com/identityserver/diagnostics/data - builder.Services.AddSerilog(lc => + _ = builder.Services.AddSerilog(lc => { - lc.WriteTo.Logger(consoleLogger => + _ = lc.WriteTo.Logger(consoleLogger => { - consoleLogger.WriteTo.Console( + _ = consoleLogger.WriteTo.Console( outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", formatProvider: CultureInfo.InvariantCulture); if (builder.Environment.IsDevelopment()) { - consoleLogger.Filter.ByExcluding(Matching.FromSource("Duende.IdentityServer.Diagnostics.Summary")); + _ = consoleLogger.Filter.ByExcluding(Matching.FromSource("Duende.IdentityServer.Diagnostics.Summary")); } }); if (builder.Environment.IsDevelopment()) { - lc.WriteTo.Logger(fileLogger => + _ = lc.WriteTo.Logger(fileLogger => { - fileLogger + _ = fileLogger .WriteTo.File("./diagnostics/diagnostic.log", rollingInterval: RollingInterval.Day, fileSizeLimitBytes: 1024 * 1024 * 10, // 10 MB rollOnFileSizeLimit: true, @@ -48,16 +48,16 @@ internal static class HostingExtensions public static WebApplication ConfigureServices(this WebApplicationBuilder builder) { - builder.Services.AddRazorPages(); + _ = builder.Services.AddRazorPages(); - builder.Services.AddDbContext(options => + _ = builder.Services.AddDbContext(options => options.UseSqlite(builder.Configuration.GetConnectionString("DefaultConnection"))); - builder.Services.AddIdentity() + _ = builder.Services.AddIdentity() .AddEntityFrameworkStores() .AddDefaultTokenProviders(); - builder.Services + _ = builder.Services .AddIdentityServer(options => { options.Events.RaiseErrorEvents = true; @@ -77,7 +77,7 @@ internal static class HostingExtensions .AddAspNetIdentity() .AddLicenseSummary(); - builder.Services.AddAuthentication() + _ = builder.Services.AddAuthentication() .AddOpenIdConnect("oidc", "Sign-in with demo.duendesoftware.com", options => { options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; @@ -101,19 +101,19 @@ internal static class HostingExtensions public static WebApplication ConfigurePipeline(this WebApplication app) { - app.UseSerilogRequestLogging(); + _ = app.UseSerilogRequestLogging(); if (app.Environment.IsDevelopment()) { - app.UseDeveloperExceptionPage(); + _ = app.UseDeveloperExceptionPage(); } - app.UseStaticFiles(); - app.UseRouting(); - app.UseIdentityServer(); - app.UseAuthorization(); + _ = app.UseStaticFiles(); + _ = app.UseRouting(); + _ = app.UseIdentityServer(); + _ = app.UseAuthorization(); - app.MapRazorPages() + _ = app.MapRazorPages() .RequireAuthorization(); return app; diff --git a/identity-server/templates/src/IdentityServerAspNetIdentity/IdentityServerAspNetIdentity.csproj b/identity-server/templates/src/IdentityServerAspNetIdentity/IdentityServerAspNetIdentity.csproj index 5eb0ffceb..62596c8ac 100644 --- a/identity-server/templates/src/IdentityServerAspNetIdentity/IdentityServerAspNetIdentity.csproj +++ b/identity-server/templates/src/IdentityServerAspNetIdentity/IdentityServerAspNetIdentity.csproj @@ -1,15 +1,12 @@ - - + net10.0 enable enable IdentityServerHost - - @@ -18,5 +15,6 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/identity-server/templates/src/IdentityServerAspNetIdentity/Pages/Device/Index.cshtml.cs b/identity-server/templates/src/IdentityServerAspNetIdentity/Pages/Device/Index.cshtml.cs index 273989303..267ec6437 100644 --- a/identity-server/templates/src/IdentityServerAspNetIdentity/Pages/Device/Index.cshtml.cs +++ b/identity-server/templates/src/IdentityServerAspNetIdentity/Pages/Device/Index.cshtml.cs @@ -116,7 +116,7 @@ public class Index : PageModel if (grantedConsent != null) { // communicate outcome of consent back to identityserver - await _interaction.HandleRequestAsync(Input.UserCode, grantedConsent); + _ = await _interaction.HandleRequestAsync(Input.UserCode, grantedConsent); // indicate that's it ok to redirect back to authorization endpoint return RedirectToPage("/Device/Success"); diff --git a/identity-server/templates/src/IdentityServerAspNetIdentity/Pages/ExternalLogin/Callback.cshtml.cs b/identity-server/templates/src/IdentityServerAspNetIdentity/Pages/ExternalLogin/Callback.cshtml.cs index f70a9a3f4..3a8706907 100644 --- a/identity-server/templates/src/IdentityServerAspNetIdentity/Pages/ExternalLogin/Callback.cshtml.cs +++ b/identity-server/templates/src/IdentityServerAspNetIdentity/Pages/ExternalLogin/Callback.cshtml.cs @@ -75,7 +75,7 @@ public class Callback : PageModel // // remove the user id and name identifier claims so we don't include it as an extra claim if/when we provision the user var claims = externalUser.Claims.ToList(); - claims.RemoveAll(c => c.Type is JwtClaimTypes.Subject or ClaimTypes.NameIdentifier); + _ = claims.RemoveAll(c => c.Type is JwtClaimTypes.Subject or ClaimTypes.NameIdentifier); user = await AutoProvisionUserAsync(provider, providerUserId, claims.ToList()); } diff --git a/identity-server/templates/src/IdentityServerAspNetIdentity/Program.cs b/identity-server/templates/src/IdentityServerAspNetIdentity/Program.cs index 86f76f558..1b23868c2 100644 --- a/identity-server/templates/src/IdentityServerAspNetIdentity/Program.cs +++ b/identity-server/templates/src/IdentityServerAspNetIdentity/Program.cs @@ -31,7 +31,7 @@ try if (app.Environment.IsDevelopment()) { - app.Lifetime.ApplicationStopping.Register(() => + _ = app.Lifetime.ApplicationStopping.Register(() => { var usage = app.Services.GetRequiredService(); Console.Write(Summary(usage)); @@ -53,12 +53,12 @@ finally static string Summary(LicenseUsageSummary usage) { var sb = new StringBuilder(); - sb.AppendLine("IdentityServer Usage Summary:"); - sb.AppendLine(CultureInfo.InvariantCulture, $" License: {usage.LicenseEdition}"); + _ = sb.AppendLine("IdentityServer Usage Summary:"); + _ = sb.AppendLine(CultureInfo.InvariantCulture, $" License: {usage.LicenseEdition}"); var features = usage.FeaturesUsed.Count > 0 ? string.Join(", ", usage.FeaturesUsed) : "None"; - sb.AppendLine(CultureInfo.InvariantCulture, $" Business and Enterprise Edition Features Used: {features}"); - sb.AppendLine(CultureInfo.InvariantCulture, $" {usage.ClientsUsed.Count} Client Id(s) Used"); - sb.AppendLine(CultureInfo.InvariantCulture, $" {usage.IssuersUsed.Count} Issuer(s) Used"); + _ = sb.AppendLine(CultureInfo.InvariantCulture, $" Business and Enterprise Edition Features Used: {features}"); + _ = sb.AppendLine(CultureInfo.InvariantCulture, $" {usage.ClientsUsed.Count} Client Id(s) Used"); + _ = sb.AppendLine(CultureInfo.InvariantCulture, $" {usage.IssuersUsed.Count} Issuer(s) Used"); return sb.ToString(); } diff --git a/identity-server/templates/src/IdentityServerEmpty/HostingExtensions.cs b/identity-server/templates/src/IdentityServerEmpty/HostingExtensions.cs index 6a72339ec..6605cb3a3 100644 --- a/identity-server/templates/src/IdentityServerEmpty/HostingExtensions.cs +++ b/identity-server/templates/src/IdentityServerEmpty/HostingExtensions.cs @@ -10,23 +10,23 @@ internal static class HostingExtensions { // Set up logging to write regular entries to console, and diagnostics data to a file. // See https://docs.duendesoftware.com/identityserver/diagnostics/data - builder.Services.AddSerilog(lc => + _ = builder.Services.AddSerilog(lc => { - lc.WriteTo.Logger(consoleLogger => + _ = lc.WriteTo.Logger(consoleLogger => { - consoleLogger.WriteTo.Console( + _ = consoleLogger.WriteTo.Console( outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", formatProvider: CultureInfo.InvariantCulture); if (builder.Environment.IsDevelopment()) { - consoleLogger.Filter.ByExcluding(Matching.FromSource("Duende.IdentityServer.Diagnostics.Summary")); + _ = consoleLogger.Filter.ByExcluding(Matching.FromSource("Duende.IdentityServer.Diagnostics.Summary")); } }); if (builder.Environment.IsDevelopment()) { - lc.WriteTo.Logger(fileLogger => + _ = lc.WriteTo.Logger(fileLogger => { - fileLogger + _ = fileLogger .WriteTo.File("./diagnostics/diagnostic.log", rollingInterval: RollingInterval.Day, fileSizeLimitBytes: 1024 * 1024 * 10, // 10 MB rollOnFileSizeLimit: true, @@ -45,7 +45,7 @@ internal static class HostingExtensions // uncomment if you want to add a UI //builder.Services.AddRazorPages(); - builder.Services.AddIdentityServer() + _ = builder.Services.AddIdentityServer() .AddInMemoryIdentityResources(Config.IdentityResources) .AddInMemoryApiScopes(Config.ApiScopes) .AddInMemoryClients(Config.Clients) @@ -56,18 +56,18 @@ internal static class HostingExtensions public static WebApplication ConfigurePipeline(this WebApplication app) { - app.UseSerilogRequestLogging(); + _ = app.UseSerilogRequestLogging(); if (app.Environment.IsDevelopment()) { - app.UseDeveloperExceptionPage(); + _ = app.UseDeveloperExceptionPage(); } // uncomment if you want to add a UI //app.UseStaticFiles(); //app.UseRouting(); - app.UseIdentityServer(); + _ = app.UseIdentityServer(); // uncomment if you want to add a UI //app.UseAuthorization(); diff --git a/identity-server/templates/src/IdentityServerEmpty/Program.cs b/identity-server/templates/src/IdentityServerEmpty/Program.cs index b2cadb7f8..2b6ca7852 100644 --- a/identity-server/templates/src/IdentityServerEmpty/Program.cs +++ b/identity-server/templates/src/IdentityServerEmpty/Program.cs @@ -21,7 +21,7 @@ try if (app.Environment.IsDevelopment()) { - app.Lifetime.ApplicationStopping.Register(() => + _ = app.Lifetime.ApplicationStopping.Register(() => { var usage = app.Services.GetRequiredService(); Console.Write(Summary(usage)); @@ -43,12 +43,12 @@ finally static string Summary(LicenseUsageSummary usage) { var sb = new StringBuilder(); - sb.AppendLine("IdentityServer Usage Summary:"); - sb.AppendLine(CultureInfo.InvariantCulture, $" License: {usage.LicenseEdition}"); + _ = sb.AppendLine("IdentityServer Usage Summary:"); + _ = sb.AppendLine(CultureInfo.InvariantCulture, $" License: {usage.LicenseEdition}"); var features = usage.FeaturesUsed.Count > 0 ? string.Join(", ", usage.FeaturesUsed) : "None"; - sb.AppendLine(CultureInfo.InvariantCulture, $" Business and Enterprise Edition Features Used: {features}"); - sb.AppendLine(CultureInfo.InvariantCulture, $" {usage.ClientsUsed.Count} Client Id(s) Used"); - sb.AppendLine(CultureInfo.InvariantCulture, $" {usage.IssuersUsed.Count} Issuer(s) Used"); + _ = sb.AppendLine(CultureInfo.InvariantCulture, $" Business and Enterprise Edition Features Used: {features}"); + _ = sb.AppendLine(CultureInfo.InvariantCulture, $" {usage.ClientsUsed.Count} Client Id(s) Used"); + _ = sb.AppendLine(CultureInfo.InvariantCulture, $" {usage.IssuersUsed.Count} Issuer(s) Used"); return sb.ToString(); } diff --git a/identity-server/templates/src/IdentityServerEntityFramework/HostingExtensions.cs b/identity-server/templates/src/IdentityServerEntityFramework/HostingExtensions.cs index e59fba358..8458a7ed1 100644 --- a/identity-server/templates/src/IdentityServerEntityFramework/HostingExtensions.cs +++ b/identity-server/templates/src/IdentityServerEntityFramework/HostingExtensions.cs @@ -18,23 +18,23 @@ internal static class HostingExtensions { // Write most logs to the console but diagnostic data to a file. // See https://docs.duendesoftware.com/identityserver/diagnostics/data - builder.Services.AddSerilog(lc => + _ = builder.Services.AddSerilog(lc => { - lc.WriteTo.Logger(consoleLogger => + _ = lc.WriteTo.Logger(consoleLogger => { - consoleLogger.WriteTo.Console( + _ = consoleLogger.WriteTo.Console( outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", formatProvider: CultureInfo.InvariantCulture); if (builder.Environment.IsDevelopment()) { - consoleLogger.Filter.ByExcluding(Matching.FromSource("Duende.IdentityServer.Diagnostics.Summary")); + _ = consoleLogger.Filter.ByExcluding(Matching.FromSource("Duende.IdentityServer.Diagnostics.Summary")); } }); if (builder.Environment.IsDevelopment()) { - lc.WriteTo.Logger(fileLogger => + _ = lc.WriteTo.Logger(fileLogger => { - fileLogger + _ = fileLogger .WriteTo.File("./diagnostics/diagnostic.log", rollingInterval: RollingInterval.Day, fileSizeLimitBytes: 1024 * 1024 * 10, // 10 MB rollOnFileSizeLimit: true, @@ -50,7 +50,7 @@ internal static class HostingExtensions public static WebApplication ConfigureServices(this WebApplicationBuilder builder) { - builder.Services.AddRazorPages(); + _ = builder.Services.AddRazorPages(); var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); @@ -86,7 +86,7 @@ internal static class HostingExtensions }) .AddLicenseSummary(); - builder.Services.AddAuthentication() + _ = builder.Services.AddAuthentication() .AddOpenIdConnect("oidc", "Sign-in with demo.duendesoftware.com", options => { options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; @@ -107,18 +107,18 @@ internal static class HostingExtensions // this adds the necessary config for the simple admin/config pages { - builder.Services.AddAuthorization(options => + _ = builder.Services.AddAuthorization(options => options.AddPolicy("admin", policy => policy.RequireClaim("sub", "1")) ); - builder.Services.Configure(options => + _ = builder.Services.Configure(options => options.Conventions.AuthorizeFolder("/Admin", "admin")); - builder.Services.AddTransient(); - builder.Services.AddTransient(); - builder.Services.AddTransient(); - builder.Services.AddTransient(); + _ = builder.Services.AddTransient(); + _ = builder.Services.AddTransient(); + _ = builder.Services.AddTransient(); + _ = builder.Services.AddTransient(); } // if you want to use server-side sessions: https://blog.duendesoftware.com/posts/20220406_session_management/ @@ -134,19 +134,19 @@ internal static class HostingExtensions public static WebApplication ConfigurePipeline(this WebApplication app) { - app.UseSerilogRequestLogging(); + _ = app.UseSerilogRequestLogging(); if (app.Environment.IsDevelopment()) { - app.UseDeveloperExceptionPage(); + _ = app.UseDeveloperExceptionPage(); } - app.UseStaticFiles(); - app.UseRouting(); - app.UseIdentityServer(); - app.UseAuthorization(); + _ = app.UseStaticFiles(); + _ = app.UseRouting(); + _ = app.UseIdentityServer(); + _ = app.UseAuthorization(); - app.MapRazorPages() + _ = app.MapRazorPages() .RequireAuthorization(); return app; diff --git a/identity-server/templates/src/IdentityServerEntityFramework/IdentityServerEntityFramework.csproj b/identity-server/templates/src/IdentityServerEntityFramework/IdentityServerEntityFramework.csproj index 087f7c6e0..ed0cd004f 100644 --- a/identity-server/templates/src/IdentityServerEntityFramework/IdentityServerEntityFramework.csproj +++ b/identity-server/templates/src/IdentityServerEntityFramework/IdentityServerEntityFramework.csproj @@ -1,26 +1,21 @@ - - + net10.0 enable enable IdentityServerHost - - - all runtime; build; native; contentfiles; analyzers; buildtransitive + - - diff --git a/identity-server/templates/src/IdentityServerEntityFramework/Migrations/.editorconfig b/identity-server/templates/src/IdentityServerEntityFramework/Migrations/.editorconfig new file mode 100644 index 000000000..98e806338 --- /dev/null +++ b/identity-server/templates/src/IdentityServerEntityFramework/Migrations/.editorconfig @@ -0,0 +1,2 @@ +[*.cs] +dotnet_diagnostic.IDE0058.severity = none diff --git a/identity-server/templates/src/IdentityServerEntityFramework/Pages/Admin/ApiScopes/ApiScopeRepository.cs b/identity-server/templates/src/IdentityServerEntityFramework/Pages/Admin/ApiScopes/ApiScopeRepository.cs index 206b547d0..a8150c3e1 100644 --- a/identity-server/templates/src/IdentityServerEntityFramework/Pages/Admin/ApiScopes/ApiScopeRepository.cs +++ b/identity-server/templates/src/IdentityServerEntityFramework/Pages/Admin/ApiScopes/ApiScopeRepository.cs @@ -83,9 +83,9 @@ public class ApiScopeRepository // CA1849 Suppressed because AddAsync is only needed for value generators that // need async database access (e.g., HiLoValueGenerator), and we don't use those // generators - _context.ApiScopes.Add(scope.ToEntity()); + _ = _context.ApiScopes.Add(scope.ToEntity()); #pragma warning restore CA1849 // Call async methods when in an async method - await _context.SaveChangesAsync(); + _ = await _context.SaveChangesAsync(); } public async Task UpdateAsync(ApiScopeModel model) @@ -113,7 +113,7 @@ public class ApiScopeRepository if (claimsToRemove.Length != 0) { - scope.UserClaims.RemoveAll(x => claimsToRemove.Contains(x.Type)); + _ = scope.UserClaims.RemoveAll(x => claimsToRemove.Contains(x.Type)); } if (claimsToAdd.Length != 0) { @@ -123,7 +123,7 @@ public class ApiScopeRepository })); } - await _context.SaveChangesAsync(); + _ = await _context.SaveChangesAsync(); } public async Task DeleteAsync(string id) @@ -135,8 +135,8 @@ public class ApiScopeRepository throw new ArgumentException("Invalid Api Scope"); } - _context.ApiScopes.Remove(scope); - await _context.SaveChangesAsync(); + _ = _context.ApiScopes.Remove(scope); + _ = await _context.SaveChangesAsync(); } diff --git a/identity-server/templates/src/IdentityServerEntityFramework/Pages/Admin/Clients/ClientRepository.cs b/identity-server/templates/src/IdentityServerEntityFramework/Pages/Admin/Clients/ClientRepository.cs index c06a331a7..1376ea9cc 100644 --- a/identity-server/templates/src/IdentityServerEntityFramework/Pages/Admin/Clients/ClientRepository.cs +++ b/identity-server/templates/src/IdentityServerEntityFramework/Pages/Admin/Clients/ClientRepository.cs @@ -138,9 +138,9 @@ public class ClientRepository // CA1849 Suppressed because AddAsync is only needed for value generators that // need async database access (e.g., HiLoValueGenerator), and we don't use those // generators - _context.Clients.Add(client.ToEntity()); + _ = _context.Clients.Add(client.ToEntity()); #pragma warning restore CA1849 // Call async methods when in an async method - await _context.SaveChangesAsync(); + _ = await _context.SaveChangesAsync(); } public async Task UpdateAsync(EditClientModel model) @@ -171,7 +171,7 @@ public class ClientRepository if (scopesToRemove.Length != 0) { - client.AllowedScopes.RemoveAll(x => scopesToRemove.Contains(x.Scope)); + _ = client.AllowedScopes.RemoveAll(x => scopesToRemove.Contains(x.Scope)); } if (scopesToAdd.Length != 0) { @@ -216,7 +216,7 @@ public class ClientRepository } } - await _context.SaveChangesAsync(); + _ = await _context.SaveChangesAsync(); } public async Task DeleteAsync(string clientId) @@ -228,8 +228,8 @@ public class ClientRepository throw new ArgumentException("Invalid Client Id"); } - _context.Clients.Remove(client); - await _context.SaveChangesAsync(); + _ = _context.Clients.Remove(client); + _ = await _context.SaveChangesAsync(); } diff --git a/identity-server/templates/src/IdentityServerEntityFramework/Pages/Admin/IdentityScopes/IdentityScopeRepository.cs b/identity-server/templates/src/IdentityServerEntityFramework/Pages/Admin/IdentityScopes/IdentityScopeRepository.cs index 02d184abb..1fee143dc 100644 --- a/identity-server/templates/src/IdentityServerEntityFramework/Pages/Admin/IdentityScopes/IdentityScopeRepository.cs +++ b/identity-server/templates/src/IdentityServerEntityFramework/Pages/Admin/IdentityScopes/IdentityScopeRepository.cs @@ -82,9 +82,9 @@ public class IdentityScopeRepository // CA1849 Suppressed because AddAsync is only needed for value generators that // need async database access (e.g., HiLoValueGenerator), and we don't use those // generators - _context.IdentityResources.Add(scope.ToEntity()); + _ = _context.IdentityResources.Add(scope.ToEntity()); #pragma warning restore CA1849 - await _context.SaveChangesAsync(); + _ = await _context.SaveChangesAsync(); } public async Task UpdateAsync(IdentityScopeModel model) @@ -112,7 +112,7 @@ public class IdentityScopeRepository if (claimsToRemove.Length != 0) { - scope.UserClaims.RemoveAll(x => claimsToRemove.Contains(x.Type)); + _ = scope.UserClaims.RemoveAll(x => claimsToRemove.Contains(x.Type)); } if (claimsToAdd.Length != 0) { @@ -122,7 +122,7 @@ public class IdentityScopeRepository })); } - await _context.SaveChangesAsync(); + _ = await _context.SaveChangesAsync(); } public async Task DeleteAsync(string id) @@ -134,8 +134,8 @@ public class IdentityScopeRepository throw new ArgumentException("Invalid Identity Scope"); } - _context.IdentityResources.Remove(scope); - await _context.SaveChangesAsync(); + _ = _context.IdentityResources.Remove(scope); + _ = await _context.SaveChangesAsync(); } diff --git a/identity-server/templates/src/IdentityServerEntityFramework/Pages/Device/Index.cshtml.cs b/identity-server/templates/src/IdentityServerEntityFramework/Pages/Device/Index.cshtml.cs index 273989303..267ec6437 100644 --- a/identity-server/templates/src/IdentityServerEntityFramework/Pages/Device/Index.cshtml.cs +++ b/identity-server/templates/src/IdentityServerEntityFramework/Pages/Device/Index.cshtml.cs @@ -116,7 +116,7 @@ public class Index : PageModel if (grantedConsent != null) { // communicate outcome of consent back to identityserver - await _interaction.HandleRequestAsync(Input.UserCode, grantedConsent); + _ = await _interaction.HandleRequestAsync(Input.UserCode, grantedConsent); // indicate that's it ok to redirect back to authorization endpoint return RedirectToPage("/Device/Success"); diff --git a/identity-server/templates/src/IdentityServerEntityFramework/Pages/ExternalLogin/Callback.cshtml.cs b/identity-server/templates/src/IdentityServerEntityFramework/Pages/ExternalLogin/Callback.cshtml.cs index 6291d2378..59b99e913 100644 --- a/identity-server/templates/src/IdentityServerEntityFramework/Pages/ExternalLogin/Callback.cshtml.cs +++ b/identity-server/templates/src/IdentityServerEntityFramework/Pages/ExternalLogin/Callback.cshtml.cs @@ -73,7 +73,7 @@ public class Callback : PageModel // // remove the user id and name identifier claims so we don't include it as an extra claim if/when we provision the user var claims = externalUser.Claims.ToList(); - claims.RemoveAll(c => c.Type is JwtClaimTypes.Subject or ClaimTypes.NameIdentifier); + _ = claims.RemoveAll(c => c.Type is JwtClaimTypes.Subject or ClaimTypes.NameIdentifier); user = _users.AutoProvisionUser(provider, providerUserId, claims); } diff --git a/identity-server/templates/src/IdentityServerEntityFramework/Program.cs b/identity-server/templates/src/IdentityServerEntityFramework/Program.cs index 86f76f558..1b23868c2 100644 --- a/identity-server/templates/src/IdentityServerEntityFramework/Program.cs +++ b/identity-server/templates/src/IdentityServerEntityFramework/Program.cs @@ -31,7 +31,7 @@ try if (app.Environment.IsDevelopment()) { - app.Lifetime.ApplicationStopping.Register(() => + _ = app.Lifetime.ApplicationStopping.Register(() => { var usage = app.Services.GetRequiredService(); Console.Write(Summary(usage)); @@ -53,12 +53,12 @@ finally static string Summary(LicenseUsageSummary usage) { var sb = new StringBuilder(); - sb.AppendLine("IdentityServer Usage Summary:"); - sb.AppendLine(CultureInfo.InvariantCulture, $" License: {usage.LicenseEdition}"); + _ = sb.AppendLine("IdentityServer Usage Summary:"); + _ = sb.AppendLine(CultureInfo.InvariantCulture, $" License: {usage.LicenseEdition}"); var features = usage.FeaturesUsed.Count > 0 ? string.Join(", ", usage.FeaturesUsed) : "None"; - sb.AppendLine(CultureInfo.InvariantCulture, $" Business and Enterprise Edition Features Used: {features}"); - sb.AppendLine(CultureInfo.InvariantCulture, $" {usage.ClientsUsed.Count} Client Id(s) Used"); - sb.AppendLine(CultureInfo.InvariantCulture, $" {usage.IssuersUsed.Count} Issuer(s) Used"); + _ = sb.AppendLine(CultureInfo.InvariantCulture, $" Business and Enterprise Edition Features Used: {features}"); + _ = sb.AppendLine(CultureInfo.InvariantCulture, $" {usage.ClientsUsed.Count} Client Id(s) Used"); + _ = sb.AppendLine(CultureInfo.InvariantCulture, $" {usage.IssuersUsed.Count} Issuer(s) Used"); return sb.ToString(); } diff --git a/identity-server/templates/src/IdentityServerEntityFramework/SeedData.cs b/identity-server/templates/src/IdentityServerEntityFramework/SeedData.cs index d4b88dc5d..da9b7b0e3 100644 --- a/identity-server/templates/src/IdentityServerEntityFramework/SeedData.cs +++ b/identity-server/templates/src/IdentityServerEntityFramework/SeedData.cs @@ -27,9 +27,9 @@ public class SeedData Log.Debug("Clients being populated"); foreach (var client in Config.Clients.ToList()) { - context.Clients.Add(client.ToEntity()); + _ = context.Clients.Add(client.ToEntity()); } - context.SaveChanges(); + _ = context.SaveChanges(); } else { @@ -41,9 +41,9 @@ public class SeedData Log.Debug("IdentityResources being populated"); foreach (var resource in Config.IdentityResources.ToList()) { - context.IdentityResources.Add(resource.ToEntity()); + _ = context.IdentityResources.Add(resource.ToEntity()); } - context.SaveChanges(); + _ = context.SaveChanges(); } else { @@ -55,9 +55,9 @@ public class SeedData Log.Debug("ApiScopes being populated"); foreach (var resource in Config.ApiScopes.ToList()) { - context.ApiScopes.Add(resource.ToEntity()); + _ = context.ApiScopes.Add(resource.ToEntity()); } - context.SaveChanges(); + _ = context.SaveChanges(); } else { @@ -67,14 +67,14 @@ public class SeedData if (!context.IdentityProviders.Any()) { Log.Debug("OIDC IdentityProviders being populated"); - context.IdentityProviders.Add(new OidcProvider + _ = context.IdentityProviders.Add(new OidcProvider { Scheme = "demoidsrv", DisplayName = "IdentityServer", Authority = "https://demo.duendesoftware.com", ClientId = "login", }.ToEntity()); - context.SaveChanges(); + _ = context.SaveChanges(); } else { diff --git a/identity-server/templates/src/IdentityServerInMem/HostingExtensions.cs b/identity-server/templates/src/IdentityServerInMem/HostingExtensions.cs index fa5b29cf2..b89ef03d9 100644 --- a/identity-server/templates/src/IdentityServerInMem/HostingExtensions.cs +++ b/identity-server/templates/src/IdentityServerInMem/HostingExtensions.cs @@ -13,23 +13,23 @@ internal static class HostingExtensions { // Write most logs to the console but diagnostic data to a file. // See https://docs.duendesoftware.com/identityserver/diagnostics/data - builder.Services.AddSerilog(lc => + _ = builder.Services.AddSerilog(lc => { - lc.WriteTo.Logger(consoleLogger => + _ = lc.WriteTo.Logger(consoleLogger => { - consoleLogger.WriteTo.Console( + _ = consoleLogger.WriteTo.Console( outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", formatProvider: CultureInfo.InvariantCulture); if (builder.Environment.IsDevelopment()) { - consoleLogger.Filter.ByExcluding(Matching.FromSource("Duende.IdentityServer.Diagnostics.Summary")); + _ = consoleLogger.Filter.ByExcluding(Matching.FromSource("Duende.IdentityServer.Diagnostics.Summary")); } }); if (builder.Environment.IsDevelopment()) { - lc.WriteTo.Logger(fileLogger => + _ = lc.WriteTo.Logger(fileLogger => { - fileLogger + _ = fileLogger .WriteTo.File("./diagnostics/diagnostic.log", rollingInterval: RollingInterval.Day, fileSizeLimitBytes: 1024 * 1024 * 10, // 10 MB rollOnFileSizeLimit: true, @@ -45,7 +45,7 @@ internal static class HostingExtensions public static WebApplication ConfigureServices(this WebApplicationBuilder builder) { - builder.Services.AddRazorPages(); + _ = builder.Services.AddRazorPages(); var isBuilder = builder.Services.AddIdentityServer(options => { @@ -64,9 +64,9 @@ internal static class HostingExtensions .AddLicenseSummary(); // in-memory, code config - isBuilder.AddInMemoryIdentityResources(Config.IdentityResources); - isBuilder.AddInMemoryApiScopes(Config.ApiScopes); - isBuilder.AddInMemoryClients(Config.Clients); + _ = isBuilder.AddInMemoryIdentityResources(Config.IdentityResources); + _ = isBuilder.AddInMemoryApiScopes(Config.ApiScopes); + _ = isBuilder.AddInMemoryClients(Config.Clients); // if you want to use server-side sessions: https://blog.duendesoftware.com/posts/20220406_session_management/ @@ -82,7 +82,7 @@ internal static class HostingExtensions // options.Conventions.AuthorizeFolder("/ServerSideSessions", "admin")); - builder.Services.AddAuthentication() + _ = builder.Services.AddAuthentication() .AddOpenIdConnect("oidc", "Sign-in with demo.duendesoftware.com", options => { options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; @@ -106,19 +106,19 @@ internal static class HostingExtensions public static WebApplication ConfigurePipeline(this WebApplication app) { - app.UseSerilogRequestLogging(); + _ = app.UseSerilogRequestLogging(); if (app.Environment.IsDevelopment()) { - app.UseDeveloperExceptionPage(); + _ = app.UseDeveloperExceptionPage(); } - app.UseStaticFiles(); - app.UseRouting(); - app.UseIdentityServer(); - app.UseAuthorization(); + _ = app.UseStaticFiles(); + _ = app.UseRouting(); + _ = app.UseIdentityServer(); + _ = app.UseAuthorization(); - app.MapRazorPages() + _ = app.MapRazorPages() .RequireAuthorization(); return app; diff --git a/identity-server/templates/src/IdentityServerInMem/Pages/Device/Index.cshtml.cs b/identity-server/templates/src/IdentityServerInMem/Pages/Device/Index.cshtml.cs index c0f16a7f7..454c8d840 100644 --- a/identity-server/templates/src/IdentityServerInMem/Pages/Device/Index.cshtml.cs +++ b/identity-server/templates/src/IdentityServerInMem/Pages/Device/Index.cshtml.cs @@ -108,7 +108,7 @@ public class Index( if (grantedConsent != null) { // communicate outcome of consent back to identityserver - await interaction.HandleRequestAsync(Input.UserCode, grantedConsent); + _ = await interaction.HandleRequestAsync(Input.UserCode, grantedConsent); // indicate that's it ok to redirect back to authorization endpoint return RedirectToPage("/Device/Success"); diff --git a/identity-server/templates/src/IdentityServerInMem/Pages/ExternalLogin/Callback.cshtml.cs b/identity-server/templates/src/IdentityServerInMem/Pages/ExternalLogin/Callback.cshtml.cs index f3639f4a8..7baac3c7a 100644 --- a/identity-server/templates/src/IdentityServerInMem/Pages/ExternalLogin/Callback.cshtml.cs +++ b/identity-server/templates/src/IdentityServerInMem/Pages/ExternalLogin/Callback.cshtml.cs @@ -63,7 +63,7 @@ public class Callback( // // remove the user id and name identifier claims so we don't include it as an extra claim if/when we provision the user var claims = externalUser.Claims.ToList(); - claims.RemoveAll(c => c.Type is JwtClaimTypes.Subject or ClaimTypes.NameIdentifier); + _ = claims.RemoveAll(c => c.Type is JwtClaimTypes.Subject or ClaimTypes.NameIdentifier); user = _users.AutoProvisionUser(provider, providerUserId, claims); } diff --git a/identity-server/templates/src/IdentityServerInMem/Program.cs b/identity-server/templates/src/IdentityServerInMem/Program.cs index cdfaf2dce..9733b241a 100644 --- a/identity-server/templates/src/IdentityServerInMem/Program.cs +++ b/identity-server/templates/src/IdentityServerInMem/Program.cs @@ -21,7 +21,7 @@ try if (app.Environment.IsDevelopment()) { - app.Lifetime.ApplicationStopping.Register(() => + _ = app.Lifetime.ApplicationStopping.Register(() => { var usage = app.Services.GetRequiredService(); Console.Write(Summary(usage)); @@ -43,12 +43,12 @@ finally static string Summary(LicenseUsageSummary usage) { var sb = new StringBuilder(); - sb.AppendLine("IdentityServer Usage Summary:"); - sb.AppendLine(CultureInfo.InvariantCulture, $" License: {usage.LicenseEdition}"); + _ = sb.AppendLine("IdentityServer Usage Summary:"); + _ = sb.AppendLine(CultureInfo.InvariantCulture, $" License: {usage.LicenseEdition}"); var features = usage.FeaturesUsed.Count > 0 ? string.Join(", ", usage.FeaturesUsed) : "None"; - sb.AppendLine(CultureInfo.InvariantCulture, $" Business and Enterprise Edition Features Used: {features}"); - sb.AppendLine(CultureInfo.InvariantCulture, $" {usage.ClientsUsed.Count} Client Id(s) Used"); - sb.AppendLine(CultureInfo.InvariantCulture, $" {usage.IssuersUsed.Count} Issuer(s) Used"); + _ = sb.AppendLine(CultureInfo.InvariantCulture, $" Business and Enterprise Edition Features Used: {features}"); + _ = sb.AppendLine(CultureInfo.InvariantCulture, $" {usage.ClientsUsed.Count} Client Id(s) Used"); + _ = sb.AppendLine(CultureInfo.InvariantCulture, $" {usage.IssuersUsed.Count} Issuer(s) Used"); return sb.ToString(); } diff --git a/identity-server/templates/src/WebApp/HostingExtensions.cs b/identity-server/templates/src/WebApp/HostingExtensions.cs index e45ca5b8c..da557e2fb 100644 --- a/identity-server/templates/src/WebApp/HostingExtensions.cs +++ b/identity-server/templates/src/WebApp/HostingExtensions.cs @@ -14,7 +14,7 @@ internal static class HostingExtensions { public static WebApplication ConfigureServices(this WebApplicationBuilder builder) { - builder.Services.AddRazorPages(); + _ = builder.Services.AddRazorPages(); // In production, these values should be stored securely in Azure Key Vault or AWS Secrets Manager. var identityProviderConfig = builder.Configuration @@ -28,7 +28,7 @@ internal static class HostingExtensions // The __Host- prefix ensures the cookie is host-only, requires Secure and Path=/ attributes var hostCookiePrefix = "__Host-"; - builder.Services.AddAuthentication(options => + _ = builder.Services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; @@ -87,7 +87,7 @@ internal static class HostingExtensions // In production, use a secure location for storing keys, such as Azure Key Vault or AWS Secrets Manager. // Make sure to secure the keys at rest. - builder.Services.AddDataProtection() + _ = builder.Services.AddDataProtection() .SetApplicationName("TemplateWebApp") .PersistKeysToFileSystem(new DirectoryInfo("./keys")); @@ -98,18 +98,18 @@ internal static class HostingExtensions { if (!app.Environment.IsDevelopment()) { - app.UseExceptionHandler("/Error"); - app.UseHsts(); + _ = app.UseExceptionHandler("/Error"); + _ = app.UseHsts(); } - app.UseHttpsRedirection(); - app.UseRouting(); + _ = app.UseHttpsRedirection(); + _ = app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); + _ = app.UseAuthentication(); + _ = app.UseAuthorization(); - app.MapStaticAssets(); - app.MapRazorPages() + _ = app.MapStaticAssets(); + _ = app.MapRazorPages() .WithStaticAssets(); return app; diff --git a/identity-server/test/Directory.Build.props b/identity-server/test/Directory.Build.props index d790c2b05..f967d20c5 100644 --- a/identity-server/test/Directory.Build.props +++ b/identity-server/test/Directory.Build.props @@ -1,5 +1,6 @@ + diff --git a/identity-server/test/IdentityServer.EndToEndTests/IdentityServer.EndToEndTests.csproj b/identity-server/test/IdentityServer.EndToEndTests/IdentityServer.EndToEndTests.csproj index 2e0323672..82110445b 100644 --- a/identity-server/test/IdentityServer.EndToEndTests/IdentityServer.EndToEndTests.csproj +++ b/identity-server/test/IdentityServer.EndToEndTests/IdentityServer.EndToEndTests.csproj @@ -1,21 +1,18 @@ - net10.0 enable enable Duende.IdentityServer.EndToEndTests - + + - - - @@ -23,11 +20,9 @@ - - diff --git a/identity-server/test/IdentityServer.IntegrationTests/Endpoints/Saml/SamlData.cs b/identity-server/test/IdentityServer.IntegrationTests/Endpoints/Saml/SamlData.cs index 8dfcb3745..fb82c7b8f 100644 --- a/identity-server/test/IdentityServer.IntegrationTests/Endpoints/Saml/SamlData.cs +++ b/identity-server/test/IdentityServer.IntegrationTests/Endpoints/Saml/SamlData.cs @@ -3,8 +3,6 @@ #nullable enable -using Microsoft.Extensions.Time.Testing; - namespace Duende.IdentityServer.IntegrationTests.Endpoints.Saml; internal class SamlData diff --git a/identity-server/test/IdentityServer.IntegrationTests/Endpoints/Saml/SamlTestHelpers.cs b/identity-server/test/IdentityServer.IntegrationTests/Endpoints/Saml/SamlTestHelpers.cs index 7d00b1767..a2c931a21 100644 --- a/identity-server/test/IdentityServer.IntegrationTests/Endpoints/Saml/SamlTestHelpers.cs +++ b/identity-server/test/IdentityServer.IntegrationTests/Endpoints/Saml/SamlTestHelpers.cs @@ -541,7 +541,7 @@ internal static class SamlTestHelpers return null; } - var targetCookie = cookieHeaderValues.FirstOrDefault(cookie => cookie.Name == "__Host-idsrv.SamlSigninState"); + var targetCookie = cookieHeaderValues.FirstOrDefault(cookie => cookie.Name == "__IdsSvr_SamlSigninState"); return targetCookie?.Value.ToString(); } diff --git a/identity-server/test/IdentityServer.IntegrationTests/Endpoints/Saml/SustainSysSamlTestFixture.cs b/identity-server/test/IdentityServer.IntegrationTests/Endpoints/Saml/SustainSysSamlTestFixture.cs index 5897de5dd..a8edadc1d 100644 --- a/identity-server/test/IdentityServer.IntegrationTests/Endpoints/Saml/SustainSysSamlTestFixture.cs +++ b/identity-server/test/IdentityServer.IntegrationTests/Endpoints/Saml/SustainSysSamlTestFixture.cs @@ -15,7 +15,6 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Time.Testing; using Sustainsys.Saml2.AspNetCore2; using IdentityProvider = Sustainsys.Saml2.IdentityProvider; diff --git a/identity-server/test/IdentityServer.IntegrationTests/Endpoints/Saml/TestSamlClaimsMapper.cs b/identity-server/test/IdentityServer.IntegrationTests/Endpoints/Saml/TestSamlClaimsMapper.cs index 38359e79c..56f569b39 100644 --- a/identity-server/test/IdentityServer.IntegrationTests/Endpoints/Saml/TestSamlClaimsMapper.cs +++ b/identity-server/test/IdentityServer.IntegrationTests/Endpoints/Saml/TestSamlClaimsMapper.cs @@ -12,7 +12,7 @@ namespace Duende.IdentityServer.IntegrationTests.Endpoints.Saml; /// public class TestSamlClaimsMapper : ISamlClaimsMapper { - public Task> MapClaimsAsync(SamlClaimsMappingContext mappingContext) + public Task> MapClaimsAsync(SamlClaimsMappingContext mappingContext) { var attributes = new List { @@ -23,6 +23,6 @@ public class TestSamlClaimsMapper : ISamlClaimsMapper Values = new List { "custom_value" } } }; - return Task.FromResult>(attributes); + return Task.FromResult>(attributes); } } diff --git a/identity-server/test/IdentityServer.IntegrationTests/Endpoints/Token/CibaTokenEndpointTests.cs b/identity-server/test/IdentityServer.IntegrationTests/Endpoints/Token/CibaTokenEndpointTests.cs index 4d488c798..49fc5f957 100644 --- a/identity-server/test/IdentityServer.IntegrationTests/Endpoints/Token/CibaTokenEndpointTests.cs +++ b/identity-server/test/IdentityServer.IntegrationTests/Endpoints/Token/CibaTokenEndpointTests.cs @@ -12,7 +12,6 @@ using Duende.IdentityServer.Test; using Duende.IdentityServer.Validation; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Time.Testing; namespace Duende.IdentityServer.IntegrationTests.Endpoints.Token; diff --git a/identity-server/test/IdentityServer.IntegrationTests/EntityFramework/Storage/Stores/SamlServiceProviderStoreTests.cs b/identity-server/test/IdentityServer.IntegrationTests/EntityFramework/Storage/Stores/SamlServiceProviderStoreTests.cs deleted file mode 100644 index 3d3a4c413..000000000 --- a/identity-server/test/IdentityServer.IntegrationTests/EntityFramework/Storage/Stores/SamlServiceProviderStoreTests.cs +++ /dev/null @@ -1,229 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -#nullable enable -using Duende.IdentityServer.EntityFramework.DbContexts; -using Duende.IdentityServer.EntityFramework.Mappers; -using Duende.IdentityServer.EntityFramework.Options; -using Duende.IdentityServer.EntityFramework.Stores; -using Duende.IdentityServer.Models; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Logging.Abstractions; - -namespace Duende.IdentityServer.IntegrationTests.EntityFramework.Storage.Stores; - -public class SamlServiceProviderStoreTests : IntegrationTest -{ - private readonly Ct _ct = TestContext.Current.CancellationToken; - - public SamlServiceProviderStoreTests(DatabaseProviderFixture fixture) : base(fixture) - { - foreach (var options in TestDatabaseProviders) - { - using var context = new ConfigurationDbContext(options); - context.Database.EnsureCreated(); - } - } - - [Theory, MemberData(nameof(TestDatabaseProviders))] - public async Task FindByEntityIdAsync_WhenSpDoesNotExist_ExpectNull(DbContextOptions options) - { - await using var context = new ConfigurationDbContext(options); - var store = new SamlServiceProviderStore(context, new NullLogger()); - - var result = await store.FindByEntityIdAsync("https://notfound.example.com", _ct); - - result.ShouldBeNull(); - } - - [Theory, MemberData(nameof(TestDatabaseProviders))] - public async Task FindByEntityIdAsync_WhenSpExists_ExpectSpReturned(DbContextOptions options) - { - var testSp = new SamlServiceProvider - { - EntityId = "https://find-test.example.com", - DisplayName = "Find Test SP", - AssertionConsumerServiceUrls = new HashSet { new Uri("https://find-test.example.com/acs") } - }; - - await using (var context = new ConfigurationDbContext(options)) - { - context.SamlServiceProviders.Add(testSp.ToEntity()); - await context.SaveChangesAsync(); - } - - SamlServiceProvider? result; - await using (var context = new ConfigurationDbContext(options)) - { - var store = new SamlServiceProviderStore(context, new NullLogger()); - result = await store.FindByEntityIdAsync(testSp.EntityId, _ct); - } - - result.ShouldNotBeNull(); - result.EntityId.ShouldBe(testSp.EntityId); - result.DisplayName.ShouldBe(testSp.DisplayName); - } - - [Theory, MemberData(nameof(TestDatabaseProviders))] - public async Task FindByEntityIdAsync_WhenSpExistsWithCollections_ExpectCollectionsReturned(DbContextOptions options) - { - var testSp = new SamlServiceProvider - { - EntityId = "https://collections-test.example.com", - DisplayName = "Collections Test SP", - AssertionConsumerServiceUrls = new HashSet - { - new Uri("https://collections-test.example.com/acs1"), - new Uri("https://collections-test.example.com/acs2") - }, - SingleLogoutServiceUrl = new SamlEndpointType - { - Location = new Uri("https://collections-test.example.com/slo"), - Binding = SamlBinding.HttpPost - }, - ClaimMappings = new Dictionary - { - { "department", "businessUnit" }, - { "email", "mail" } - }, - AssertionConsumerServiceBinding = SamlBinding.HttpPost, - ClockSkew = TimeSpan.FromMinutes(5), - RequireSignedAuthnRequests = false, - Enabled = true - }; - - await using (var context = new ConfigurationDbContext(options)) - { - context.SamlServiceProviders.Add(testSp.ToEntity()); - await context.SaveChangesAsync(); - } - - SamlServiceProvider? result; - await using (var context = new ConfigurationDbContext(options)) - { - var store = new SamlServiceProviderStore(context, new NullLogger()); - result = await store.FindByEntityIdAsync(testSp.EntityId, _ct); - } - - result.ShouldNotBeNull(); - result.ShouldSatisfyAllConditions( - sp => sp.EntityId.ShouldBe(testSp.EntityId), - sp => sp.DisplayName.ShouldBe(testSp.DisplayName), - sp => sp.AssertionConsumerServiceUrls.Count.ShouldBe(2), - sp => sp.AssertionConsumerServiceUrls.ShouldContain(u => u.AbsoluteUri == "https://collections-test.example.com/acs1"), - sp => sp.AssertionConsumerServiceUrls.ShouldContain(u => u.AbsoluteUri == "https://collections-test.example.com/acs2"), - sp => sp.SingleLogoutServiceUrl.ShouldNotBeNull(), - sp => sp.SingleLogoutServiceUrl!.Location.AbsoluteUri.ShouldBe("https://collections-test.example.com/slo"), - sp => sp.SingleLogoutServiceUrl!.Binding.ShouldBe(SamlBinding.HttpPost), - sp => sp.ClaimMappings.Count.ShouldBe(2), - sp => sp.ClaimMappings["department"].ShouldBe("businessUnit"), - sp => sp.ClaimMappings["email"].ShouldBe("mail"), - sp => sp.ClockSkew.ShouldBe(TimeSpan.FromMinutes(5)) - ); - } - - [Fact] - public async Task GetAllSamlServiceProvidersAsync_WhenNoSpsExist_ExpectEmptyCollection() - { - var freshOptions = DatabaseProviderBuilder.BuildSqlite( - nameof(GetAllSamlServiceProvidersAsync_WhenNoSpsExist_ExpectEmptyCollection), StoreOptions); - await using var context = new ConfigurationDbContext(freshOptions); - await context.Database.EnsureCreatedAsync(); - - var store = new SamlServiceProviderStore(context, new NullLogger()); - - var result = new List(); - await foreach (var sp in store.GetAllSamlServiceProvidersAsync(_ct)) - { - result.Add(sp); - } - - result.ShouldNotBeNull(); - result.ShouldBeEmpty(); - } - - [Theory, MemberData(nameof(TestDatabaseProviders))] - public async Task GetAllSamlServiceProvidersAsync_WhenSpsExist_ExpectAllReturned(DbContextOptions options) - { - var testSps = new List - { - new() { EntityId = "https://enum-sp1.example.com", DisplayName = "Enum SP 1", - AssertionConsumerServiceUrls = new HashSet { new Uri("https://enum-sp1.example.com/acs") } }, - new() { EntityId = "https://enum-sp2.example.com", DisplayName = "Enum SP 2", - AssertionConsumerServiceUrls = new HashSet { new Uri("https://enum-sp2.example.com/acs") } }, - new() { EntityId = "https://enum-sp3.example.com", DisplayName = "Enum SP 3", - AssertionConsumerServiceUrls = new HashSet { new Uri("https://enum-sp3.example.com/acs") } } - }; - - await using (var context = new ConfigurationDbContext(options)) - { - foreach (var sp in testSps) - { - context.SamlServiceProviders.Add(sp.ToEntity()); - } - await context.SaveChangesAsync(); - } - - await using (var context = new ConfigurationDbContext(options)) - { - var store = new SamlServiceProviderStore(context, new NullLogger()); - - var result = new List(); - await foreach (var sp in store.GetAllSamlServiceProvidersAsync(_ct)) - { - result.Add(sp); - } - - result.ShouldNotBeNull(); - result.Count.ShouldBeGreaterThanOrEqualTo(3); - result.ShouldContain(s => s.EntityId == "https://enum-sp1.example.com"); - result.ShouldContain(s => s.EntityId == "https://enum-sp2.example.com"); - result.ShouldContain(s => s.EntityId == "https://enum-sp3.example.com"); - } - } - - [Theory, MemberData(nameof(TestDatabaseProviders))] - public async Task GetAllSamlServiceProvidersAsync_WhenSpsExistWithCollections_ExpectCollectionsIncluded(DbContextOptions options) - { - var testSp = new SamlServiceProvider - { - EntityId = "https://enum-collections-sp.example.com", - DisplayName = "Enum Collections SP", - AssertionConsumerServiceUrls = new HashSet - { - new Uri("https://enum-collections-sp.example.com/acs") - }, - ClaimMappings = new Dictionary - { - { "role", "samlRole" } - } - }; - - await using (var context = new ConfigurationDbContext(options)) - { - context.SamlServiceProviders.Add(testSp.ToEntity()); - await context.SaveChangesAsync(); - } - - await using (var context = new ConfigurationDbContext(options)) - { - var store = new SamlServiceProviderStore(context, new NullLogger()); - - var result = new List(); - await foreach (var sp in store.GetAllSamlServiceProvidersAsync(_ct)) - { - result.Add(sp); - } - - var found = result.FirstOrDefault(s => s.EntityId == testSp.EntityId); - found.ShouldNotBeNull(); - found.ShouldSatisfyAllConditions( - sp => sp.EntityId.ShouldBe(testSp.EntityId), - sp => sp.AssertionConsumerServiceUrls.Count.ShouldBe(1), - sp => sp.AssertionConsumerServiceUrls.ShouldContain(u => u.AbsoluteUri == "https://enum-collections-sp.example.com/acs"), - sp => sp.ClaimMappings.Count.ShouldBe(1), - sp => sp.ClaimMappings["role"].ShouldBe("samlRole") - ); - } - } -} diff --git a/identity-server/test/IdentityServer.IntegrationTests/Extensibility/CustomClaimsServiceTests.cs b/identity-server/test/IdentityServer.IntegrationTests/Extensibility/CustomClaimsServiceTests.cs index 3ea10bbbf..171399786 100644 --- a/identity-server/test/IdentityServer.IntegrationTests/Extensibility/CustomClaimsServiceTests.cs +++ b/identity-server/test/IdentityServer.IntegrationTests/Extensibility/CustomClaimsServiceTests.cs @@ -77,7 +77,7 @@ public class CustomClaimsService : DefaultClaimsService { } - public override async Task> GetAccessTokenClaimsAsync(ClaimsPrincipal subject, ResourceValidationResult resourceResult, ValidatedRequest request, Ct ct) + public override async Task> GetAccessTokenClaimsAsync(ClaimsPrincipal subject, ResourceValidationResult resourceResult, ValidatedRequest request, Ct ct) { var result = (await base.GetAccessTokenClaimsAsync(subject, resourceResult, request, ct)).ToList(); diff --git a/identity-server/test/IdentityServer.IntegrationTests/IdentityServer.IntegrationTests.csproj b/identity-server/test/IdentityServer.IntegrationTests/IdentityServer.IntegrationTests.csproj index e0f2988b7..d506bce71 100644 --- a/identity-server/test/IdentityServer.IntegrationTests/IdentityServer.IntegrationTests.csproj +++ b/identity-server/test/IdentityServer.IntegrationTests/IdentityServer.IntegrationTests.csproj @@ -1,28 +1,21 @@ - net10.0 Duende.IdentityServer.IntegrationTests - - - + - + - - - - Always @@ -31,13 +24,11 @@ Always - PreserveNewest - diff --git a/identity-server/test/IdentityServer.UnitTests/Caches/ResourceStoreCacheTests.cs b/identity-server/test/IdentityServer.UnitTests/Caches/ResourceStoreCacheTests.cs index 8b6e74927..628d5d017 100644 --- a/identity-server/test/IdentityServer.UnitTests/Caches/ResourceStoreCacheTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Caches/ResourceStoreCacheTests.cs @@ -6,7 +6,6 @@ using Duende.IdentityServer.Models; using Duende.IdentityServer.Services; using Duende.IdentityServer.Stores; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Time.Testing; namespace IdentityServer.UnitTests.Caches; diff --git a/identity-server/test/IdentityServer.UnitTests/Common/MockBackChannelAuthenticationRequestStore.cs b/identity-server/test/IdentityServer.UnitTests/Common/MockBackChannelAuthenticationRequestStore.cs index d4f42eb07..ff5ad0513 100644 --- a/identity-server/test/IdentityServer.UnitTests/Common/MockBackChannelAuthenticationRequestStore.cs +++ b/identity-server/test/IdentityServer.UnitTests/Common/MockBackChannelAuthenticationRequestStore.cs @@ -28,12 +28,12 @@ public class MockBackChannelAuthenticationRequestStore : IBackChannelAuthenticat return Task.FromResult(item.Value); } - public Task> GetLoginsForUserAsync(string subjectId, Ct ct, string clientId = null) + public Task> GetLoginsForUserAsync(string subjectId, Ct ct, string clientId = null) { var items = Items.Where(x => x.Value.Subject.GetSubjectId() == subjectId && (clientId == null || x.Value.ClientId == clientId) ); - return Task.FromResult(items.Select(x => x.Value).AsEnumerable()); + return Task.FromResult>(items.Select(x => x.Value).ToArray()); } public Task RemoveByInternalIdAsync(string id, Ct _) diff --git a/identity-server/test/IdentityServer.UnitTests/Common/MockClaimsService.cs b/identity-server/test/IdentityServer.UnitTests/Common/MockClaimsService.cs index 18413c38c..f3578bea3 100644 --- a/identity-server/test/IdentityServer.UnitTests/Common/MockClaimsService.cs +++ b/identity-server/test/IdentityServer.UnitTests/Common/MockClaimsService.cs @@ -13,7 +13,7 @@ internal class MockClaimsService : IClaimsService public List IdentityTokenClaims { get; set; } = new List(); public List AccessTokenClaims { get; set; } = new List(); - public Task> GetIdentityTokenClaimsAsync(ClaimsPrincipal subject, ResourceValidationResult resources, bool includeAllIdentityClaims, ValidatedRequest request, Ct _) => Task.FromResult(IdentityTokenClaims.AsEnumerable()); + public Task> GetIdentityTokenClaimsAsync(ClaimsPrincipal subject, ResourceValidationResult resources, bool includeAllIdentityClaims, ValidatedRequest request, Ct _) => Task.FromResult>(IdentityTokenClaims); - public Task> GetAccessTokenClaimsAsync(ClaimsPrincipal subject, ResourceValidationResult resources, ValidatedRequest request, Ct _) => Task.FromResult(AccessTokenClaims.AsEnumerable()); + public Task> GetAccessTokenClaimsAsync(ClaimsPrincipal subject, ResourceValidationResult resources, ValidatedRequest request, Ct _) => Task.FromResult>(AccessTokenClaims); } diff --git a/identity-server/test/IdentityServer.UnitTests/Common/MockKeyMaterialService.cs b/identity-server/test/IdentityServer.UnitTests/Common/MockKeyMaterialService.cs index b3ff7dc24..9e286b434 100644 --- a/identity-server/test/IdentityServer.UnitTests/Common/MockKeyMaterialService.cs +++ b/identity-server/test/IdentityServer.UnitTests/Common/MockKeyMaterialService.cs @@ -13,9 +13,9 @@ internal class MockKeyMaterialService : IKeyMaterialService public List SigningCredentials = new List(); public List ValidationKeys = new List(); - public Task> GetAllSigningCredentialsAsync(Ct _) => Task.FromResult(SigningCredentials.AsEnumerable()); + public Task> GetAllSigningCredentialsAsync(Ct _) => Task.FromResult>(SigningCredentials); public Task GetSigningCredentialsAsync(IEnumerable allowedAlgorithms, Ct _) => Task.FromResult(SigningCredentials.FirstOrDefault()); - public Task> GetValidationKeysAsync(Ct _) => Task.FromResult(ValidationKeys.AsEnumerable()); + public Task> GetValidationKeysAsync(Ct _) => Task.FromResult>(ValidationKeys); } diff --git a/identity-server/test/IdentityServer.UnitTests/Common/MockLogoutNotificationService.cs b/identity-server/test/IdentityServer.UnitTests/Common/MockLogoutNotificationService.cs index fb3161350..b21e011bf 100644 --- a/identity-server/test/IdentityServer.UnitTests/Common/MockLogoutNotificationService.cs +++ b/identity-server/test/IdentityServer.UnitTests/Common/MockLogoutNotificationService.cs @@ -15,15 +15,15 @@ public class MockLogoutNotificationService : ILogoutNotificationService public bool SendBackChannelLogoutNotificationsCalled { get; set; } public List BackChannelLogoutRequests { get; set; } = new List(); - public Task> GetFrontChannelLogoutNotificationsUrlsAsync(LogoutNotificationContext context, Ct _) + public Task> GetFrontChannelLogoutNotificationsUrlsAsync(LogoutNotificationContext context, Ct _) { GetFrontChannelLogoutNotificationsUrlsCalled = true; - return Task.FromResult(FrontChannelLogoutNotificationsUrls.AsEnumerable()); + return Task.FromResult>(FrontChannelLogoutNotificationsUrls); } - public Task> GetBackChannelLogoutNotificationsAsync(LogoutNotificationContext context, Ct _) + public Task> GetBackChannelLogoutNotificationsAsync(LogoutNotificationContext context, Ct _) { SendBackChannelLogoutNotificationsCalled = true; - return Task.FromResult(BackChannelLogoutRequests.AsEnumerable()); + return Task.FromResult>(BackChannelLogoutRequests); } } diff --git a/identity-server/test/IdentityServer.UnitTests/Common/MockPersistedGrantService.cs b/identity-server/test/IdentityServer.UnitTests/Common/MockPersistedGrantService.cs index 20a3318ba..8b6555ca5 100644 --- a/identity-server/test/IdentityServer.UnitTests/Common/MockPersistedGrantService.cs +++ b/identity-server/test/IdentityServer.UnitTests/Common/MockPersistedGrantService.cs @@ -9,10 +9,10 @@ namespace UnitTests.Common; public class MockPersistedGrantService : IPersistedGrantService { - public IEnumerable GetAllGrantsResult { get; set; } + public IReadOnlyCollection GetAllGrantsResult { get; set; } public bool RemoveAllGrantsWasCalled { get; set; } - public Task> GetAllGrantsAsync(string subjectId, Ct _) => Task.FromResult(GetAllGrantsResult ?? Enumerable.Empty()); + public Task> GetAllGrantsAsync(string subjectId, Ct _) => Task.FromResult(GetAllGrantsResult ?? Array.Empty()); public Task RemoveAllGrantsAsync(string subjectId, Ct _, string clientId = null, string sessionId = null) { diff --git a/identity-server/test/IdentityServer.UnitTests/Common/MockSamlLogoutNotificationService.cs b/identity-server/test/IdentityServer.UnitTests/Common/MockSamlLogoutNotificationService.cs index b92d9c52a..461d77c69 100644 --- a/identity-server/test/IdentityServer.UnitTests/Common/MockSamlLogoutNotificationService.cs +++ b/identity-server/test/IdentityServer.UnitTests/Common/MockSamlLogoutNotificationService.cs @@ -11,9 +11,9 @@ public class MockSamlLogoutNotificationService : ISamlLogoutNotificationService public bool GetSamlFrontChannelLogoutsAsyncCalled { get; set; } public List SamlFrontChannelLogouts { get; set; } = []; - public Task> GetSamlFrontChannelLogoutsAsync(LogoutNotificationContext context, Ct _) + public Task> GetSamlFrontChannelLogoutsAsync(LogoutNotificationContext context, Ct _) { GetSamlFrontChannelLogoutsAsyncCalled = true; - return Task.FromResult(SamlFrontChannelLogouts.AsEnumerable()); + return Task.FromResult>(SamlFrontChannelLogouts); } } diff --git a/identity-server/test/IdentityServer.UnitTests/Common/MockUserSession.cs b/identity-server/test/IdentityServer.UnitTests/Common/MockUserSession.cs index f0d4d26ae..7d762ff4a 100644 --- a/identity-server/test/IdentityServer.UnitTests/Common/MockUserSession.cs +++ b/identity-server/test/IdentityServer.UnitTests/Common/MockUserSession.cs @@ -47,7 +47,7 @@ public class MockUserSession : IUserSession return Task.CompletedTask; } - public Task> GetClientListAsync(Ct _) => Task.FromResult>(Clients); + public Task> GetClientListAsync(Ct _) => Task.FromResult>(Clients); public Task AddClientIdAsync(string clientId, Ct _) { @@ -62,7 +62,7 @@ public class MockUserSession : IUserSession return Task.CompletedTask; } - public Task> GetSamlSessionListAsync(Ct _) => Task.FromResult>(SamlSessions); + public Task> GetSamlSessionListAsync(Ct _) => Task.FromResult>(SamlSessions); public Task RemoveSamlSessionAsync(string entityId, Ct _) { diff --git a/identity-server/test/IdentityServer.UnitTests/Common/TestSamlClaimsMapper.cs b/identity-server/test/IdentityServer.UnitTests/Common/TestSamlClaimsMapper.cs index 1162f198f..7a3f15be6 100644 --- a/identity-server/test/IdentityServer.UnitTests/Common/TestSamlClaimsMapper.cs +++ b/identity-server/test/IdentityServer.UnitTests/Common/TestSamlClaimsMapper.cs @@ -12,7 +12,7 @@ namespace UnitTests.Common; /// public class TestSamlClaimsMapper : ISamlClaimsMapper { - public Task> MapClaimsAsync(SamlClaimsMappingContext mappingContext) + public Task> MapClaimsAsync(SamlClaimsMappingContext mappingContext) { var attributes = new List { @@ -23,6 +23,6 @@ public class TestSamlClaimsMapper : ISamlClaimsMapper Values = new List { "custom_value" } } }; - return Task.FromResult>(attributes); + return Task.FromResult>(attributes); } } diff --git a/identity-server/test/IdentityServer.UnitTests/Endpoints/Results/AuthorizeResultTests.cs b/identity-server/test/IdentityServer.UnitTests/Endpoints/Results/AuthorizeResultTests.cs index be347e577..320ce85e8 100644 --- a/identity-server/test/IdentityServer.UnitTests/Endpoints/Results/AuthorizeResultTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Endpoints/Results/AuthorizeResultTests.cs @@ -14,7 +14,6 @@ using Duende.IdentityServer.Validation; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.WebUtilities; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Time.Testing; using UnitTests.Common; using UnitTests.Validation.Setup; diff --git a/identity-server/test/IdentityServer.UnitTests/Endpoints/Results/EndSessionResultTests.cs b/identity-server/test/IdentityServer.UnitTests/Endpoints/Results/EndSessionResultTests.cs index aece7cd96..1f8510cdc 100644 --- a/identity-server/test/IdentityServer.UnitTests/Endpoints/Results/EndSessionResultTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Endpoints/Results/EndSessionResultTests.cs @@ -9,7 +9,6 @@ using Duende.IdentityServer.Services; using Duende.IdentityServer.Validation; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.WebUtilities; -using Microsoft.Extensions.Time.Testing; using UnitTests.Common; namespace UnitTests.Endpoints.Results; diff --git a/identity-server/test/IdentityServer.UnitTests/Extensions/HttpContextExtensionsTests.cs b/identity-server/test/IdentityServer.UnitTests/Extensions/HttpContextExtensionsTests.cs index 65f1a8401..5462974be 100644 --- a/identity-server/test/IdentityServer.UnitTests/Extensions/HttpContextExtensionsTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Extensions/HttpContextExtensionsTests.cs @@ -11,7 +11,6 @@ using Duende.IdentityServer.Services; using Duende.IdentityServer.Stores; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Time.Testing; using UnitTests.Common; namespace UnitTests.Extensions; diff --git a/identity-server/test/IdentityServer.UnitTests/Extensions/IResourceStoreExtensionsTests.cs b/identity-server/test/IdentityServer.UnitTests/Extensions/IResourceStoreExtensionsTests.cs index 2e788d49c..97a733925 100644 --- a/identity-server/test/IdentityServer.UnitTests/Extensions/IResourceStoreExtensionsTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Extensions/IResourceStoreExtensionsTests.cs @@ -148,15 +148,15 @@ public class IResourceStoreExtensionsTests public List ApiResources { get; set; } = new List(); public List ApiScopes { get; set; } = new List(); - public Task> FindApiResourcesByNameAsync(IEnumerable names, Ct _) + public Task> FindApiResourcesByNameAsync(IEnumerable names, Ct _) { var apis = from a in ApiResources where names.Contains(a.Name) select a; - return Task.FromResult(apis); + return Task.FromResult>(apis.ToArray()); } - public Task> FindApiResourcesByScopeNameAsync(IEnumerable names, Ct _) + public Task> FindApiResourcesByScopeNameAsync(IEnumerable names, Ct _) { ArgumentNullException.ThrowIfNull(names); @@ -164,10 +164,10 @@ public class IResourceStoreExtensionsTests where a.Scopes.Any(x => names.Contains(x)) select a; - return Task.FromResult(api); + return Task.FromResult>(api.ToArray()); } - public Task> FindIdentityResourcesByScopeNameAsync(IEnumerable names, Ct _) + public Task> FindIdentityResourcesByScopeNameAsync(IEnumerable names, Ct _) { ArgumentNullException.ThrowIfNull(names); @@ -175,15 +175,15 @@ public class IResourceStoreExtensionsTests where names.Contains(i.Name) select i; - return Task.FromResult(identity); + return Task.FromResult>(identity.ToArray()); } - public Task> FindApiScopesByNameAsync(IEnumerable scopeNames, Ct _) + public Task> FindApiScopesByNameAsync(IEnumerable scopeNames, Ct _) { var q = from x in ApiScopes where scopeNames.Contains(x.Name) select x; - return Task.FromResult(q); + return Task.FromResult>(q.ToArray()); } public Task GetAllResourcesAsync(Ct _) diff --git a/identity-server/test/IdentityServer.UnitTests/Extensions/ISamlServiceProviderStoreExtensionsTests.cs b/identity-server/test/IdentityServer.UnitTests/Extensions/ISamlServiceProviderStoreExtensionsTests.cs deleted file mode 100644 index da1db26c4..000000000 --- a/identity-server/test/IdentityServer.UnitTests/Extensions/ISamlServiceProviderStoreExtensionsTests.cs +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -#nullable enable -using System.Runtime.CompilerServices; -using Duende.IdentityServer.Models; -using Duende.IdentityServer.Stores; - -namespace UnitTests.Extensions; - -public class ISamlServiceProviderStoreExtensionsTests -{ - private readonly Ct _ct = TestContext.Current.CancellationToken; - - [Fact] - public async Task FindEnabledSamlServiceProviderByEntityIdAsync_WhenSpIsEnabled_ShouldReturnSp() - { - var sp = new SamlServiceProvider { EntityId = "https://sp.example.com", Enabled = true }; - var store = new StubSamlServiceProviderStore(sp); - - var result = await store.FindEnabledSamlServiceProviderByEntityIdAsync(sp.EntityId, _ct); - - result.ShouldNotBeNull(); - result.EntityId.ShouldBe(sp.EntityId); - } - - [Fact] - public async Task FindEnabledSamlServiceProviderByEntityIdAsync_WhenSpIsDisabled_ShouldReturnNull() - { - var sp = new SamlServiceProvider { EntityId = "https://sp.example.com", Enabled = false }; - var store = new StubSamlServiceProviderStore(sp); - - var result = await store.FindEnabledSamlServiceProviderByEntityIdAsync(sp.EntityId, _ct); - - result.ShouldBeNull(); - } - - [Fact] - public async Task FindEnabledSamlServiceProviderByEntityIdAsync_WhenSpNotFound_ShouldReturnNull() - { - var store = new StubSamlServiceProviderStore(null); - - var result = await store.FindEnabledSamlServiceProviderByEntityIdAsync("https://notfound.example.com", _ct); - - result.ShouldBeNull(); - } - - private class StubSamlServiceProviderStore(SamlServiceProvider? sp) : ISamlServiceProviderStore - { - public Task FindByEntityIdAsync(string entityId, Ct _) => Task.FromResult(sp); - - public async IAsyncEnumerable GetAllSamlServiceProvidersAsync([EnumeratorCancellation] Ct _) - { - if (sp != null) - { - yield return sp; - } - } - } -} diff --git a/identity-server/test/IdentityServer.UnitTests/Extensions/IdentityServerBuilderExtensionsCacheStoreTests.cs b/identity-server/test/IdentityServer.UnitTests/Extensions/IdentityServerBuilderExtensionsCacheStoreTests.cs index 19f50ab1a..c2c39bbdd 100644 --- a/identity-server/test/IdentityServer.UnitTests/Extensions/IdentityServerBuilderExtensionsCacheStoreTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Extensions/IdentityServerBuilderExtensionsCacheStoreTests.cs @@ -22,15 +22,15 @@ public class IdentityServerBuilderExtensionsCacheStoreTests private class CustomResourceStore : IResourceStore { - public Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames, Ct _) => throw new System.NotImplementedException(); + public Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames, Ct _) => throw new System.NotImplementedException(); - public Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames, Ct _) => throw new System.NotImplementedException(); + public Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames, Ct _) => throw new System.NotImplementedException(); - public Task> FindApiResourcesByNameAsync(IEnumerable names, Ct _) => throw new System.NotImplementedException(); + public Task> FindApiResourcesByNameAsync(IEnumerable names, Ct _) => throw new System.NotImplementedException(); public Task GetAllResourcesAsync(Ct _) => throw new System.NotImplementedException(); - public Task> FindApiScopesByNameAsync(IEnumerable scopeNames, Ct _) => throw new System.NotImplementedException(); + public Task> FindApiScopesByNameAsync(IEnumerable scopeNames, Ct _) => throw new System.NotImplementedException(); } [Fact] diff --git a/identity-server/test/IdentityServer.UnitTests/Hosting/EndpointRouterTests.cs b/identity-server/test/IdentityServer.UnitTests/Hosting/EndpointRouterTests.cs index 7900846db..79584f5bc 100644 --- a/identity-server/test/IdentityServer.UnitTests/Hosting/EndpointRouterTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Hosting/EndpointRouterTests.cs @@ -9,7 +9,6 @@ using Duende.IdentityServer.Licensing.V2; using Duende.IdentityServer.Logging; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Time.Testing; using UnitTests.Common; namespace UnitTests.Hosting; diff --git a/identity-server/test/IdentityServer.UnitTests/IdentityServer.UnitTests.csproj b/identity-server/test/IdentityServer.UnitTests/IdentityServer.UnitTests.csproj index 158349f66..f0802e128 100644 --- a/identity-server/test/IdentityServer.UnitTests/IdentityServer.UnitTests.csproj +++ b/identity-server/test/IdentityServer.UnitTests/IdentityServer.UnitTests.csproj @@ -1,19 +1,14 @@ - net10.0 - - - - + - Always @@ -22,20 +17,16 @@ Always - - - - diff --git a/identity-server/test/IdentityServer.UnitTests/Licensing/v2/LicenseExpirationCheckerTests.cs b/identity-server/test/IdentityServer.UnitTests/Licensing/v2/LicenseExpirationCheckerTests.cs index c36de4c6c..7b3ab9d0c 100644 --- a/identity-server/test/IdentityServer.UnitTests/Licensing/v2/LicenseExpirationCheckerTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Licensing/v2/LicenseExpirationCheckerTests.cs @@ -5,7 +5,6 @@ using Duende.IdentityServer.Configuration; using Duende.IdentityServer.Licensing.V2; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Testing; -using Microsoft.Extensions.Time.Testing; namespace IdentityServer.UnitTests.Licensing.V2; diff --git a/identity-server/test/IdentityServer.UnitTests/Mappers/SamlServiceProviderMappersTests.cs b/identity-server/test/IdentityServer.UnitTests/Mappers/SamlServiceProviderMappersTests.cs deleted file mode 100644 index 4a6efe2d2..000000000 --- a/identity-server/test/IdentityServer.UnitTests/Mappers/SamlServiceProviderMappersTests.cs +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -using Duende.IdentityServer.EntityFramework.Mappers; -using Duende.IdentityServer.Models; -using Models = Duende.IdentityServer.Models; - -namespace IdentityServer.UnitTests.Mappers; - -public class SamlServiceProviderMappersTests -{ - private static X509Certificate2 CreateSelfSignedCert() - { - using var rsa = RSA.Create(2048); - var request = new CertificateRequest( - "CN=Test", - rsa, - HashAlgorithmName.SHA256, - RSASignaturePadding.Pkcs1); - return request.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddYears(1)); - } - - [Fact] - public void Can_Map_minimal_sp() - { - var model = new Models.SamlServiceProvider - { - EntityId = "https://sp.example.com", - AssertionConsumerServiceUrls = new HashSet { new Uri("https://sp.example.com/acs") } - }; - - var entity = model.ToEntity(); - var roundTripped = entity.ToModel(); - - roundTripped.ShouldNotBeNull(); - entity.ShouldNotBeNull(); - roundTripped.EntityId.ShouldBe(model.EntityId); - } - - [Fact] - public void EntityId_maps_correctly() - { - var model = new Models.SamlServiceProvider { EntityId = "https://sp.example.com" }; - - var entity = model.ToEntity(); - - entity.EntityId.ShouldBe("https://sp.example.com"); - entity.ToModel().EntityId.ShouldBe("https://sp.example.com"); - } - - [Fact] - public void Enabled_maps_correctly() - { - var model = new Models.SamlServiceProvider { EntityId = "x", Enabled = false }; - - var entity = model.ToEntity(); - var roundTripped = entity.ToModel(); - - entity.Enabled.ShouldBeFalse(); - roundTripped.Enabled.ShouldBeFalse(); - } - - [Fact] - public void TimeSpan_ClockSkew_maps_to_ticks_and_back() - { - var ts = TimeSpan.FromMinutes(5); - var model = new Models.SamlServiceProvider { EntityId = "x", ClockSkew = ts }; - - var entity = model.ToEntity(); - var roundTripped = entity.ToModel(); - - entity.ClockSkewTicks.ShouldBe(ts.Ticks); - roundTripped.ClockSkew.ShouldBe(ts); - } - - [Fact] - public void Null_TimeSpan_ClockSkew_maps_to_null() - { - var model = new Models.SamlServiceProvider { EntityId = "x", ClockSkew = null }; - - var entity = model.ToEntity(); - var roundTripped = entity.ToModel(); - - entity.ClockSkewTicks.ShouldBeNull(); - roundTripped.ClockSkew.ShouldBeNull(); - } - - [Fact] - public void TimeSpan_RequestMaxAge_maps_to_ticks_and_back() - { - var ts = TimeSpan.FromSeconds(300); - var model = new Models.SamlServiceProvider { EntityId = "x", RequestMaxAge = ts }; - - var entity = model.ToEntity(); - var roundTripped = entity.ToModel(); - - entity.RequestMaxAgeTicks.ShouldBe(ts.Ticks); - roundTripped.RequestMaxAge.ShouldBe(ts); - } - - [Fact] - public void ACS_urls_map_correctly() - { - var urls = new HashSet - { - new Uri("https://sp.example.com/acs1"), - new Uri("https://sp.example.com/acs2") - }; - var model = new Models.SamlServiceProvider { EntityId = "x", AssertionConsumerServiceUrls = urls }; - - var entity = model.ToEntity(); - var roundTripped = entity.ToModel(); - - entity.AssertionConsumerServiceUrls.Count.ShouldBe(2); - entity.AssertionConsumerServiceUrls.ShouldContain(a => a.Url == "https://sp.example.com/acs1"); - entity.AssertionConsumerServiceUrls.ShouldContain(a => a.Url == "https://sp.example.com/acs2"); - - roundTripped.AssertionConsumerServiceUrls.Count.ShouldBe(2); - roundTripped.AssertionConsumerServiceUrls.ShouldContain(u => u.AbsoluteUri == "https://sp.example.com/acs1"); - roundTripped.AssertionConsumerServiceUrls.ShouldContain(u => u.AbsoluteUri == "https://sp.example.com/acs2"); - } - - [Fact] - public void SamlEndpointType_SingleLogoutServiceUrl_maps_correctly() - { - var endpoint = new SamlEndpointType - { - Location = new Uri("https://sp.example.com/slo"), - Binding = SamlBinding.HttpPost - }; - var model = new Models.SamlServiceProvider { EntityId = "x", SingleLogoutServiceUrl = endpoint }; - - var entity = model.ToEntity(); - var roundTripped = entity.ToModel(); - - entity.SingleLogoutServiceUrl.ShouldBe("https://sp.example.com/slo"); - entity.SingleLogoutServiceBinding.ShouldBe((int)SamlBinding.HttpPost); - - roundTripped.SingleLogoutServiceUrl.ShouldNotBeNull(); - roundTripped.SingleLogoutServiceUrl!.Location.AbsoluteUri.ShouldBe("https://sp.example.com/slo"); - roundTripped.SingleLogoutServiceUrl.Binding.ShouldBe(SamlBinding.HttpPost); - } - - [Fact] - public void Null_SingleLogoutServiceUrl_maps_correctly() - { - var model = new Models.SamlServiceProvider { EntityId = "x", SingleLogoutServiceUrl = null }; - - var entity = model.ToEntity(); - var roundTripped = entity.ToModel(); - - entity.SingleLogoutServiceUrl.ShouldBeNull(); - entity.SingleLogoutServiceBinding.ShouldBeNull(); - roundTripped.SingleLogoutServiceUrl.ShouldBeNull(); - } - - [Fact] - public void Signing_certificates_map_to_base64_and_back() - { - var cert = CreateSelfSignedCert(); - var model = new Models.SamlServiceProvider - { - EntityId = "x", - SigningCertificates = new List { cert } - }; - - var entity = model.ToEntity(); - var roundTripped = entity.ToModel(); - - entity.SigningCertificates.Count.ShouldBe(1); - entity.SigningCertificates[0].Data.ShouldBe(Convert.ToBase64String(cert.RawData)); - - roundTripped.SigningCertificates!.Count.ShouldBe(1); - roundTripped.SigningCertificates.First().RawData.ShouldBe(cert.RawData); - } - - [Fact] - public void Encryption_certificates_map_to_base64_and_back() - { - var cert = CreateSelfSignedCert(); - var model = new Models.SamlServiceProvider - { - EntityId = "x", - EncryptionCertificates = new List { cert } - }; - - var entity = model.ToEntity(); - var roundTripped = entity.ToModel(); - - entity.EncryptionCertificates.Count.ShouldBe(1); - entity.EncryptionCertificates[0].Data.ShouldBe(Convert.ToBase64String(cert.RawData)); - - roundTripped.EncryptionCertificates!.Count.ShouldBe(1); - roundTripped.EncryptionCertificates.First().RawData.ShouldBe(cert.RawData); - } - - [Fact] - public void ClaimMappings_map_correctly() - { - var model = new Models.SamlServiceProvider - { - EntityId = "x", - ClaimMappings = new Dictionary - { - { "department", "businessUnit" }, - { "email", "mail" } - } - }; - - var entity = model.ToEntity(); - var roundTripped = entity.ToModel(); - - entity.ClaimMappings.Count.ShouldBe(2); - entity.ClaimMappings.ShouldContain(m => m.ClaimType == "department" && m.SamlAttributeName == "businessUnit"); - entity.ClaimMappings.ShouldContain(m => m.ClaimType == "email" && m.SamlAttributeName == "mail"); - - roundTripped.ClaimMappings.Count.ShouldBe(2); - roundTripped.ClaimMappings["department"].ShouldBe("businessUnit"); - roundTripped.ClaimMappings["email"].ShouldBe("mail"); - } - - [Fact] - public void SigningBehavior_maps_correctly() - { - var model = new Models.SamlServiceProvider - { - EntityId = "x", - SigningBehavior = SamlSigningBehavior.SignBoth - }; - - var entity = model.ToEntity(); - var roundTripped = entity.ToModel(); - - entity.SigningBehavior.ShouldBe((int)SamlSigningBehavior.SignBoth); - roundTripped.SigningBehavior.ShouldBe(SamlSigningBehavior.SignBoth); - } - - [Fact] - public void Null_SigningBehavior_maps_correctly() - { - var model = new Models.SamlServiceProvider { EntityId = "x", SigningBehavior = null }; - - var entity = model.ToEntity(); - var roundTripped = entity.ToModel(); - - entity.SigningBehavior.ShouldBeNull(); - roundTripped.SigningBehavior.ShouldBeNull(); - } - - [Fact] - public void AssertionConsumerServiceBinding_enum_maps_correctly() - { - var model = new Models.SamlServiceProvider - { - EntityId = "x", - AssertionConsumerServiceBinding = SamlBinding.HttpPost - }; - - var entity = model.ToEntity(); - var roundTripped = entity.ToModel(); - - entity.AssertionConsumerServiceBinding.ShouldBe((int)SamlBinding.HttpPost); - roundTripped.AssertionConsumerServiceBinding.ShouldBe(SamlBinding.HttpPost); - } -} diff --git a/identity-server/test/IdentityServer.UnitTests/ResponseHandling/AuthorizeInteractionResponseGenerator/AuthorizeInteractionResponseGeneratorTests.cs b/identity-server/test/IdentityServer.UnitTests/ResponseHandling/AuthorizeInteractionResponseGenerator/AuthorizeInteractionResponseGeneratorTests.cs index 694e61831..1c090ad37 100644 --- a/identity-server/test/IdentityServer.UnitTests/ResponseHandling/AuthorizeInteractionResponseGenerator/AuthorizeInteractionResponseGeneratorTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/ResponseHandling/AuthorizeInteractionResponseGenerator/AuthorizeInteractionResponseGeneratorTests.cs @@ -6,7 +6,6 @@ using Duende.IdentityServer; using Duende.IdentityServer.Configuration; using Duende.IdentityServer.Models; using Duende.IdentityServer.Validation; -using Microsoft.Extensions.Time.Testing; using UnitTests.Common; using static Duende.IdentityModel.OidcConstants; diff --git a/identity-server/test/IdentityServer.UnitTests/ResponseHandling/AuthorizeInteractionResponseGenerator/AuthorizeInteractionResponseGeneratorTests_Consent.cs b/identity-server/test/IdentityServer.UnitTests/ResponseHandling/AuthorizeInteractionResponseGenerator/AuthorizeInteractionResponseGeneratorTests_Consent.cs index f6455502b..bd7e154c0 100644 --- a/identity-server/test/IdentityServer.UnitTests/ResponseHandling/AuthorizeInteractionResponseGenerator/AuthorizeInteractionResponseGeneratorTests_Consent.cs +++ b/identity-server/test/IdentityServer.UnitTests/ResponseHandling/AuthorizeInteractionResponseGenerator/AuthorizeInteractionResponseGeneratorTests_Consent.cs @@ -7,7 +7,6 @@ using Duende.IdentityModel; using Duende.IdentityServer.Configuration; using Duende.IdentityServer.Models; using Duende.IdentityServer.Validation; -using Microsoft.Extensions.Time.Testing; using UnitTests.Common; namespace UnitTests.ResponseHandling.AuthorizeInteractionResponseGenerator; diff --git a/identity-server/test/IdentityServer.UnitTests/ResponseHandling/AuthorizeInteractionResponseGenerator/AuthorizeInteractionResponseGeneratorTests_Custom.cs b/identity-server/test/IdentityServer.UnitTests/ResponseHandling/AuthorizeInteractionResponseGenerator/AuthorizeInteractionResponseGeneratorTests_Custom.cs index 48692cb6f..97b1d042f 100644 --- a/identity-server/test/IdentityServer.UnitTests/ResponseHandling/AuthorizeInteractionResponseGenerator/AuthorizeInteractionResponseGeneratorTests_Custom.cs +++ b/identity-server/test/IdentityServer.UnitTests/ResponseHandling/AuthorizeInteractionResponseGenerator/AuthorizeInteractionResponseGeneratorTests_Custom.cs @@ -9,7 +9,6 @@ using Duende.IdentityServer.ResponseHandling; using Duende.IdentityServer.Services; using Duende.IdentityServer.Validation; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Time.Testing; using UnitTests.Common; using static Duende.IdentityModel.OidcConstants; diff --git a/identity-server/test/IdentityServer.UnitTests/ResponseHandling/AuthorizeInteractionResponseGenerator/AuthorizeInteractionResponseGeneratorTests_Login.cs b/identity-server/test/IdentityServer.UnitTests/ResponseHandling/AuthorizeInteractionResponseGenerator/AuthorizeInteractionResponseGeneratorTests_Login.cs index a7ff911aa..9fd130109 100644 --- a/identity-server/test/IdentityServer.UnitTests/ResponseHandling/AuthorizeInteractionResponseGenerator/AuthorizeInteractionResponseGeneratorTests_Login.cs +++ b/identity-server/test/IdentityServer.UnitTests/ResponseHandling/AuthorizeInteractionResponseGenerator/AuthorizeInteractionResponseGeneratorTests_Login.cs @@ -8,7 +8,6 @@ using Duende.IdentityServer; using Duende.IdentityServer.Configuration; using Duende.IdentityServer.Models; using Duende.IdentityServer.Validation; -using Microsoft.Extensions.Time.Testing; using UnitTests.Common; namespace UnitTests.ResponseHandling.AuthorizeInteractionResponseGenerator; diff --git a/identity-server/test/IdentityServer.UnitTests/ResponseHandling/DeviceAuthorizationResponseGeneratorTests.cs b/identity-server/test/IdentityServer.UnitTests/ResponseHandling/DeviceAuthorizationResponseGeneratorTests.cs index a7a0de4cd..99a188efc 100644 --- a/identity-server/test/IdentityServer.UnitTests/ResponseHandling/DeviceAuthorizationResponseGeneratorTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/ResponseHandling/DeviceAuthorizationResponseGeneratorTests.cs @@ -10,7 +10,6 @@ using Duende.IdentityServer.Services.Default; using Duende.IdentityServer.Stores; using Duende.IdentityServer.Validation; using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Time.Testing; using UnitTests.Common; namespace UnitTests.ResponseHandling; diff --git a/identity-server/test/IdentityServer.UnitTests/Saml/SamlAssertionEncryptorTests.cs b/identity-server/test/IdentityServer.UnitTests/Saml/SamlAssertionEncryptorTests.cs index 40a07ac1c..4399d7657 100644 --- a/identity-server/test/IdentityServer.UnitTests/Saml/SamlAssertionEncryptorTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Saml/SamlAssertionEncryptorTests.cs @@ -7,7 +7,6 @@ using System.Xml.Linq; using Duende.IdentityServer.Internal.Saml.Infrastructure; using Duende.IdentityServer.Models; using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Time.Testing; namespace UnitTests.Saml; diff --git a/identity-server/test/IdentityServer.UnitTests/Saml/SamlFrontChannelLogoutRequestBuilderTests.cs b/identity-server/test/IdentityServer.UnitTests/Saml/SamlFrontChannelLogoutRequestBuilderTests.cs index d45406711..395dfb462 100644 --- a/identity-server/test/IdentityServer.UnitTests/Saml/SamlFrontChannelLogoutRequestBuilderTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Saml/SamlFrontChannelLogoutRequestBuilderTests.cs @@ -11,7 +11,6 @@ using Duende.IdentityServer.Internal.Saml.Infrastructure; using Duende.IdentityServer.Internal.Saml.SingleLogout; using Duende.IdentityServer.Models; using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Time.Testing; namespace UnitTests.Saml; diff --git a/identity-server/test/IdentityServer.UnitTests/Saml/SamlLogoutCallbackProcessorTests.cs b/identity-server/test/IdentityServer.UnitTests/Saml/SamlLogoutCallbackProcessorTests.cs index 1fbd553fb..e84617473 100644 --- a/identity-server/test/IdentityServer.UnitTests/Saml/SamlLogoutCallbackProcessorTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Saml/SamlLogoutCallbackProcessorTests.cs @@ -2,14 +2,12 @@ // See LICENSE in the project root for license information. #nullable enable -using System.Runtime.CompilerServices; using Duende.IdentityServer.Internal.Saml.SingleLogout; using Duende.IdentityServer.Models; using Duende.IdentityServer.Saml.Models; using Duende.IdentityServer.Services; using Duende.IdentityServer.Stores; using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Time.Testing; namespace UnitTests.Saml; @@ -263,14 +261,6 @@ public class SamlLogoutCallbackProcessorTests ServiceProviders.TryGetValue(entityId, out var sp); return Task.FromResult(sp); } - - public async IAsyncEnumerable GetAllSamlServiceProvidersAsync([EnumeratorCancellation] Ct _) - { - foreach (var sp in ServiceProviders.Values) - { - yield return sp; - } - } } private class MockIssuerNameService : IIssuerNameService diff --git a/identity-server/test/IdentityServer.UnitTests/Saml/SamlLogoutNotificationServiceTests.cs b/identity-server/test/IdentityServer.UnitTests/Saml/SamlLogoutNotificationServiceTests.cs index c8a27d524..9b93c2e36 100644 --- a/identity-server/test/IdentityServer.UnitTests/Saml/SamlLogoutNotificationServiceTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Saml/SamlLogoutNotificationServiceTests.cs @@ -9,7 +9,6 @@ using Duende.IdentityServer.Models; using Duende.IdentityServer.Saml.Models; using Duende.IdentityServer.Stores; using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Time.Testing; using UnitTests.Common; using UnitTests.Validation.Setup; using SamlBinding = Duende.IdentityServer.Models.SamlBinding; diff --git a/identity-server/test/IdentityServer.UnitTests/Saml/SamlSigninStateIdCookieTests.cs b/identity-server/test/IdentityServer.UnitTests/Saml/SamlSigninStateIdCookieTests.cs new file mode 100644 index 000000000..d1c9026ba --- /dev/null +++ b/identity-server/test/IdentityServer.UnitTests/Saml/SamlSigninStateIdCookieTests.cs @@ -0,0 +1,75 @@ +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + +using Duende.IdentityServer.Configuration; +using Duende.IdentityServer.Internal.Saml.SingleSignin; +using Duende.IdentityServer.Internal.Saml.SingleSignin.Models; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Options; + +namespace UnitTests.Saml; + +public class SamlSigninStateIdCookieTests +{ + private static SamlSigninStateIdCookie CreateCookie(HttpContext httpContext, SamlOptions options = null) + { + var accessor = new StubHttpContextAccessor(httpContext); + var samlOptions = options ?? new SamlOptions(); + return new SamlSigninStateIdCookie(accessor, Options.Create(samlOptions)); + } + + [Fact] + public void StoreSamlSigninStateId_UsesDefaultCookieName() + { + var httpContext = new DefaultHttpContext(); + var cookie = CreateCookie(httpContext); + + cookie.StoreSamlSigninStateId(StateId.NewId()); + + httpContext.Response.Headers.SetCookie.ToString().ShouldContain("__IdsSvr_SamlSigninState="); + } + + [Fact] + public void StoreSamlSigninStateId_UsesConfiguredCookieName() + { + var httpContext = new DefaultHttpContext(); + var options = new SamlOptions { SigninStateCookieName = "custom_cookie" }; + var cookie = CreateCookie(httpContext, options); + + cookie.StoreSamlSigninStateId(StateId.NewId()); + + httpContext.Response.Headers.SetCookie.ToString().ShouldContain("custom_cookie="); + } + + [Fact] + public void TryGetSamlSigninStateId_UsesConfiguredCookieName() + { + var httpContext = new DefaultHttpContext(); + var stateId = StateId.NewId(); + httpContext.Request.Headers.Cookie = $"custom_cookie={stateId}"; + + var options = new SamlOptions { SigninStateCookieName = "custom_cookie" }; + var cookie = CreateCookie(httpContext, options); + + var result = cookie.TryGetSamlSigninStateId(out _); + + result.ShouldBeTrue(); + } + + [Fact] + public void ClearAuthenticationState_UsesConfiguredCookieName() + { + var httpContext = new DefaultHttpContext(); + var options = new SamlOptions { SigninStateCookieName = "custom_cookie" }; + var cookie = CreateCookie(httpContext, options); + + cookie.ClearAuthenticationState(); + + httpContext.Response.Headers.SetCookie.ToString().ShouldContain("custom_cookie="); + } + + private sealed class StubHttpContextAccessor(HttpContext httpContext) : IHttpContextAccessor + { + public HttpContext HttpContext { get; set; } = httpContext; + } +} diff --git a/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultBackChannelLogoutServiceTests.cs b/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultBackChannelLogoutServiceTests.cs index b6ace2bc0..182201cd2 100644 --- a/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultBackChannelLogoutServiceTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultBackChannelLogoutServiceTests.cs @@ -8,7 +8,6 @@ using Duende.IdentityServer; using Duende.IdentityServer.Configuration; using Duende.IdentityServer.Services; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Time.Testing; using Microsoft.IdentityModel.Tokens; using UnitTests.Common; using UnitTests.Validation.Setup; diff --git a/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultBackchannelAuthenticationInteractionServiceTests.cs b/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultBackchannelAuthenticationInteractionServiceTests.cs index 930169ac1..94bf3dec9 100644 --- a/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultBackchannelAuthenticationInteractionServiceTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultBackchannelAuthenticationInteractionServiceTests.cs @@ -7,7 +7,6 @@ using Duende.IdentityServer; using Duende.IdentityServer.Models; using Duende.IdentityServer.Services; using Duende.IdentityServer.Stores; -using Microsoft.Extensions.Time.Testing; using UnitTests.Common; namespace UnitTests.Services.Default; diff --git a/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultConsentServiceTests.cs b/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultConsentServiceTests.cs index c800ce871..5fe4e6294 100644 --- a/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultConsentServiceTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultConsentServiceTests.cs @@ -9,7 +9,6 @@ using Duende.IdentityServer.Extensions; using Duende.IdentityServer.Models; using Duende.IdentityServer.Services; using Duende.IdentityServer.Validation; -using Microsoft.Extensions.Time.Testing; using UnitTests.Common; namespace UnitTests.Services.Default; diff --git a/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultEventServiceTests.cs b/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultEventServiceTests.cs index dbe544bd2..09b1e5a43 100644 --- a/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultEventServiceTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultEventServiceTests.cs @@ -3,7 +3,6 @@ using Duende.IdentityServer.Configuration; using Duende.IdentityServer.Events; -using Microsoft.Extensions.Time.Testing; using UnitTests.Common; namespace UnitTests.Services.Default; diff --git a/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultIdentityServerInteractionServiceTests.cs b/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultIdentityServerInteractionServiceTests.cs index 9fe6a01ac..5104af65f 100644 --- a/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultIdentityServerInteractionServiceTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultIdentityServerInteractionServiceTests.cs @@ -10,7 +10,6 @@ using Duende.IdentityServer.Services; using Duende.IdentityServer.Stores; using Duende.IdentityServer.Validation; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Time.Testing; using UnitTests.Common; namespace UnitTests.Services.Default; diff --git a/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultPersistedGrantServiceTests.cs b/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultPersistedGrantServiceTests.cs index 2f069e823..e65a9715d 100644 --- a/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultPersistedGrantServiceTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultPersistedGrantServiceTests.cs @@ -576,7 +576,7 @@ public class DefaultPersistedGrantServiceTests public CorruptingPersistedGrantStore(IPersistedGrantStore inner) => _inner = inner; - public async Task> GetAllAsync(PersistedGrantFilter filter, Ct ct) + public async Task> GetAllAsync(PersistedGrantFilter filter, Ct ct) { var items = await _inner.GetAllAsync(filter, ct); if (ClientIdToCorrupt != null) diff --git a/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultRefreshTokenServiceTests.cs b/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultRefreshTokenServiceTests.cs index 4f32bd9fd..6345f49f8 100644 --- a/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultRefreshTokenServiceTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultRefreshTokenServiceTests.cs @@ -7,7 +7,6 @@ using Duende.IdentityServer.Models; using Duende.IdentityServer.Services; using Duende.IdentityServer.Stores; using Duende.IdentityServer.Stores.Serialization; -using Microsoft.Extensions.Time.Testing; using UnitTests.Common; using UnitTests.Validation.Setup; diff --git a/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultTokenServiceTests.cs b/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultTokenServiceTests.cs index af95c3669..fc030ee2d 100644 --- a/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultTokenServiceTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultTokenServiceTests.cs @@ -9,7 +9,6 @@ using Duende.IdentityServer.Models; using Duende.IdentityServer.Services; using Duende.IdentityServer.Validation; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Time.Testing; using UnitTests.Common; namespace UnitTests.Services.Default; diff --git a/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultUserSessionTests.cs b/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultUserSessionTests.cs index 68f9a050e..7ebe553b4 100644 --- a/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultUserSessionTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Services/Default/DefaultUserSessionTests.cs @@ -10,7 +10,6 @@ using Duende.IdentityServer.Extensions; using Duende.IdentityServer.Services; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Time.Testing; using UnitTests.Common; namespace UnitTests.Services.Default; diff --git a/identity-server/test/IdentityServer.UnitTests/Services/Default/DistributedDeviceFlowThrottlingServiceTests.cs b/identity-server/test/IdentityServer.UnitTests/Services/Default/DistributedDeviceFlowThrottlingServiceTests.cs index 679465854..ae3f04fef 100644 --- a/identity-server/test/IdentityServer.UnitTests/Services/Default/DistributedDeviceFlowThrottlingServiceTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Services/Default/DistributedDeviceFlowThrottlingServiceTests.cs @@ -8,7 +8,6 @@ using Duende.IdentityServer.Models; using Duende.IdentityServer.Services; using Duende.IdentityServer.Stores; using Microsoft.Extensions.Caching.Distributed; -using Microsoft.Extensions.Time.Testing; namespace UnitTests.Services.Default; diff --git a/identity-server/test/IdentityServer.UnitTests/Services/Default/KeyManagement/InMemoryKeyStoreCacheTests.cs b/identity-server/test/IdentityServer.UnitTests/Services/Default/KeyManagement/InMemoryKeyStoreCacheTests.cs index efab38136..7538288ef 100644 --- a/identity-server/test/IdentityServer.UnitTests/Services/Default/KeyManagement/InMemoryKeyStoreCacheTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Services/Default/KeyManagement/InMemoryKeyStoreCacheTests.cs @@ -3,7 +3,6 @@ using Duende.IdentityServer.Services.KeyManagement; -using Microsoft.Extensions.Time.Testing; namespace UnitTests.Services.Default.KeyManagement; diff --git a/identity-server/test/IdentityServer.UnitTests/Services/Default/KeyManagement/KeyManagerTests.cs b/identity-server/test/IdentityServer.UnitTests/Services/Default/KeyManagement/KeyManagerTests.cs index 4ce844018..569738658 100644 --- a/identity-server/test/IdentityServer.UnitTests/Services/Default/KeyManagement/KeyManagerTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Services/Default/KeyManagement/KeyManagerTests.cs @@ -9,7 +9,6 @@ using Duende.IdentityServer.Internal; using Duende.IdentityServer.Models; using Duende.IdentityServer.Services.KeyManagement; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Time.Testing; using UnitTests.Validation.Setup; namespace UnitTests.Services.Default.KeyManagement; diff --git a/identity-server/test/IdentityServer.UnitTests/Services/Default/KeyManagement/MockSigningKeyStore.cs b/identity-server/test/IdentityServer.UnitTests/Services/Default/KeyManagement/MockSigningKeyStore.cs index 46260dc80..a311e63a6 100644 --- a/identity-server/test/IdentityServer.UnitTests/Services/Default/KeyManagement/MockSigningKeyStore.cs +++ b/identity-server/test/IdentityServer.UnitTests/Services/Default/KeyManagement/MockSigningKeyStore.cs @@ -23,10 +23,10 @@ internal class MockSigningKeyStore : ISigningKeyStore return Task.CompletedTask; } - public Task> LoadKeysAsync(Ct _) + public Task> LoadKeysAsync(Ct _) { LoadKeysAsyncWasCalled = true; - return Task.FromResult>(Keys); + return Task.FromResult>(Keys); } public Task StoreKeyAsync(SerializedKey key, Ct _) diff --git a/identity-server/test/IdentityServer.UnitTests/Services/Default/KeyManagement/MockSigningKeyStoreCache.cs b/identity-server/test/IdentityServer.UnitTests/Services/Default/KeyManagement/MockSigningKeyStoreCache.cs index 4185d6900..40c269ba5 100644 --- a/identity-server/test/IdentityServer.UnitTests/Services/Default/KeyManagement/MockSigningKeyStoreCache.cs +++ b/identity-server/test/IdentityServer.UnitTests/Services/Default/KeyManagement/MockSigningKeyStoreCache.cs @@ -1,6 +1,7 @@ // Copyright (c) Duende Software. All rights reserved. // See LICENSE in the project root for license information. +#nullable enable using Duende.IdentityServer.Services.KeyManagement; @@ -8,19 +9,19 @@ namespace UnitTests.Services.Default.KeyManagement; internal class MockSigningKeyStoreCache : ISigningKeyStoreCache { - public List Cache { get; set; } = new List(); + public List? Cache { get; set; } = new List(); public bool GetKeysAsyncWasCalled { get; set; } public bool StoreKeysAsyncWasCalled { get; set; } public TimeSpan StoreKeysAsyncDuration { get; set; } - public Task> GetKeysAsync(Ct _) + public Task?> GetKeysAsync(Ct _) { GetKeysAsyncWasCalled = true; - return Task.FromResult(Cache.AsEnumerable()); + return Task.FromResult?>(Cache); } - public Task StoreKeysAsync(IEnumerable keys, TimeSpan duration, Ct _) + public Task StoreKeysAsync(IReadOnlyCollection keys, TimeSpan duration, Ct _) { StoreKeysAsyncWasCalled = true; StoreKeysAsyncDuration = duration; diff --git a/identity-server/test/IdentityServer.UnitTests/Stores/InMemorySamlServiceProviderStoreTests.cs b/identity-server/test/IdentityServer.UnitTests/Stores/InMemorySamlServiceProviderStoreTests.cs deleted file mode 100644 index 98446044b..000000000 --- a/identity-server/test/IdentityServer.UnitTests/Stores/InMemorySamlServiceProviderStoreTests.cs +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -using Duende.IdentityServer.Models; -using Duende.IdentityServer.Stores; - -namespace UnitTests.Stores; - -public class InMemorySamlServiceProviderStoreTests -{ - private readonly Ct _ct = TestContext.Current.CancellationToken; - - [Fact] - public void InMemorySamlServiceProviderStore_should_throw_if_contains_duplicate_entity_ids() - { - var sps = new List - { - new() { EntityId = "https://sp1.example.com" }, - new() { EntityId = "https://sp1.example.com" }, - new() { EntityId = "https://sp3.example.com" } - }; - - Action act = () => new InMemorySamlServiceProviderStore(sps); - act.ShouldThrow(); - } - - [Fact] - public void InMemorySamlServiceProviderStore_should_not_throw_if_no_duplicate_entity_ids() - { - var sps = new List - { - new() { EntityId = "https://sp1.example.com" }, - new() { EntityId = "https://sp2.example.com" }, - new() { EntityId = "https://sp3.example.com" } - }; - - new InMemorySamlServiceProviderStore(sps); - } - - [Fact] - public async Task FindByEntityIdAsync_should_return_sp_when_found() - { - var sps = new List - { - new() { EntityId = "https://sp1.example.com", Enabled = true }, - new() { EntityId = "https://sp2.example.com", Enabled = true } - }; - var store = new InMemorySamlServiceProviderStore(sps); - - var result = await store.FindByEntityIdAsync("https://sp1.example.com", _ct); - - result.ShouldNotBeNull(); - result.EntityId.ShouldBe("https://sp1.example.com"); - } - - [Fact] - public async Task FindByEntityIdAsync_should_return_null_when_not_found() - { - var sps = new List - { - new() { EntityId = "https://sp1.example.com", Enabled = true } - }; - var store = new InMemorySamlServiceProviderStore(sps); - - var result = await store.FindByEntityIdAsync("https://notfound.example.com", _ct); - - result.ShouldBeNull(); - } - - [Fact] - public async Task FindByEntityIdAsync_should_return_null_when_sp_is_disabled() - { - var sps = new List - { - new() { EntityId = "https://sp1.example.com", Enabled = false } - }; - var store = new InMemorySamlServiceProviderStore(sps); - - var result = await store.FindByEntityIdAsync("https://sp1.example.com", _ct); - - result.ShouldBeNull(); - } - - [Fact] - public async Task GetAllSamlServiceProvidersAsync_should_return_all_sps() - { - var sps = new List - { - new() { EntityId = "https://sp1.example.com" }, - new() { EntityId = "https://sp2.example.com" }, - new() { EntityId = "https://sp3.example.com" } - }; - var store = new InMemorySamlServiceProviderStore(sps); - - var result = new List(); - await foreach (var sp in store.GetAllSamlServiceProvidersAsync(_ct)) - { - result.Add(sp); - } - - result.ShouldNotBeNull(); - result.Count.ShouldBe(3); - result.ShouldContain(s => s.EntityId == "https://sp1.example.com"); - result.ShouldContain(s => s.EntityId == "https://sp2.example.com"); - result.ShouldContain(s => s.EntityId == "https://sp3.example.com"); - } - - [Fact] - public async Task GetAllSamlServiceProvidersAsync_should_return_empty_when_no_sps() - { - var store = new InMemorySamlServiceProviderStore([]); - - var result = new List(); - await foreach (var sp in store.GetAllSamlServiceProvidersAsync(_ct)) - { - result.Add(sp); - } - - result.ShouldNotBeNull(); - result.ShouldBeEmpty(); - } -} diff --git a/identity-server/test/IdentityServer.UnitTests/Stores/ValidatingSamlServiceProviderStoreTests.cs b/identity-server/test/IdentityServer.UnitTests/Stores/ValidatingSamlServiceProviderStoreTests.cs deleted file mode 100644 index 024f259ca..000000000 --- a/identity-server/test/IdentityServer.UnitTests/Stores/ValidatingSamlServiceProviderStoreTests.cs +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -#nullable enable - -using System.Runtime.CompilerServices; -using Duende.IdentityServer.Events; -using Duende.IdentityServer.Models; -using Duende.IdentityServer.Services; -using Duende.IdentityServer.Stores; -using Duende.IdentityServer.Validation; -using Microsoft.Extensions.Logging.Abstractions; -using UnitTests.Common; - -namespace UnitTests.Stores; - -public class ValidatingSamlServiceProviderStoreTests -{ - private readonly Ct _ct = TestContext.Current.CancellationToken; - - private readonly TestEventService _events = new(); - private readonly NullLogger> _logger = new(); - - [Fact] - public async Task FindByEntityIdAsync_WhenSpIsValid_ShouldReturnSp() - { - var sp = new SamlServiceProvider { EntityId = "https://sp1.example.com" }; - var innerStore = StubSamlServiceProviderStore.WithSp(sp); - var validator = new StubSamlServiceProviderConfigurationValidator(isValid: true); - var store = new ValidatingSamlServiceProviderStore(innerStore, validator, _events, _logger); - - var result = await store.FindByEntityIdAsync(sp.EntityId, _ct); - - result.ShouldNotBeNull(); - result.EntityId.ShouldBe(sp.EntityId); - } - - [Fact] - public async Task FindByEntityIdAsync_WhenSpIsInvalid_ShouldReturnNull() - { - var sp = new SamlServiceProvider { EntityId = "https://sp1.example.com" }; - var innerStore = StubSamlServiceProviderStore.WithSp(sp); - var validator = new StubSamlServiceProviderConfigurationValidator(isValid: false, errorMessage: "Invalid configuration"); - var store = new ValidatingSamlServiceProviderStore(innerStore, validator, _events, _logger); - - var result = await store.FindByEntityIdAsync(sp.EntityId, _ct); - - result.ShouldBeNull(); - } - - [Fact] - public async Task FindByEntityIdAsync_WhenSpIsInvalid_ShouldRaiseEvent() - { - var sp = new SamlServiceProvider { EntityId = "https://sp1.example.com" }; - var innerStore = StubSamlServiceProviderStore.WithSp(sp); - var validator = new StubSamlServiceProviderConfigurationValidator(isValid: false, errorMessage: "Invalid configuration"); - var store = new ValidatingSamlServiceProviderStore(innerStore, validator, _events, _logger); - - await store.FindByEntityIdAsync(sp.EntityId, _ct); - - _events.AssertEventWasRaised(); - } - - [Fact] - public async Task FindByEntityIdAsync_WhenSpNotFound_ShouldReturnNull() - { - var innerStore = StubSamlServiceProviderStore.Empty(); - var validator = new StubSamlServiceProviderConfigurationValidator(isValid: true); - var store = new ValidatingSamlServiceProviderStore(innerStore, validator, _events, _logger); - - var result = await store.FindByEntityIdAsync("https://notfound.example.com", _ct); - - result.ShouldBeNull(); - } - - [Fact] - public async Task GetAllSamlServiceProvidersAsync_WhenAllSpsAreValid_ShouldReturnAll() - { - var sps = new List - { - new() { EntityId = "https://sp1.example.com" }, - new() { EntityId = "https://sp2.example.com" }, - new() { EntityId = "https://sp3.example.com" } - }; - var innerStore = StubSamlServiceProviderStore.WithSps(sps); - var validator = new StubSamlServiceProviderConfigurationValidator(isValid: true); - var store = new ValidatingSamlServiceProviderStore(innerStore, validator, _events, _logger); - - var result = new List(); - await foreach (var sp in store.GetAllSamlServiceProvidersAsync(_ct)) - { - result.Add(sp); - } - - result.Count.ShouldBe(3); - result.ShouldContain(s => s.EntityId == "https://sp1.example.com"); - result.ShouldContain(s => s.EntityId == "https://sp2.example.com"); - result.ShouldContain(s => s.EntityId == "https://sp3.example.com"); - } - - [Fact] - public async Task GetAllSamlServiceProvidersAsync_WhenSomeSpsAreInvalid_ShouldReturnOnlyValid() - { - var sps = new List - { - new() { EntityId = "https://valid1.example.com" }, - new() { EntityId = "https://invalid1.example.com" }, - new() { EntityId = "https://valid2.example.com" } - }; - var innerStore = StubSamlServiceProviderStore.WithSps(sps); - var validator = new StubSamlServiceProviderConfigurationValidator( - validationFunc: sp => !sp.EntityId.Contains("invalid"), - errorMessage: "SP is invalid" - ); - var store = new ValidatingSamlServiceProviderStore(innerStore, validator, _events, _logger); - - var result = new List(); - await foreach (var sp in store.GetAllSamlServiceProvidersAsync(_ct)) - { - result.Add(sp); - } - - result.Count.ShouldBe(2); - result.ShouldContain(s => s.EntityId == "https://valid1.example.com"); - result.ShouldContain(s => s.EntityId == "https://valid2.example.com"); - result.ShouldNotContain(s => s.EntityId == "https://invalid1.example.com"); - } - - [Fact] - public async Task GetAllSamlServiceProvidersAsync_WhenSpIsInvalid_ShouldRaiseEvent() - { - var sps = new List - { - new() { EntityId = "https://invalid.example.com" } - }; - var innerStore = StubSamlServiceProviderStore.WithSps(sps); - var validator = new StubSamlServiceProviderConfigurationValidator(isValid: false, errorMessage: "Invalid configuration"); - var store = new ValidatingSamlServiceProviderStore(innerStore, validator, _events, _logger); - - var result = new List(); - await foreach (var sp in store.GetAllSamlServiceProvidersAsync(_ct)) - { - result.Add(sp); - } - - result.ShouldBeEmpty(); - _events.AssertEventWasRaised(); - } - - [Fact] - public async Task GetAllSamlServiceProvidersAsync_WhenNoSps_ShouldReturnEmpty() - { - var innerStore = StubSamlServiceProviderStore.Empty(); - var validator = new StubSamlServiceProviderConfigurationValidator(isValid: true); - var store = new ValidatingSamlServiceProviderStore(innerStore, validator, _events, _logger); - - var result = new List(); - await foreach (var sp in store.GetAllSamlServiceProvidersAsync(_ct)) - { - result.Add(sp); - } - - result.ShouldBeEmpty(); - } - - [Fact] - public async Task GetAllSamlServiceProvidersAsync_WhenAllInvalid_ShouldRaiseMultipleEvents() - { - var sps = new List - { - new() { EntityId = "https://invalid1.example.com" }, - new() { EntityId = "https://invalid2.example.com" } - }; - var innerStore = StubSamlServiceProviderStore.WithSps(sps); - var validator = new StubSamlServiceProviderConfigurationValidator(isValid: false, errorMessage: "All invalid"); - var eventService = new StubEventService(); - var store = new ValidatingSamlServiceProviderStore(innerStore, validator, eventService, _logger); - - var result = new List(); - await foreach (var sp in store.GetAllSamlServiceProvidersAsync(_ct)) - { - result.Add(sp); - } - - result.ShouldBeEmpty(); - eventService.RaisedEventCount.ShouldBe(2); - } - - private class StubSamlServiceProviderStore : ISamlServiceProviderStore - { - private readonly SamlServiceProvider? _sp; - private readonly IEnumerable _sps; - - private StubSamlServiceProviderStore(SamlServiceProvider? sp, IEnumerable sps) - { - _sp = sp; - _sps = sps; - } - - public static StubSamlServiceProviderStore Empty() => new(null, []); - public static StubSamlServiceProviderStore WithSp(SamlServiceProvider sp) => new(sp, [sp]); - public static StubSamlServiceProviderStore WithSps(IEnumerable sps) => new(sps.FirstOrDefault(), sps); - - public Task FindByEntityIdAsync(string entityId, Ct _) => Task.FromResult(_sp); - - public async IAsyncEnumerable GetAllSamlServiceProvidersAsync([EnumeratorCancellation] Ct _) - { - foreach (var sp in _sps) - { - yield return sp; - } - } - } - - private class StubSamlServiceProviderConfigurationValidator : ISamlServiceProviderConfigurationValidator - { - private readonly bool _isValid; - private readonly string? _errorMessage; - private readonly Func? _validationFunc; - - public StubSamlServiceProviderConfigurationValidator(bool isValid, string? errorMessage = null) - { - _isValid = isValid; - _errorMessage = errorMessage; - } - - public StubSamlServiceProviderConfigurationValidator(Func validationFunc, string? errorMessage = null) - { - _validationFunc = validationFunc; - _errorMessage = errorMessage; - _isValid = true; - } - - public Task ValidateAsync(SamlServiceProviderConfigurationValidationContext context) - { - var isValid = _validationFunc != null ? _validationFunc(context.ServiceProvider) : _isValid; - - if (!isValid) - { - context.SetError(_errorMessage ?? "Validation failed"); - } - - return Task.CompletedTask; - } - } - - private class StubEventService : IEventService - { - public int RaisedEventCount { get; private set; } - - public bool CanRaiseEventType(EventTypes evtType) => true; - - public Task RaiseAsync(Event evt, Ct _) - { - RaisedEventCount++; - return Task.CompletedTask; - } - } -} diff --git a/identity-server/test/IdentityServer.UnitTests/Validation/AccessTokenValidation.cs b/identity-server/test/IdentityServer.UnitTests/Validation/AccessTokenValidation.cs index ad71b819a..4dc3ac02f 100644 --- a/identity-server/test/IdentityServer.UnitTests/Validation/AccessTokenValidation.cs +++ b/identity-server/test/IdentityServer.UnitTests/Validation/AccessTokenValidation.cs @@ -7,7 +7,6 @@ using Duende.IdentityModel; using Duende.IdentityServer.Configuration; using Duende.IdentityServer.Models; using Duende.IdentityServer.Stores; -using Microsoft.Extensions.Time.Testing; using UnitTests.Common; using UnitTests.Validation.Setup; diff --git a/identity-server/test/IdentityServer.UnitTests/Validation/DPoPProofValidatorTests.cs b/identity-server/test/IdentityServer.UnitTests/Validation/DPoPProofValidatorTests.cs index 10e235640..2e1657028 100644 --- a/identity-server/test/IdentityServer.UnitTests/Validation/DPoPProofValidatorTests.cs +++ b/identity-server/test/IdentityServer.UnitTests/Validation/DPoPProofValidatorTests.cs @@ -13,7 +13,6 @@ using Duende.IdentityServer.Models; using Duende.IdentityServer.Validation; using Microsoft.AspNetCore.DataProtection; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Time.Testing; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; using UnitTests.Common; diff --git a/identity-server/test/IdentityServer.UnitTests/Validation/DefaultSamlServiceProviderConfigurationValidatorTests.cs b/identity-server/test/IdentityServer.UnitTests/Validation/DefaultSamlServiceProviderConfigurationValidatorTests.cs deleted file mode 100644 index b94055ee3..000000000 --- a/identity-server/test/IdentityServer.UnitTests/Validation/DefaultSamlServiceProviderConfigurationValidatorTests.cs +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -using Duende.IdentityServer.Models; -using Duende.IdentityServer.Validation; - -namespace UnitTests.Validation; - -public class DefaultSamlServiceProviderConfigurationValidatorTests -{ - private readonly DefaultSamlServiceProviderConfigurationValidator _validator = new(); - - private static SamlServiceProvider ValidSp() => new() - { - EntityId = "https://sp.example.com", - AssertionConsumerServiceUrls = new HashSet { new Uri("https://sp.example.com/acs") } - }; - - [Fact] - public async Task Valid_sp_should_pass_validation() - { - var sp = ValidSp(); - var ctx = new SamlServiceProviderConfigurationValidationContext(sp); - - await _validator.ValidateAsync(ctx); - - ctx.IsValid.ShouldBeTrue(); - } - - [Fact] - public async Task Missing_entity_id_should_fail() - { - var sp = ValidSp(); - sp.EntityId = ""; - var ctx = new SamlServiceProviderConfigurationValidationContext(sp); - - await _validator.ValidateAsync(ctx); - - ctx.IsValid.ShouldBeFalse(); - ctx.ErrorMessage.ShouldBe("EntityId is required."); - } - - [Fact] - public async Task Whitespace_entity_id_should_fail() - { - var sp = ValidSp(); - sp.EntityId = " "; - var ctx = new SamlServiceProviderConfigurationValidationContext(sp); - - await _validator.ValidateAsync(ctx); - - ctx.IsValid.ShouldBeFalse(); - ctx.ErrorMessage.ShouldBe("EntityId is required."); - } - - // Empty/null ACS URLs are NOT a configuration error — the endpoint handlers - // are responsible for returning specific errors when no ACS URLs are configured. - [Fact] - public async Task Empty_acs_urls_should_pass() - { - var sp = ValidSp(); - sp.AssertionConsumerServiceUrls = new HashSet(); - var ctx = new SamlServiceProviderConfigurationValidationContext(sp); - - await _validator.ValidateAsync(ctx); - - ctx.IsValid.ShouldBeTrue(); - } - - [Fact] - public async Task Null_acs_urls_should_pass() - { - var sp = ValidSp(); - sp.AssertionConsumerServiceUrls = null!; - var ctx = new SamlServiceProviderConfigurationValidationContext(sp); - - await _validator.ValidateAsync(ctx); - - ctx.IsValid.ShouldBeTrue(); - } - - [Fact] - public async Task Http_acs_url_should_fail() - { - var sp = ValidSp(); - sp.AssertionConsumerServiceUrls = new HashSet { new Uri("http://sp.example.com/acs") }; - var ctx = new SamlServiceProviderConfigurationValidationContext(sp); - - await _validator.ValidateAsync(ctx); - - ctx.IsValid.ShouldBeFalse(); - ctx.ErrorMessage.ShouldBe("Assertion Consumer Service URL 'http://sp.example.com/acs' does not use HTTPS scheme."); - } - - [Fact] - public async Task Http_slo_url_should_fail() - { - var sp = ValidSp(); - sp.SingleLogoutServiceUrl = new SamlEndpointType - { - Location = new Uri("http://sp.example.com/slo"), - Binding = SamlBinding.HttpPost - }; - var ctx = new SamlServiceProviderConfigurationValidationContext(sp); - - await _validator.ValidateAsync(ctx); - - ctx.IsValid.ShouldBeFalse(); - ctx.ErrorMessage.ShouldBe("Single Logout Service URL 'http://sp.example.com/slo' does not use HTTPS scheme."); - } - - [Fact] - public async Task Https_slo_url_should_pass() - { - var sp = ValidSp(); - sp.SingleLogoutServiceUrl = new SamlEndpointType - { - Location = new Uri("https://sp.example.com/slo"), - Binding = SamlBinding.HttpPost - }; - var ctx = new SamlServiceProviderConfigurationValidationContext(sp); - - await _validator.ValidateAsync(ctx); - - ctx.IsValid.ShouldBeTrue(); - } - - [Fact] - public async Task Null_slo_url_should_pass() - { - var sp = ValidSp(); - sp.SingleLogoutServiceUrl = null; - var ctx = new SamlServiceProviderConfigurationValidationContext(sp); - - await _validator.ValidateAsync(ctx); - - ctx.IsValid.ShouldBeTrue(); - } - - // RequireSignedAuthnRequests without signing certs is NOT a configuration error — - // the endpoint handlers are responsible for giving specific errors in this case. - [Fact] - public async Task RequireSignedAuthnRequests_without_signing_certs_should_pass() - { - var sp = ValidSp(); - sp.RequireSignedAuthnRequests = true; - sp.SigningCertificates = null; - var ctx = new SamlServiceProviderConfigurationValidationContext(sp); - - await _validator.ValidateAsync(ctx); - - ctx.IsValid.ShouldBeTrue(); - } - - [Fact] - public async Task RequireSignedAuthnRequests_with_empty_signing_certs_should_pass() - { - var sp = ValidSp(); - sp.RequireSignedAuthnRequests = true; - sp.SigningCertificates = new List(); - var ctx = new SamlServiceProviderConfigurationValidationContext(sp); - - await _validator.ValidateAsync(ctx); - - ctx.IsValid.ShouldBeTrue(); - } - - [Fact] - public async Task RequireSignedAuthnRequests_false_without_certs_should_pass() - { - var sp = ValidSp(); - sp.RequireSignedAuthnRequests = false; - sp.SigningCertificates = null; - var ctx = new SamlServiceProviderConfigurationValidationContext(sp); - - await _validator.ValidateAsync(ctx); - - ctx.IsValid.ShouldBeTrue(); - } - - [Fact] - public async Task EncryptAssertions_without_encryption_certs_should_fail() - { - var sp = ValidSp(); - sp.EncryptAssertions = true; - sp.EncryptionCertificates = null; - var ctx = new SamlServiceProviderConfigurationValidationContext(sp); - - await _validator.ValidateAsync(ctx); - - ctx.IsValid.ShouldBeFalse(); - ctx.ErrorMessage.ShouldBe("Encryption certificates are required when EncryptAssertions is true."); - } - - [Fact] - public async Task EncryptAssertions_false_without_certs_should_pass() - { - var sp = ValidSp(); - sp.EncryptAssertions = false; - sp.EncryptionCertificates = null; - var ctx = new SamlServiceProviderConfigurationValidationContext(sp); - - await _validator.ValidateAsync(ctx); - - ctx.IsValid.ShouldBeTrue(); - } -} diff --git a/identity-server/test/IdentityServer.UnitTests/Validation/Secrets/PrivateKeyJwtSecretValidation.cs b/identity-server/test/IdentityServer.UnitTests/Validation/Secrets/PrivateKeyJwtSecretValidation.cs index bb590466d..cb22d9507 100644 --- a/identity-server/test/IdentityServer.UnitTests/Validation/Secrets/PrivateKeyJwtSecretValidation.cs +++ b/identity-server/test/IdentityServer.UnitTests/Validation/Secrets/PrivateKeyJwtSecretValidation.cs @@ -234,13 +234,13 @@ public class PrivateKeyJwtSecretValidation } [Theory] - [InlineData(Typ.ClientAuthentication, true, false)] - [InlineData(Typ.ClientAuthentication, false, false)] + [InlineData(Typ.ClientAuthentication, true, true)] + [InlineData(Typ.ClientAuthentication, false, true)] [InlineData(Typ.None, true, false)] [InlineData(Typ.None, false, true)] [InlineData(Typ.JWT, true, false)] [InlineData(Typ.JWT, false, true)] - public async Task Strict_audience_does_not_allow_single_valued_arrays(Typ typ, bool setStrictOption, bool expectedResult) + public async Task Strict_audience_allows_single_valued_arrays(Typ typ, bool setStrictOption, bool expectedResult) { _options.Preview.StrictClientAssertionAudienceValidation = setStrictOption; @@ -248,7 +248,7 @@ public class PrivateKeyJwtSecretValidation var client = await _clients.FindEnabledClientByIdAsync(clientId, _ct); var token = new JwtSecurityTokenHandler().WriteToken(CreateToken( clientId, - audiences: ["https://idsrv.com/connect/token"], + audiences: ["https://idsrv.com"], typ: typ)); var secret = new ParsedSecret diff --git a/identity-server/test/IdentityServer.UnitTests/Validation/Secrets/SecretValidation.cs b/identity-server/test/IdentityServer.UnitTests/Validation/Secrets/SecretValidation.cs index b6f02f5c7..d1d1deb7a 100644 --- a/identity-server/test/IdentityServer.UnitTests/Validation/Secrets/SecretValidation.cs +++ b/identity-server/test/IdentityServer.UnitTests/Validation/Secrets/SecretValidation.cs @@ -8,7 +8,6 @@ using Duende.IdentityServer.Models; using Duende.IdentityServer.Stores; using Duende.IdentityServer.Validation; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Time.Testing; using UnitTests.Validation.Setup; namespace UnitTests.Validation.Secrets; diff --git a/identity-server/test/IdentityServer.UnitTests/Validation/Setup/Factory.cs b/identity-server/test/IdentityServer.UnitTests/Validation/Setup/Factory.cs index 69b5f623b..7a3332567 100644 --- a/identity-server/test/IdentityServer.UnitTests/Validation/Setup/Factory.cs +++ b/identity-server/test/IdentityServer.UnitTests/Validation/Setup/Factory.cs @@ -16,7 +16,6 @@ using Duende.IdentityServer.Validation; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; -using Microsoft.Extensions.Time.Testing; using UnitTests.Common; namespace UnitTests.Validation.Setup; diff --git a/ignore-this/README.md b/ignore-this/README.md new file mode 100644 index 000000000..749474779 --- /dev/null +++ b/ignore-this/README.md @@ -0,0 +1,3 @@ +# Duende.IgnoreThis + +Test package for validating the release pipeline. Not intended for production use. diff --git a/ignore-this/ignore-this.slnf b/ignore-this/ignore-this.slnf new file mode 100644 index 000000000..c8a457ab9 --- /dev/null +++ b/ignore-this/ignore-this.slnf @@ -0,0 +1,9 @@ +{ + "solution": { + "path": "..\\products.slnx", + "projects": [ + "ignore-this\\src\\IgnoreThis\\IgnoreThis.csproj", + "ignore-this\\test\\IgnoreThis.Tests\\IgnoreThis.Tests.csproj" + ] + } +} diff --git a/ignore-this/src/Directory.Build.props b/ignore-this/src/Directory.Build.props new file mode 100644 index 000000000..de732b89c --- /dev/null +++ b/ignore-this/src/Directory.Build.props @@ -0,0 +1,14 @@ + + + + + + + + enable + Duende IgnoreThis + it- + 0.1 + + + diff --git a/ignore-this/src/IgnoreThis/IgnoreThis.csproj b/ignore-this/src/IgnoreThis/IgnoreThis.csproj new file mode 100644 index 000000000..309182e16 --- /dev/null +++ b/ignore-this/src/IgnoreThis/IgnoreThis.csproj @@ -0,0 +1,11 @@ + + + net10.0 + enable + true + Duende.IgnoreThis + $(PackageId) + $(PackageId) + Ignore this package; it is used internally to test our package publishing process. + + diff --git a/ignore-this/test/Directory.Build.props b/ignore-this/test/Directory.Build.props new file mode 100644 index 000000000..689890199 --- /dev/null +++ b/ignore-this/test/Directory.Build.props @@ -0,0 +1,7 @@ + + + + + enable + + diff --git a/ignore-this/test/IgnoreThis.Tests/Class1.cs b/ignore-this/test/IgnoreThis.Tests/Class1.cs new file mode 100644 index 000000000..61c147b02 --- /dev/null +++ b/ignore-this/test/IgnoreThis.Tests/Class1.cs @@ -0,0 +1,11 @@ +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + +namespace Duende.IgnoreThis; + +public class Class1 +{ + [Fact] + public void Test1() + { } +} diff --git a/ignore-this/test/IgnoreThis.Tests/IgnoreThis.Tests.csproj b/ignore-this/test/IgnoreThis.Tests/IgnoreThis.Tests.csproj new file mode 100644 index 000000000..65ebdef5c --- /dev/null +++ b/ignore-this/test/IgnoreThis.Tests/IgnoreThis.Tests.csproj @@ -0,0 +1,9 @@ + + + net10.0 + Duende.IgnoreThis + + + + + diff --git a/products.slnx b/products.slnx index 3707b838f..101ad3ab5 100644 --- a/products.slnx +++ b/products.slnx @@ -1,27 +1,22 @@ + - - - - - - @@ -32,7 +27,6 @@ - @@ -59,49 +53,31 @@ - - + - - - - - - - - - - - - + + - - - - - - - + + - + - - @@ -143,10 +119,10 @@ - + @@ -170,7 +146,6 @@ - @@ -184,20 +159,11 @@ - - - + + - - - - - - - - - - + + diff --git a/products.slnx.v3.ncrunchsolution b/products.slnx.v3.ncrunchsolution deleted file mode 100644 index 13107d394..000000000 --- a/products.slnx.v3.ncrunchsolution +++ /dev/null @@ -1,8 +0,0 @@ - - - True - True - True - True - - \ No newline at end of file diff --git a/products.v3.ncrunchsolution b/products.v3.ncrunchsolution deleted file mode 100644 index fe9b0700d..000000000 --- a/products.v3.ncrunchsolution +++ /dev/null @@ -1,8 +0,0 @@ - - - True - False - True - True - - \ No newline at end of file diff --git a/shared/ShouldlyExtensions/ShouldlyExtensions.cs b/shared/ShouldlyExtensions/ShouldlyExtensions.cs index b07f37b75..90cab46c0 100644 --- a/shared/ShouldlyExtensions/ShouldlyExtensions.cs +++ b/shared/ShouldlyExtensions/ShouldlyExtensions.cs @@ -57,7 +57,7 @@ public static class ShouldlyExtensions { var missingItems = expected.Where(item => !actual.Contains(item)).ToList(); - if (missingItems.Any()) + if (missingItems.Count > 0) { throw new ShouldAssertException( $"Expected collection to contain all items, but these were missing: {string.Join(", ", missingItems)}.\n" + diff --git a/shared/ShouldlyExtensions/ShouldlyExtensions.csproj b/shared/ShouldlyExtensions/ShouldlyExtensions.csproj index 743467715..c4188b665 100644 --- a/shared/ShouldlyExtensions/ShouldlyExtensions.csproj +++ b/shared/ShouldlyExtensions/ShouldlyExtensions.csproj @@ -1,12 +1,11 @@ - net10.0 - enable + None + false enable false Shouldly - false diff --git a/shared/Xunit.Playwright/Retries/DelayedMessageBus.cs b/shared/Xunit.Playwright/Retries/DelayedMessageBus.cs index f0da034c5..3316b022c 100644 --- a/shared/Xunit.Playwright/Retries/DelayedMessageBus.cs +++ b/shared/Xunit.Playwright/Retries/DelayedMessageBus.cs @@ -30,7 +30,7 @@ internal sealed class DelayedMessageBus(IMessageBus innerBus) : IMessageBus { foreach (var message in _messages) { - innerBus.QueueMessage(message); + _ = innerBus.QueueMessage(message); } } } diff --git a/shared/Xunit.Playwright/Xunit.Playwright.csproj b/shared/Xunit.Playwright/Xunit.Playwright.csproj index 8fbf0b5e1..e967e28ff 100644 --- a/shared/Xunit.Playwright/Xunit.Playwright.csproj +++ b/shared/Xunit.Playwright/Xunit.Playwright.csproj @@ -1,39 +1,31 @@ - - net10.0 - enable + None enable Duende.Xunit.Playwright Duende.Xunit.Playwright - true false - false - $(DefineConstants);DEBUG_NCRUNCH - - - - - + + + + - - + - diff --git a/src.props b/src.props index ed25891fd..37f8f20a4 100644 --- a/src.props +++ b/src.props @@ -1,31 +1,10 @@ - - net10.0 - - Duende Software - Duende Software - Duende Software - - - - - - - embedded - - - - latest - true - true - true - True - true - $(NoWarn);CS1591;NU1507 false true + Generated + true true @@ -41,39 +20,23 @@ build.$(BUILD_NUMBER) patch - - true - true $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb true + true + true ../../README.md - - - true - true + + + $(NoWarn);RS0016 + $(NoWarn);RS0037 - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + + diff --git a/src.targets b/src.targets new file mode 100644 index 000000000..d2b725b9f --- /dev/null +++ b/src.targets @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/templates.props b/templates.props deleted file mode 100644 index 2ccce55c8..000000000 --- a/templates.props +++ /dev/null @@ -1,59 +0,0 @@ - - - Template - net10.0 - true - false - en-US - true - - Duende Software - Duende Software - Duende Software - - false - true - - LICENSE - icon.png - - - $(NoWarn);NU5128 - - - 0 - build.$(BUILD_NUMBER) - patch - - - true - https://github.com/duendesoftware/products - https://github.com/duendesoftware/products/releases - README.md - - - - - true - true - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/templates/build/Program.cs b/templates/build/Program.cs index e67467e62..58b213340 100644 --- a/templates/build/Program.cs +++ b/templates/build/Program.cs @@ -77,7 +77,7 @@ void CopyDir(DirectoryInfo source, DirectoryInfo target) void CopyFile(DirectoryInfo directoryInfo, FileInfo fileInfo) { var destFileName = Path.Combine(directoryInfo.FullName, fileInfo.Name); - fileInfo.CopyTo(destFileName, true); + _ = fileInfo.CopyTo(destFileName, true); } bool TryFindFile(string fileName, [NotNullWhen(true)] out FileInfo? found) diff --git a/templates/build/build.csproj b/templates/build/build.csproj index ed9781c22..7562235a5 100644 --- a/templates/build/build.csproj +++ b/templates/build/build.csproj @@ -2,9 +2,8 @@ Exe - net10.0 - enable enable + $(NoWarn);CA1303 diff --git a/templates/templates.csproj b/templates/templates.csproj index 3388c24ba..e64bdc9bd 100644 --- a/templates/templates.csproj +++ b/templates/templates.csproj @@ -1,17 +1,46 @@ - net10.0 + Template + true + false + en-US + + false + true + Duende.Templates Templates for Duende Identity Server and Duende BFF dotnet-new;templates;duende;bff; + LICENSE + icon.png + README.md + + + $(NoWarn);NU5128 + + + 0 + build.$(BUILD_NUMBER) + patch templates- + + + true + https://github.com/duendesoftware/products + https://github.com/duendesoftware/products/releases - - - - README.md + + + true + true @@ -19,5 +48,17 @@ + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/test.props b/test.props index 6f05c5bec..57275d6e1 100644 --- a/test.props +++ b/test.props @@ -1,43 +1,87 @@ - net10.0 - latest - full - false + Recommended + true + true - true - true - - true - $(NoWarn);CS1591;NU1507 exe true - - - - - true - true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(NoWarn);CA1000;CA1001;CA1002;CA1003;CA1012;CA1024;CA1031;CA1033;CA1041;CA1051;CA1052;CA1054;CA1055;CA1056;CA1062;CA1063;CA1304;CA1305;CA1307;CA1308;CA1309;CA1310;CA1311;CA1508;CA1515;CA1707;CA1708;CA1711;CA1716;CA1724;CA1725;CA1805;CA1806;CA1810;CA1812;CA1816;CA1820;CA1822;CA1823;CA1825;CA1829;CA1835;CA1848;CA1849;CA1850;CA1851;CA1852;CA1859;CA1860;CA1861;CA1863;CA1864;CA1866;CA1869;CA1872;CA2000;CA2016;CA2201;CA2211;CA2213;CA2227;CA2234;CA2254;CA5350 - - - - + + + + + + +