mirror of
https://github.com/DuendeSoftware/products
synced 2026-05-24 09:28:24 +00:00
Publish - 2026-03-16 22:06:27 UTC
This commit is contained in:
parent
fee70ffce7
commit
3e811895ec
495 changed files with 2618 additions and 6471 deletions
12
.config/dotnet-tools.json
vendored
Normal file
12
.config/dotnet-tools.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"version": 1,
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"NuGetKeyVaultSignTool": {
|
||||
"version": "3.2.3",
|
||||
"commands": [
|
||||
"NuGetKeyVaultSignTool"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
33
.github/CONTRIBUTING.md
vendored
33
.github/CONTRIBUTING.md
vendored
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
69
.github/workflows/auto-close-external.yml
vendored
69
.github/workflows/auto-close-external.yml
vendored
|
|
@ -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})`);
|
||||
118
.github/workflows/bff-release.yml
vendored
118
.github/workflows/bff-release.yml
vendored
|
|
@ -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
|
||||
118
.github/workflows/docs-mcp-release.yml
vendored
118
.github/workflows/docs-mcp-release.yml
vendored
|
|
@ -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
|
||||
118
.github/workflows/identity-server-release.yml
vendored
118
.github/workflows/identity-server-release.yml
vendored
|
|
@ -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
|
||||
118
.github/workflows/templates-release.yml
vendored
118
.github/workflows/templates-release.yml
vendored
|
|
@ -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
|
||||
9
.gitignore
vendored
9
.gitignore
vendored
|
|
@ -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
|
||||
|
|
|
|||
43
Directory.Build.props
Normal file
43
Directory.Build.props
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<Company>Duende Software</Company>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<AnalysisMode>All</AnalysisMode>
|
||||
<Authors>$(Company)</Authors>
|
||||
<ContinuousIntegrationBuild Condition="'$(GITHUB_ACTIONS)' == 'true'">True</ContinuousIntegrationBuild>
|
||||
<Copyright>$(Company)</Copyright>
|
||||
<DebugType>embedded</DebugType>
|
||||
<Deterministic>true</Deterministic>
|
||||
<!-- <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild> -->
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<IsPackable>false</IsPackable>
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
<!-- <NoWarn>$(NoWarn);EnableGenerateDocumentationFile</NoWarn>--><!-- workaround for https://github.com/dotnet/roslyn/issues/41640 -->
|
||||
<!-- <Nullable>enable</Nullable> -->
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<NoWarn>$(NoWarn);CA1034</NoWarn><!-- Nested types should not be visible -->
|
||||
<NoWarn>$(NoWarn);CA1040</NoWarn><!-- Avoid empty interfaces -->
|
||||
<NoWarn>$(NoWarn);CA2007</NoWarn><!-- Do not directly await a Task -->
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn><!-- Missing XML comment for publicly visible type or member -->
|
||||
<NoWarn>$(NoWarn);NU1507</NoWarn><!-- There are 2 package sources defined in your configuration -->
|
||||
</PropertyGroup>
|
||||
|
||||
<!--Release builds do more work and are stricter. This allows for faster
|
||||
development: devs can be messy/experimental initially and verify their
|
||||
code easily by running a build in Release mode, and we also enforce
|
||||
stricter rules in CI with the Release configuration.
|
||||
-->
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<!-- Workaround for https://github.com/dotnet/roslyn/issues/41640 -->
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)shared/Global.cs" Link="Global.cs" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
1
Directory.Build.targets
Normal file
1
Directory.Build.targets
Normal file
|
|
@ -0,0 +1 @@
|
|||
<Project />
|
||||
|
|
@ -1,79 +1,87 @@
|
|||
<Project>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="AngleSharp" Version="1.1.2" />
|
||||
|
||||
<PackageVersion Include="Aspire.Hosting.Testing" Version="13.0.0" />
|
||||
<PackageVersion Include="Aspire.Hosting.SqlServer" Version="13.0.0" />
|
||||
<PackageVersion Include="Aspire.Hosting.PostgreSQL" Version="13.1.1" />
|
||||
<PackageVersion Include="Aspire.Hosting.SqlServer" Version="13.1.1" />
|
||||
<PackageVersion Include="Aspire.Hosting.Testing" Version="13.1.1" />
|
||||
<PackageVersion Include="BenchmarkDotNet" Version="0.15.0" />
|
||||
<PackageVersion Include="BullsEye" Version="5.0.0" />
|
||||
<!-- Added aspire transitive package to resolve package vulnerability -->
|
||||
<PackageVersion Include="KubernetesClient" Version="17.0.14" />
|
||||
<PackageVersion Include="Bullseye" Version="6.0.0" />
|
||||
<PackageVersion Include="coverlet.collector" Version="6.0.4" />
|
||||
<PackageVersion Include="Cronos" Version="0.11.1" />
|
||||
<PackageVersion Include="Duende.AccessTokenManagement" Version="4.1.1" />
|
||||
<PackageVersion Include="Duende.AccessTokenManagement.OpenIdConnect" Version="4.1.1" />
|
||||
<PackageVersion Include="Duende.AspNetCore.Authentication.JwtBearer" Version="0.3.0" />
|
||||
<PackageVersion Include="Duende.ConformanceReport" Version="0.1.0" />
|
||||
<PackageVersion Include="Duende.IdentityModel" Version="8.0.0" />
|
||||
<PackageVersion Include="Duende.IdentityModel.OidcClient" Version="7.0.0" />
|
||||
<PackageVersion Include="Duende.IdentityServer" Version="7.4.0-preview.2" />
|
||||
<PackageVersion Include="Duende.IdentityServer.Storage" Version="7.4.0-preview.2" />
|
||||
<PackageVersion Include="Duende.Internal.ValueObjectSourceGenerator" Version="1.0.1" />
|
||||
<PackageVersion Include="Duende.Private.Licensing" Version="1.0.0" />
|
||||
<PackageVersion Include="Duende.RazorSlices" Version="1.0.0" />
|
||||
<PackageVersion Include="Google.Protobuf" Version="3.31.1" />
|
||||
<PackageVersion Include="Grpc.AspNetCore" Version="2.76.0" />
|
||||
<PackageVersion Include="Grpc.AspNetCore.Web" Version="2.76.0" />
|
||||
<PackageVersion Include="Grpc.Net.Client" Version="2.76.0" />
|
||||
<PackageVersion Include="Grpc.Net.Client.Web" Version="2.76.0" />
|
||||
<PackageVersion Include="Grpc.Tools" Version="2.78.0" />
|
||||
<PackageVersion Include="IdentityModel.AspNetCore.OAuth2Introspection" Version="6.2.0" />
|
||||
<PackageVersion Include="Markdig" Version="0.43.0" />
|
||||
<PackageVersion Include="MartinCostello.Logging.XUnit.v3" Version="0.7.0" />
|
||||
<PackageVersion Include="Microsoft.Testing.Extensions.CodeCoverage" Version="18.4.1" />
|
||||
<!-- Review Packages -->
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Authentication.Certificate" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Components.Authorization" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.DataProtection.Abstractions" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.WebUtilities" Version="2.2.0" />
|
||||
<PackageVersion Include="Microsoft.Build.Tasks.Core" Version="17.14.28" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="3.3.4" />
|
||||
<PackageVersion Include="Microsoft.Data.SqlClient" Version="6.1.4" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Hybrid" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Diagnostics.Testing" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Http" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Http" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="10.1.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Testing" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Primitives" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Options.DataAnnotations" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.ServiceDiscovery" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.TimeProvider.Testing" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.0.1" />
|
||||
<PackageVersion Include="Microsoft.IdentityModel.Logging" Version="8.0.1" />
|
||||
<PackageVersion Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="8.0.1" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
||||
<PackageVersion Include="Microsoft.NETCore.Jit" Version="2.0.8" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
|
||||
<PackageVersion Include="Microsoft.Playwright.Xunit.v3" Version="1.58.0" />
|
||||
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Testing.Extensions.CodeCoverage" Version="18.4.1" />
|
||||
<PackageVersion Include="Microsoft.Testing.Extensions.TrxReport" Version="2.1.0" />
|
||||
<PackageVersion Include="MimeKit" Version="4.15.1" />
|
||||
<PackageVersion Include="MinVer" Version="6.0.0" />
|
||||
<PackageVersion Include="ModelContextProtocol" Version="0.4.0-preview.3" />
|
||||
<PackageVersion Include="ModelContextProtocol.AspNetCore" Version="0.4.0-preview.3" />
|
||||
<PackageVersion Include="NBomber" Version="6.0.2" />
|
||||
<PackageVersion Include="NBomber.Http" Version="6.0.2" />
|
||||
<PackageVersion Include="NBomber.Sinks.Timescale" Version="0.8.0" />
|
||||
<PackageVersion Include="netDumbster" Version="3.1.1" />
|
||||
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageVersion Include="Npgsql" Version="10.0.1" />
|
||||
<PackageVersion Include="NSubstitute" Version="5.1.0" />
|
||||
<PackageVersion Include="OpenTelemetry" Version="1.12.0" />
|
||||
<PackageVersion Include="OpenTelemetry.Exporter.Console" Version="1.12.0" />
|
||||
<PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.12.0" />
|
||||
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="1.12.0" />
|
||||
|
|
@ -81,33 +89,30 @@
|
|||
<PackageVersion Include="OpenTelemetry.Instrumentation.Http" Version="1.12.0" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.Runtime" Version="1.12.0" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.SqlClient" Version="1.12.0-beta.2" />
|
||||
<PackageVersion Include="OpenTelemetry" Version="1.12.0" />
|
||||
<PackageVersion Include="PublicApiGenerator" Version="11.1.0" />
|
||||
<PackageVersion Include="Duende.RazorSlices" Version="1.0.0" />
|
||||
<PackageVersion Include="PublicApiGenerator" Version="11.5.4" />
|
||||
<PackageVersion Include="ReverseMarkdown" Version="4.7.0" />
|
||||
<PackageVersion Include="RichardSzalay.MockHttp" Version="7.0.0" />
|
||||
<PackageVersion Include="Serilog" Version="4.2.0" />
|
||||
<PackageVersion Include="Serilog.AspNetCore" Version="8.0.3" />
|
||||
<PackageVersion Include="Serilog.Extensions.Logging" Version="9.0.2" />
|
||||
<PackageVersion Include="Serilog.Sinks.Console" Version="6.0.0" />
|
||||
<PackageVersion Include="Serilog.Sinks.File" Version="7.0.0" />
|
||||
<PackageVersion Include="Serilog.Sinks.OpenTelemetry" Version="4.2.0" />
|
||||
<PackageVersion Include="Serilog.Sinks.TextWriter" Version="3.0.0" />
|
||||
<PackageVersion Include="Serilog.Extensions.Logging" Version="9.0.2" />
|
||||
<PackageVersion Include="Shouldly" Version="4.2.1" />
|
||||
<PackageVersion Include="Shouldly" Version="4.3.0" />
|
||||
<PackageVersion Include="SimpleExec" Version="12.0.0" />
|
||||
<PackageVersion Include="SimpleFeedReader" Version="2.0.4" />
|
||||
<PackageVersion Include="Spectre.Console.Cli" Version="0.53.0" />
|
||||
<PackageVersion Include="Spectre.Console.Json" Version="0.53.0" />
|
||||
<PackageVersion Include="Sustainsys.Saml2.AspNetCore2" Version="2.11.0" />
|
||||
<PackageVersion Include="System.CommandLine" Version="2.0.3" />
|
||||
<PackageVersion Include="System.Drawing.Common" Version="10.0.3" />
|
||||
<PackageVersion Include="System.Formats.Cbor" Version="10.0.3" />
|
||||
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.0.1" />
|
||||
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
|
||||
<PackageVersion Include="System.Text.Json" Version="10.0.0" />
|
||||
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
|
||||
<PackageVersion Include="xunit.v3.core" Version="3.2.2" />
|
||||
<PackageVersion Include="Verify.XunitV3" Version="31.13.0" />
|
||||
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
|
||||
<PackageVersion Include="xunit.v3.core.mtp-v2" Version="3.2.2" />
|
||||
<PackageVersion Include="xunit.v3.extensibility.core" Version="3.2.2" />
|
||||
<PackageVersion Include="Verify.XunitV3" Version="31.13.0" />
|
||||
<PackageVersion Include="Vogen" Version="7.0.3" />
|
||||
<PackageVersion Include="Yarp.ReverseProxy" Version="2.1.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -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"
|
||||
]
|
||||
|
|
|
|||
25
aspnetcore-authentication-jwtbearer/build.cs
Normal file
25
aspnetcore-authentication-jwtbearer/build.cs
Normal file
|
|
@ -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);
|
||||
|
|
@ -5,15 +5,12 @@
|
|||
<RootNamespace>Duende.AspNetCore.Authentication.JwtBearer</RootNamespace>
|
||||
<AssemblyName>Duende.AspNetCore.Authentication.JwtBearer</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
|
||||
<PackageReference Include="Duende.IdentityModel" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Hybrid" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<InternalsVisibleTo Include="Duende.AspNetCore.Authentication.JwtBearer.Tests" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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('\"');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ public sealed class DPoPOptions
|
|||
/// <item>Signatures are allowed from RSA, PSA, or ECDSA algorithms with key sizes of 256, 384, or 512 bits.</item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
public TokenValidationParameters ProofTokenValidationParameters = new()
|
||||
public TokenValidationParameters ProofTokenValidationParameters { get; set; } = new()
|
||||
{
|
||||
ValidateAudience = false,
|
||||
ValidateIssuer = false,
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,18 +20,18 @@ public static class DPoPServiceCollectionExtensions
|
|||
/// </summary>
|
||||
public IServiceCollection ConfigureDPoPTokensForScheme(string scheme)
|
||||
{
|
||||
services.AddOptions<DPoPOptions>();
|
||||
_ = services.AddOptions<DPoPOptions>();
|
||||
|
||||
services.AddSingleton<DPoPJwtBearerEvents>();
|
||||
_ = services.AddSingleton<DPoPJwtBearerEvents>();
|
||||
services.TryAddTransient<IDPoPProofValidator, DPoPProofValidator>();
|
||||
services.TryAddTransient<IDPoPNonceValidator, DefaultDPoPNonceValidator>();
|
||||
services.AddTransient<DPoPExpirationValidator>();
|
||||
_ = services.AddTransient<DPoPExpirationValidator>();
|
||||
services.TryAddTransient<IDPoPProofValidator, DPoPProofValidator>();
|
||||
|
||||
services.TryAddTransient<DPoPHybridCacheProvider>();
|
||||
services.TryAddTransient<IReplayCache, ReplayCache>();
|
||||
|
||||
services.AddSingleton<IPostConfigureOptions<JwtBearerOptions>>(sp =>
|
||||
_ = services.AddSingleton<IPostConfigureOptions<JwtBearerOptions>>(sp =>
|
||||
{
|
||||
var events = sp.GetRequiredService<DPoPJwtBearerEvents>();
|
||||
return new ConfigureJwtBearerOptions(events)
|
||||
|
|
@ -48,7 +48,7 @@ public static class DPoPServiceCollectionExtensions
|
|||
/// </summary>
|
||||
public IServiceCollection ConfigureDPoPTokensForScheme(string scheme, Action<DPoPOptions> configure)
|
||||
{
|
||||
services.Configure(scheme, configure);
|
||||
_ = services.Configure(scheme, configure);
|
||||
return services.ConfigureDPoPTokensForScheme(scheme);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project>
|
||||
|
||||
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)..\'))" />
|
||||
<Import Project="../../src.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
|
|
@ -9,6 +10,11 @@
|
|||
<MinVerTagPrefix>aaj-</MinVerTagPrefix>
|
||||
<MinVerMinimumMajorMinor>0.2</MinVerMinimumMajorMinor>
|
||||
<AssemblyName>Duende.$(MSBuildProjectName)</AssemblyName>
|
||||
<!-- CA1848/CA1873: LoggerMessage refactor is a separate effort -->
|
||||
<!-- CA1031: Intentional catch-all for malformed token parsing -->
|
||||
<!-- CA5404: DPoP proofs intentionally skip audience/issuer/lifetime validation -->
|
||||
<!-- CA1056: ExpectedUrl is used as string throughout the DPoP flow -->
|
||||
<NoWarn>$(NoWarn);CA1848;CA1873;CA1031;CA5404;CA1056</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
<Project>
|
||||
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.targets', '$(MSBuildThisFileDirectory)..\'))" />
|
||||
<Import Project="../../src.targets" />
|
||||
</Project>
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
|
|
@ -7,7 +6,6 @@
|
|||
<RootNameSpace>Duende.AspNetCore.Authentication.JwtBearer</RootNameSpace>
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AngleSharp" />
|
||||
<PackageReference Include="Duende.AccessTokenManagement.OpenIdConnect" />
|
||||
|
|
@ -16,13 +14,9 @@
|
|||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" />
|
||||
<PackageReference Include="Microsoft.Extensions.Diagnostics.Testing" />
|
||||
<PackageReference Include="MartinCostello.Logging.XUnit.v3" />
|
||||
<PackageReference Include="Microsoft.Extensions.TimeProvider.Testing" />
|
||||
<PackageReference Include="RichardSzalay.MockHttp" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference
|
||||
Include="..\..\src\AspNetCore.Authentication.JwtBearer\AspNetCore.Authentication.JwtBearer.csproj" />
|
||||
<ProjectReference Include="..\..\src\AspNetCore.Authentication.JwtBearer\AspNetCore.Authentication.JwtBearer.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -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<IDPoPNonceValidator>(customValidator);
|
||||
_ = services.AddSingleton<IDPoPNonceValidator>(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<HybridCache>(ServiceProviderKeys.ProofTokenReplayHybridCache, cache);
|
||||
_ = services.AddKeyedSingleton<HybridCache>(ServiceProviderKeys.ProofTokenReplayHybridCache, cache);
|
||||
};
|
||||
await Initialize();
|
||||
|
||||
|
|
@ -270,12 +270,12 @@ public class DPoPIntegrationTests
|
|||
/// </summary>
|
||||
private async Task<UserToken> 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<UserToken>();
|
||||
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 =>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project>
|
||||
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)..\'))" />
|
||||
<Import Project="../../test.props" />
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
<SolutionConfiguration>
|
||||
<Settings>
|
||||
<AllowParallelTestExecution>True</AllowParallelTestExecution>
|
||||
<EnableRDI>False</EnableRDI>
|
||||
<RdiConfigured>True</RdiConfigured>
|
||||
<SolutionConfigured>True</SolutionConfigured>
|
||||
</Settings>
|
||||
</SolutionConfiguration>
|
||||
28
bff/build.cs
Normal file
28
bff/build.cs
Normal file
|
|
@ -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);
|
||||
|
|
@ -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<IRenderModeContext, ServerRenderModeContext>();
|
||||
_ = builder.Services.AddScoped<IRenderModeContext, ServerRenderModeContext>();
|
||||
|
||||
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>()
|
||||
_ = app.MapRazorComponents<App>()
|
||||
.AddInteractiveServerRenderMode()
|
||||
.AddInteractiveWebAssemblyRenderMode()
|
||||
.AddAdditionalAssemblies(typeof(Hosts.Bff.Blazor.PerComponent.Client._Imports).Assembly);
|
||||
|
|
|
|||
|
|
@ -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<AuthenticationStateProvider, ServerAuthenticationStateProvider>();
|
||||
_ = builder.Services.AddCascadingAuthenticationState();
|
||||
_ = builder.Services.AddScoped<AuthenticationStateProvider, ServerAuthenticationStateProvider>();
|
||||
|
||||
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>()
|
||||
_ = app.MapRazorComponents<App>()
|
||||
.AddInteractiveWebAssemblyRenderMode()
|
||||
.AddAdditionalAssemblies(typeof(Hosts.Bff.Blazor.WebAssembly.Client._Imports).Assembly);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project>
|
||||
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)..\'))" />
|
||||
<PropertyGroup>
|
||||
<!-- This line is needed because:
|
||||
|
||||
|
|
@ -17,9 +18,8 @@
|
|||
we do need this check, we're setting it here as well.
|
||||
|
||||
-->
|
||||
<AnalysisMode>None</AnalysisMode>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
|
||||
<WarnOnPackingNonPackableProject>false</WarnOnPackingNonPackableProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="../../hosts_and_clients.props" />
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
<Nullable>enable</Nullable>
|
||||
<IsAspireHost>true</IsAspireHost>
|
||||
<UserSecretsId>616547e2-3a28-4c9d-8685-f4ac02581162</UserSecretsId>
|
||||
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1,16 +1,13 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
<RootNamespace>Bff.EF</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\migrations\UserSessionDb\UserSessionDb.csproj" />
|
||||
<ProjectReference Include="..\..\src\Bff.EntityFramework\Bff.EntityFramework.csproj" />
|
||||
|
|
@ -19,5 +16,4 @@
|
|||
<ItemGroup>
|
||||
<ProjectReference Include="..\Hosts.ServiceDefaults\Hosts.ServiceDefaults.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,19 +1,15 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Duende.IdentityServer" />
|
||||
<PackageReference Include="Duende.IdentityModel" />
|
||||
<PackageReference Include="Duende.IdentityServer" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\bff\hosts\Hosts.ServiceDefaults\Hosts.ServiceDefaults.csproj" />
|
||||
<ProjectReference Include="..\..\src\Bff.Yarp\Bff.Yarp.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -16,21 +16,21 @@ var builder = Host.CreateApplicationBuilder();
|
|||
|
||||
if (startupConfiguration.IsServiceEnabled("api"))
|
||||
{
|
||||
builder.Services.Configure<ApiSettings>(builder.Configuration);
|
||||
builder.Services.AddHostedService<ApiHostedService>();
|
||||
_ = builder.Services.Configure<ApiSettings>(builder.Configuration);
|
||||
_ = builder.Services.AddHostedService<ApiHostedService>();
|
||||
}
|
||||
|
||||
if (startupConfiguration.IsServiceEnabled("idsrv"))
|
||||
{
|
||||
builder.Services.Configure<IdentityServerSettings>(builder.Configuration);
|
||||
builder.Services.AddHostedService<IdentityServerService>();
|
||||
_ = builder.Services.Configure<IdentityServerSettings>(builder.Configuration);
|
||||
_ = builder.Services.AddHostedService<IdentityServerService>();
|
||||
}
|
||||
|
||||
if (startupConfiguration.IsServiceEnabled("bff"))
|
||||
{
|
||||
builder.Services.Configure<BffSettings>(builder.Configuration);
|
||||
builder.Services.AddHostedService<SingleFrontendBffService>();
|
||||
builder.Services.AddHostedService<MultiFrontendBffService>();
|
||||
_ = builder.Services.Configure<BffSettings>(builder.Configuration);
|
||||
_ = builder.Services.AddHostedService<SingleFrontendBffService>();
|
||||
_ = builder.Services.AddHostedService<MultiFrontendBffService>();
|
||||
|
||||
}
|
||||
// Add services to the container.
|
||||
|
|
|
|||
|
|
@ -12,16 +12,16 @@ public class ApiHostedService(IOptions<ApiSettings> 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);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<ForwardedHeadersOptions>(options =>
|
||||
_ = builder.Services.Configure<ForwardedHeadersOptions>(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
|
||||
|
|
|
|||
|
|
@ -20,19 +20,19 @@ public class IdentityServerService(IOptions<IdentityServerSettings> 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<ForwardedHeadersOptions>(options =>
|
||||
_ = builder.Services.Configure<ForwardedHeadersOptions>(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<IdentityServerSettings> 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<IdentityServerSettings> 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<IdentityServerSettings> 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<IdentityServerSettings> 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();
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ public class MultiFrontendBffService(IConfiguration config, IOptions<BffSettings
|
|||
|
||||
public override void ConfigureBff(IBffServicesBuilder bff)
|
||||
{
|
||||
bff.ConfigureOpenIdConnect(o => 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<BffSettings
|
|||
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
bff.AddFrontends(
|
||||
_ = bff.AddFrontends(
|
||||
new BffFrontend(BffFrontendName.Parse("bff-with-path-" + i))
|
||||
.MapToPath("/path" + i));
|
||||
}
|
||||
|
|
@ -35,4 +35,3 @@ public class MultiFrontendBffService(IConfiguration config, IOptions<BffSettings
|
|||
|
||||
public override void ConfigureApp(WebApplication app) => app.MapGet("/", (CurrentFrontendAccessor currentFrontendAccessor) => "multi - " + currentFrontendAccessor.Get().Name);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<TokenExchangeGrantValidator>();
|
||||
_ = isBuilder.AddInMemoryIdentityResources(Config.IdentityResources);
|
||||
_ = isBuilder.AddInMemoryApiScopes(Config.ApiScopes);
|
||||
_ = isBuilder.AddInMemoryClients(Config.Clients);
|
||||
_ = isBuilder.AddInMemoryApiResources(Config.ApiResources);
|
||||
_ = isBuilder.AddExtensionGrantValidator<TokenExchangeGrantValidator>();
|
||||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -1,17 +1,13 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
<ImplicitUsings>true</ImplicitUsings>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Duende.IdentityServer" />
|
||||
<PackageReference Include="Duende.IdentityModel" />
|
||||
<PackageReference Include="Duende.IdentityServer" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Hosts.ServiceDefaults\Hosts.ServiceDefaults.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,25 +23,25 @@ public static class Extensions
|
|||
{
|
||||
public static TBuilder AddServiceDefaults<TBuilder>(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<ServiceDiscoveryOptions>(options =>
|
||||
_ = builder.Services.Configure<ServiceDiscoveryOptions>(options =>
|
||||
{
|
||||
options.AllowedSchemes = ["https"];
|
||||
});
|
||||
|
|
@ -51,23 +51,23 @@ public static class Extensions
|
|||
|
||||
public static TBuilder ConfigureOpenTelemetry<TBuilder>(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<TBuilder>(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")
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Duende.IdentityModel" />
|
||||
<PackageReference Include="Duende.AspNetCore.Authentication.JwtBearer" />
|
||||
<PackageReference Include="Duende.IdentityModel" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Hosts.ServiceDefaults\Hosts.ServiceDefaults.csproj" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ public class ToDoController : ControllerBase
|
|||
return NotFound();
|
||||
}
|
||||
|
||||
Data.Remove(item);
|
||||
_ = Data.Remove(item);
|
||||
_logger.LogInformation("Delete {id}", id);
|
||||
|
||||
return NoContent();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ public class ToDoController : ControllerBase
|
|||
return NotFound();
|
||||
}
|
||||
|
||||
Data.Remove(item);
|
||||
_ = Data.Remove(item);
|
||||
_logger.LogInformation("Delete {id}", id);
|
||||
|
||||
return NoContent();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ public class ToDoController : ControllerBase
|
|||
return NotFound();
|
||||
}
|
||||
|
||||
Data.Remove(item);
|
||||
_ = Data.Remove(item);
|
||||
_logger.LogInformation("Delete {id}", id);
|
||||
|
||||
return NoContent();
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project>
|
||||
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)..\'))" />
|
||||
<PropertyGroup>
|
||||
<AnalysisMode>None</AnalysisMode>
|
||||
<RootNamespace>$(AssemblyName)</RootNamespace>
|
||||
<AssemblyName>Duende.$(MSBuildProjectName)</AssemblyName>
|
||||
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
|
||||
<WarnOnPackingNonPackableProject>false</WarnOnPackingNonPackableProject>
|
||||
</PropertyGroup>
|
||||
<Import Project="../../hosts_and_clients.props" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
|||
2
bff/migrations/UserSessionDb/Migrations/.editorconfig
Normal file
2
bff/migrations/UserSessionDb/Migrations/.editorconfig
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
[*.cs]
|
||||
dotnet_diagnostic.IDE0058.severity = none
|
||||
|
|
@ -25,6 +25,6 @@ public class Program
|
|||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
_ = webBuilder.UseStartup<Startup>();
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,10 +16,10 @@ public class Startup
|
|||
{
|
||||
var cn = Configuration.GetConnectionString("db");
|
||||
|
||||
services.AddDbContext<SessionDbContext>(options =>
|
||||
_ = services.AddDbContext<SessionDbContext>(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));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Bff.EntityFramework\Bff.EntityFramework.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
|
|
@ -7,24 +6,20 @@
|
|||
<Nullable>enable</Nullable>
|
||||
<WarningsAsErrors>false</WarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Duende.IdentityServer" />
|
||||
<PackageReference Include="Duende.IdentityModel" />
|
||||
<PackageReference Include="BenchmarkDotNet" />
|
||||
<PackageReference Include="Duende.IdentityModel" />
|
||||
<PackageReference Include="Duende.IdentityServer" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.TestHost" />
|
||||
<PackageReference Include="Serilog.Extensions.Logging" />
|
||||
<PackageReference Include="Serilog.Sinks.File" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Bff.Yarp\Bff.Yarp.csproj" />
|
||||
<ProjectReference Include="..\..\src\Bff\Bff.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -53,27 +53,27 @@ public class BffHost : Host
|
|||
.AddRemoteApis();
|
||||
if (!Internet.UseKestrel)
|
||||
{
|
||||
services.AddSingleton<IForwarderHttpClientFactory>(new SimulatedInternetYarpForwarderFactory(Internet));
|
||||
_ = services.AddSingleton<IForwarderHttpClientFactory>(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);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<T>() where T : notnull => _app.Services.GetRequiredService<T>();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ public class PlainYarpProxy : Host
|
|||
{
|
||||
OnConfigureServices += services =>
|
||||
{
|
||||
services.AddSingleton<IForwarderHttpClientFactory>(new SimulatedInternetYarpForwarderFactory(Internet));
|
||||
services.AddReverseProxy()
|
||||
_ = services.AddSingleton<IForwarderHttpClientFactory>(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();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<HttpResponseMessage> SendAsync(
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<HttpResponseMessage> RunScenario(IScenarioContext context)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project>
|
||||
|
||||
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)..\'))" />
|
||||
<Import Project="../../src.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<AnalysisMode>None</AnalysisMode>
|
||||
<IsPackable>false</IsPackable>
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
<!-- RS0026: Do not add multiple overloads with optional parameters -->
|
||||
<NoWarn>$(NoWarn);RS0026</NoWarn>
|
||||
|
||||
<!-- RS0027: API with optional parameter(s) should have the most parameters amongst its public overloads -->
|
||||
<NoWarn>$(NoWarn);RS0027</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,23 +1,18 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<AssemblyName>Duende.BFF.Blazor.Client</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" />
|
||||
<PackageReference Include="Duende.Private.Licensing" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<InternalsVisibleTo Include="Duende.Bff.Tests" />
|
||||
<InternalsVisibleTo Include="DynamicProxyGenAssembly2" />
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ internal class BffClientAuthenticationStateProvider : AuthenticationStateProvide
|
|||
ILogger<BffClientAuthenticationStateProvider> 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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<PersistentUserService>()
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ public static class
|
|||
{
|
||||
ArgumentNullException.ThrowIfNull(builder);
|
||||
|
||||
builder.Services.AddActivatedSingleton<ServerSideSessionChecker>();
|
||||
_ = builder.Services.AddActivatedSingleton<ServerSideSessionChecker>();
|
||||
|
||||
builder.Services
|
||||
_ = builder.Services
|
||||
.AddOpenIdConnectAccessTokenManagement()
|
||||
.AddBlazorServerAccessTokenManagement<ServerSideTokenStore>()
|
||||
.AddSingleton<IClaimsTransformation, AddServerManagementClaimsTransform>()
|
||||
|
|
@ -28,7 +28,7 @@ public static class
|
|||
|
||||
if (configureOptions != null)
|
||||
{
|
||||
builder.Services.Configure(configureOptions);
|
||||
_ = builder.Services.Configure(configureOptions);
|
||||
}
|
||||
|
||||
return builder;
|
||||
|
|
|
|||
|
|
@ -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<AuthenticationState> task) => _authenticationStateTask = task;
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ public static class BffBuilderExtensions
|
|||
where T : IBffServicesBuilder
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(bffBuilder);
|
||||
bffBuilder.Services.AddDbContext<TContext>(action);
|
||||
_ = bffBuilder.Services.AddDbContext<TContext>(action);
|
||||
return bffBuilder.AddEntityFrameworkServerSideSessionsServices<TContext, T>();
|
||||
}
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ public static class BffBuilderExtensions
|
|||
where T : IBffServicesBuilder
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(bffBuilder);
|
||||
bffBuilder.Services.AddDbContext<TContext>(action);
|
||||
_ = bffBuilder.Services.AddDbContext<TContext>(action);
|
||||
return bffBuilder.AddEntityFrameworkServerSideSessionsServices<TContext, T>();
|
||||
}
|
||||
|
||||
|
|
@ -76,9 +76,9 @@ public static class BffBuilderExtensions
|
|||
where T : IBffServicesBuilder
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(bffBuilder);
|
||||
bffBuilder.Services.AddTransient<IUserSessionStoreCleanup, UserSessionStore>();
|
||||
bffBuilder.Services.AddTransient<ISessionDbContext>(svcs => svcs.GetRequiredService<TContext>());
|
||||
bffBuilder.AddServerSideSessions<UserSessionStore>();
|
||||
_ = bffBuilder.Services.AddTransient<IUserSessionStoreCleanup, UserSessionStore>();
|
||||
_ = bffBuilder.Services.AddTransient<ISessionDbContext>(svcs => svcs.GetRequiredService<TContext>());
|
||||
_ = bffBuilder.AddServerSideSessions<UserSessionStore>();
|
||||
|
||||
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<SessionCleanupHost>();
|
||||
bffBuilder.Services.AddSingleton<IHostedService>(sp => sp.GetRequiredService<SessionCleanupHost>());
|
||||
_ = bffBuilder.Services.AddSingleton<SessionCleanupHost>();
|
||||
_ = bffBuilder.Services.AddSingleton<IHostedService>(sp => sp.GetRequiredService<SessionCleanupHost>());
|
||||
return bffBuilder;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
|
@ -263,7 +263,7 @@ internal sealed class UserSessionStore(
|
|||
removed += found;
|
||||
try
|
||||
{
|
||||
await sessionDbContext.SaveChangesAsync(ct);
|
||||
_ = await sessionDbContext.SaveChangesAsync(ct);
|
||||
}
|
||||
catch (DbUpdateConcurrencyException ex)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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<UserSessionEntity>(entity =>
|
||||
_ = modelBuilder.Entity<UserSessionEntity>(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<PartitionKeyConverter>().HasMaxLength(200);
|
||||
entity.Property(x => x.Key).HasConversion<UserKeyConverter>().IsRequired().HasMaxLength(200);
|
||||
entity.Property(x => x.SubjectId).IsRequired().HasMaxLength(200);
|
||||
entity.Property(x => x.Ticket).IsRequired();
|
||||
_ = entity.Property(x => x.PartitionKey).HasConversion<PartitionKeyConverter>().HasMaxLength(200);
|
||||
_ = entity.Property(x => x.Key).HasConversion<UserKeyConverter>().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);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<BffOptions>(opt =>
|
||||
_ = builder.Services.Configure<BffOptions>(opt =>
|
||||
{
|
||||
opt.MiddlewareLoaders.Add(app =>
|
||||
{
|
||||
app.UseBffRemoteRoutes();
|
||||
_ = app.UseBffRemoteRoutes();
|
||||
});
|
||||
});
|
||||
builder.Services.AddHttpForwarder();
|
||||
builder.Services.AddSingleton<RemoteRouteHandler>();
|
||||
_ = builder.Services.AddHttpForwarder();
|
||||
_ = builder.Services.AddSingleton<RemoteRouteHandler>();
|
||||
|
||||
builder.Services.AddSingleton<IBffPluginLoader, ProxyBffPluginLoader>();
|
||||
_ = builder.Services.AddSingleton<IBffPluginLoader, ProxyBffPluginLoader>();
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -45,12 +45,12 @@ internal class AccessTokenTransformProvider(IOptions<BffOptions> options, ILogge
|
|||
var values = new HashSet<string>();
|
||||
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<BffOptions> options, ILogge
|
|||
return;
|
||||
}
|
||||
|
||||
transformBuildContext.AddRequestTransform(async transformContext =>
|
||||
_ = transformBuildContext.AddRequestTransform(async transformContext =>
|
||||
{
|
||||
transformContext.HttpContext.CheckForBffMiddleware(_options);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ public static class ReverseProxyBuilderExtensions
|
|||
/// <returns></returns>
|
||||
public static IReverseProxyBuilder AddBffExtensions(this IReverseProxyBuilder builder)
|
||||
{
|
||||
builder.AddTransforms<AccessTokenTransformProvider>();
|
||||
_ = builder.AddTransforms<AccessTokenTransformProvider>();
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ public readonly record struct DPoPProofKey : IStronglyTypedValue<DPoPProofKey>
|
|||
message = string.Empty;
|
||||
try
|
||||
{
|
||||
JsonWebKey.Create(value);
|
||||
_ = JsonWebKey.Create(value);
|
||||
return true;
|
||||
}
|
||||
catch (JsonException e)
|
||||
|
|
|
|||
|
|
@ -4,9 +4,6 @@
|
|||
<TargetFramework>net10.0</TargetFramework>
|
||||
<AssemblyName>Duende.BFF</AssemblyName>
|
||||
<Description>Backend for frontend (BFF) host for ASP.NET Core</Description>
|
||||
<!-- Related to https://github.com/dotnet/sdk/issues/50676-->
|
||||
<!-- <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>-->
|
||||
<!-- <CompilerGeneratedFilesOutputPath>Otel/Generated</CompilerGeneratedFilesOutputPath>-->
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,103 +34,103 @@ public static class BffBuilderExtensions
|
|||
public static T ConfigureOpenIdConnect<T>(this T builder, Action<OpenIdConnectOptions> oidc)
|
||||
where T : IBffBuilder
|
||||
{
|
||||
builder.Services.Configure<BffOptions>(bffOptions => bffOptions.ConfigureOpenIdConnectDefaults += oidc);
|
||||
_ = builder.Services.Configure<BffOptions>(bffOptions => bffOptions.ConfigureOpenIdConnectDefaults += oidc);
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static T ConfigureCookies<T>(this T builder, Action<CookieAuthenticationOptions> oidc)
|
||||
where T : IBffBuilder
|
||||
{
|
||||
builder.Services.Configure<BffOptions>(bffOptions => bffOptions.ConfigureCookieDefaults += oidc);
|
||||
_ = builder.Services.Configure<BffOptions>(bffOptions => bffOptions.ConfigureCookieDefaults += oidc);
|
||||
return builder;
|
||||
}
|
||||
|
||||
internal static T AddBaseBffServices<T>(this T builder) where T : IBffServicesBuilder
|
||||
{
|
||||
builder.Services.AddSingleton<GetLicenseKey>(sp =>
|
||||
_ = builder.Services.AddSingleton<GetLicenseKey>(sp =>
|
||||
() => sp.GetRequiredService<IOptions<BffOptions>>().Value.LicenseKey);
|
||||
builder.Services.AddSingleton<License>(sp =>
|
||||
_ = builder.Services.AddSingleton<License>(sp =>
|
||||
{
|
||||
var accessor = sp.GetRequiredService<LicenseAccessor>();
|
||||
return accessor.Current;
|
||||
});
|
||||
builder.Services.AddSingleton<LicenseAccessor>();
|
||||
_ = builder.Services.AddSingleton<LicenseAccessor>();
|
||||
builder.Services.TryAddSingleton<LicenseValidator>();
|
||||
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<IConfigureOptions<OpenIdConnectOptions>, BffConfigureOpenIdConnectOptions>();
|
||||
builder.Services.AddOpenIdConnectAccessTokenManagement();
|
||||
_ = builder.Services.AddSingleton<IConfigureOptions<OpenIdConnectOptions>, BffConfigureOpenIdConnectOptions>();
|
||||
_ = builder.Services.AddOpenIdConnectAccessTokenManagement();
|
||||
|
||||
builder.Services
|
||||
_ = builder.Services
|
||||
.AddSingleton<IConfigureOptions<UserTokenManagementOptions>, ConfigureUserTokenManagementOptions>();
|
||||
|
||||
builder.Services.AddTransient<IReturnUrlValidator, LocalUrlReturnUrlValidator>();
|
||||
_ = builder.Services.AddTransient<IReturnUrlValidator, LocalUrlReturnUrlValidator>();
|
||||
builder.Services.TryAddSingleton<IAccessTokenRetriever, DefaultAccessTokenRetriever>();
|
||||
|
||||
// management endpoints
|
||||
builder.Services.AddTransient<ILoginEndpoint, DefaultLoginEndpoint>();
|
||||
_ = builder.Services.AddTransient<ILoginEndpoint, DefaultLoginEndpoint>();
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
builder.Services.AddTransient<ISilentLoginEndpoint, DefaultSilentLoginEndpoint>();
|
||||
_ = builder.Services.AddTransient<ISilentLoginEndpoint, DefaultSilentLoginEndpoint>();
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
builder.Services.AddTransient<ISilentLoginCallbackEndpoint, DefaultSilentLoginCallbackEndpoint>();
|
||||
builder.Services.AddTransient<ILogoutEndpoint, DefaultLogoutEndpoint>();
|
||||
builder.Services.AddTransient<IUserEndpoint, DefaultUserEndpoint>();
|
||||
builder.Services.AddTransient<IBackchannelLogoutEndpoint, DefaultBackchannelLogoutEndpoint>();
|
||||
builder.Services.AddTransient<IDiagnosticsEndpoint, DefaultDiagnosticsEndpoint>();
|
||||
_ = builder.Services.AddTransient<ISilentLoginCallbackEndpoint, DefaultSilentLoginCallbackEndpoint>();
|
||||
_ = builder.Services.AddTransient<ILogoutEndpoint, DefaultLogoutEndpoint>();
|
||||
_ = builder.Services.AddTransient<IUserEndpoint, DefaultUserEndpoint>();
|
||||
_ = builder.Services.AddTransient<IBackchannelLogoutEndpoint, DefaultBackchannelLogoutEndpoint>();
|
||||
_ = builder.Services.AddTransient<IDiagnosticsEndpoint, DefaultDiagnosticsEndpoint>();
|
||||
|
||||
// session management
|
||||
builder.Services.TryAddTransient<ISessionRevocationService, NopSessionRevocationService>();
|
||||
|
||||
// cookie configuration
|
||||
builder.Services
|
||||
_ = builder.Services
|
||||
.AddSingleton<IPostConfigureOptions<CookieAuthenticationOptions>, PostConfigureSlidingExpirationCheck>();
|
||||
builder.Services
|
||||
_ = builder.Services
|
||||
.AddSingleton<IPostConfigureOptions<CookieAuthenticationOptions>,
|
||||
PostConfigureApplicationCookieRevokeRefreshToken>();
|
||||
builder.Services.AddSingleton<ActiveCookieAuthenticationScheme>();
|
||||
builder.Services.AddSingleton<ActiveOpenIdConnectAuthenticationScheme>();
|
||||
_ = builder.Services.AddSingleton<ActiveCookieAuthenticationScheme>();
|
||||
_ = builder.Services.AddSingleton<ActiveOpenIdConnectAuthenticationScheme>();
|
||||
|
||||
builder.Services
|
||||
_ = builder.Services
|
||||
.AddSingleton<IPostConfigureOptions<OpenIdConnectOptions>, PostConfigureOidcOptionsForSilentLogin>();
|
||||
|
||||
builder.Services.AddSingleton<TrialModeAuthenticatedSessionTracker>();
|
||||
builder.Services
|
||||
_ = builder.Services.AddSingleton<TrialModeAuthenticatedSessionTracker>();
|
||||
_ = builder.Services
|
||||
.AddSingleton<IPostConfigureOptions<CookieAuthenticationOptions>,
|
||||
PostConfigureApplicationCookieTrialModeCheck>();
|
||||
|
||||
AddBffMetrics(builder);
|
||||
|
||||
// wrap ASP.NET Core
|
||||
builder.Services.AddAuthentication();
|
||||
_ = builder.Services.AddAuthentication();
|
||||
builder.Services.AddTransientDecorator<IAuthenticationService, BffAuthenticationService>();
|
||||
|
||||
// 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<BuildUserSessionPartitionKey>(sp =>
|
||||
_ = builder.Services.AddSingleton<BuildUserSessionPartitionKey>(sp =>
|
||||
sp.GetRequiredService<UserSessionPartitionKeyBuilder>().BuildPartitionKey);
|
||||
builder.Services.AddSingleton<UserSessionPartitionKeyBuilder>();
|
||||
_ = builder.Services.AddSingleton<UserSessionPartitionKeyBuilder>();
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
internal static void AddBffMetrics<T>(T builder) where T : IBffBuilder =>
|
||||
builder.Services.AddSingleton<BffMetrics>();
|
||||
_ = builder.Services.AddSingleton<BffMetrics>();
|
||||
|
||||
internal static T AddDiagnostics<T>(this T builder)
|
||||
where T : IBffServicesBuilder
|
||||
{
|
||||
builder.Services.AddSingleton<IDiagnosticEntry, BasicServerInfoDiagnosticEntry>();
|
||||
builder.Services.AddSingleton<IDiagnosticEntry, AssemblyInfoDiagnosticEntry>();
|
||||
builder.Services.AddSingleton<IDiagnosticEntry, FrontendCountDiagnosticEntry>();
|
||||
builder.Services.AddSingleton<DiagnosticSummary>();
|
||||
builder.Services.AddSingleton(serviceProvider => new DiagnosticDataService(
|
||||
_ = builder.Services.AddSingleton<IDiagnosticEntry, BasicServerInfoDiagnosticEntry>();
|
||||
_ = builder.Services.AddSingleton<IDiagnosticEntry, AssemblyInfoDiagnosticEntry>();
|
||||
_ = builder.Services.AddSingleton<IDiagnosticEntry, FrontendCountDiagnosticEntry>();
|
||||
_ = builder.Services.AddSingleton<DiagnosticSummary>();
|
||||
_ = builder.Services.AddSingleton(serviceProvider => new DiagnosticDataService(
|
||||
serviceProvider.GetRequiredService<TimeProvider>().GetUtcNow().UtcDateTime,
|
||||
serviceProvider.GetServices<IDiagnosticEntry>()));
|
||||
builder.Services.AddHostedService<DiagnosticHostedService>();
|
||||
_ = builder.Services.AddHostedService<DiagnosticHostedService>();
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
|
@ -138,31 +138,31 @@ public static class BffBuilderExtensions
|
|||
internal static T AddDynamicFrontends<T>(this T builder)
|
||||
where T : IBffServicesBuilder
|
||||
{
|
||||
builder.Services.AddHybridCache();
|
||||
_ = builder.Services.AddHybridCache();
|
||||
|
||||
builder.Services.AddHostedService<BffCacheClearingHostedService>();
|
||||
_ = builder.Services.AddHostedService<BffCacheClearingHostedService>();
|
||||
|
||||
builder.Services.AddTransient<IStartupFilter, ConfigureBffStartupFilter>();
|
||||
_ = builder.Services.AddTransient<IStartupFilter, ConfigureBffStartupFilter>();
|
||||
|
||||
// Register the frontend collection, which will be used to store and retrieve frontends
|
||||
builder.Services.AddSingleton<FrontendCollection>();
|
||||
_ = builder.Services.AddSingleton<FrontendCollection>();
|
||||
// Add a public accessible interface to the frontend collection, so our users can access it
|
||||
builder.Services.AddSingleton<IFrontendCollection>((sp) => sp.GetRequiredService<FrontendCollection>());
|
||||
_ = builder.Services.AddSingleton<IFrontendCollection>((sp) => sp.GetRequiredService<FrontendCollection>());
|
||||
|
||||
builder.Services.AddTransient<CurrentFrontendAccessor>();
|
||||
builder.Services.AddSingleton<FrontendSelector>();
|
||||
_ = builder.Services.AddTransient<CurrentFrontendAccessor>();
|
||||
_ = builder.Services.AddSingleton<FrontendSelector>();
|
||||
|
||||
// Add a scheme provider that will inject authentication schemes that are needed for the BFF
|
||||
builder.Services.AddTransient<IAuthenticationSchemeProvider, BffAuthenticationSchemeProvider>();
|
||||
_ = builder.Services.AddTransient<IAuthenticationSchemeProvider, BffAuthenticationSchemeProvider>();
|
||||
|
||||
// Configure the AspNet Core Authentication settings if no
|
||||
// .AddAuthentication().AddCookie().AddOpenIdConnect() was added
|
||||
builder.Services
|
||||
_ = builder.Services
|
||||
.AddSingleton<IPostConfigureOptions<AuthenticationOptions>, BffConfigureAuthenticationOptions>();
|
||||
|
||||
builder.Services.AddSingleton<IConfigureOptions<CookieAuthenticationOptions>, BffConfigureCookieOptions>();
|
||||
_ = builder.Services.AddSingleton<IConfigureOptions<CookieAuthenticationOptions>, 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<HttpClientFactoryOptions>(indexHtmlClientBuilder.Name, options =>
|
||||
_ = services.Configure<HttpClientFactoryOptions>(indexHtmlClientBuilder.Name, options =>
|
||||
{
|
||||
options.HttpMessageHandlerBuilderActions.Add(httpMessageHandlerBuilder =>
|
||||
{
|
||||
|
|
@ -215,16 +215,16 @@ public static class BffBuilderExtensions
|
|||
|
||||
internal static void AddServerSideSessionsSupportingServices(this IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<BuildUserSessionPartitionKey>(sp =>
|
||||
_ = services.AddSingleton<BuildUserSessionPartitionKey>(sp =>
|
||||
sp.GetRequiredService<UserSessionPartitionKeyBuilder>().BuildPartitionKey);
|
||||
services.AddSingleton<UserSessionPartitionKeyBuilder>();
|
||||
_ = services.AddSingleton<UserSessionPartitionKeyBuilder>();
|
||||
|
||||
services.AddSingleton<UserSessionPartitionKeyBuilder>();
|
||||
services
|
||||
_ = services.AddSingleton<UserSessionPartitionKeyBuilder>();
|
||||
_ = services
|
||||
.AddSingleton<IPostConfigureOptions<CookieAuthenticationOptions>,
|
||||
PostConfigureApplicationCookieTicketStore>();
|
||||
services.AddTransient<IServerTicketStore, ServerSideTicketStore>();
|
||||
services.AddTransient<ISessionRevocationService, SessionRevocationService>();
|
||||
_ = services.AddTransient<IServerTicketStore, ServerSideTicketStore>();
|
||||
_ = services.AddTransient<ISessionRevocationService, SessionRevocationService>();
|
||||
// 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<IUserSessionStore, T>();
|
||||
builder.AddServerSideSessions();
|
||||
_ = builder.Services.AddTransient<IUserSessionStore, T>();
|
||||
_ = builder.AddServerSideSessions();
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ public static class BffEndpointRouteBuilderExtensions
|
|||
return;
|
||||
}
|
||||
|
||||
endpoints.Map(options.LoginPath.Value!, ProcessWith<ILoginEndpoint>)
|
||||
_ = endpoints.Map(options.LoginPath.Value!, ProcessWith<ILoginEndpoint>)
|
||||
.WithMetadata(new BffUiEndpointAttribute())
|
||||
.AllowAnonymous();
|
||||
}
|
||||
|
|
@ -91,7 +91,7 @@ public static class BffEndpointRouteBuilderExtensions
|
|||
|
||||
if (!endpoints.AlreadyMappedManagementEndpoint(options.SilentLoginPath))
|
||||
{
|
||||
endpoints.MapGet(options.SilentLoginPath.Value!, ProcessWith<ISilentLoginEndpoint>)
|
||||
_ = endpoints.MapGet(options.SilentLoginPath.Value!, ProcessWith<ISilentLoginEndpoint>)
|
||||
.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<ISilentLoginCallbackEndpoint>)
|
||||
_ = endpoints.MapGet(options.SilentLoginCallbackPath.Value!, ProcessWith<ISilentLoginCallbackEndpoint>)
|
||||
.WithMetadata(new BffUiEndpointAttribute())
|
||||
.AllowAnonymous();
|
||||
}
|
||||
|
|
@ -121,7 +121,7 @@ public static class BffEndpointRouteBuilderExtensions
|
|||
return;
|
||||
}
|
||||
|
||||
endpoints.MapGet(options.LogoutPath.Value!, ProcessWith<ILogoutEndpoint>)
|
||||
_ = endpoints.MapGet(options.LogoutPath.Value!, ProcessWith<ILogoutEndpoint>)
|
||||
.WithName("Logout")
|
||||
.WithMetadata(new BffUiEndpointAttribute())
|
||||
.AllowAnonymous();
|
||||
|
|
@ -143,7 +143,7 @@ public static class BffEndpointRouteBuilderExtensions
|
|||
return;
|
||||
}
|
||||
|
||||
endpoints.MapGet(options.UserPath.Value!, ProcessWith<IUserEndpoint>)
|
||||
_ = endpoints.MapGet(options.UserPath.Value!, ProcessWith<IUserEndpoint>)
|
||||
.AllowAnonymous()
|
||||
.AsBffApiEndpoint();
|
||||
}
|
||||
|
|
@ -164,7 +164,7 @@ public static class BffEndpointRouteBuilderExtensions
|
|||
return;
|
||||
}
|
||||
|
||||
endpoints.MapPost(options.BackChannelLogoutPath.Value!, ProcessWith<IBackchannelLogoutEndpoint>)
|
||||
_ = endpoints.MapPost(options.BackChannelLogoutPath.Value!, ProcessWith<IBackchannelLogoutEndpoint>)
|
||||
.AllowAnonymous();
|
||||
}
|
||||
|
||||
|
|
@ -184,7 +184,7 @@ public static class BffEndpointRouteBuilderExtensions
|
|||
return;
|
||||
}
|
||||
|
||||
endpoints.MapGet(options.DiagnosticsPath.Value!, ProcessWith<IDiagnosticsEndpoint>)
|
||||
_ = endpoints.MapGet(options.DiagnosticsPath.Value!, ProcessWith<IDiagnosticsEndpoint>)
|
||||
.AllowAnonymous();
|
||||
}
|
||||
|
||||
|
|
@ -201,6 +201,6 @@ public static class BffEndpointRouteBuilderExtensions
|
|||
internal static void CheckLicense(this IServiceProvider serviceProvider)
|
||||
{
|
||||
var license = serviceProvider.GetRequiredService<LicenseValidator>();
|
||||
license.CheckLicense();
|
||||
_ = license.CheckLicense();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue