Use public/private key in bit Boilerplate for data protection and jwt issue/validation (#12120)#12121
Conversation
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughReplaces symmetric JWT signing with RSA/X509-based signing via a new AppCertificateService, adds OpenID discovery and JWKS endpoints, removes JwtIssuerSigningKeySecret from configuration and docs, updates data protection to use certificates, and adjusts authentication middleware to use JwtBearer with certificate-backed validation. Changes
Sequence DiagramssequenceDiagram
participant Client as Client
participant API as Server.Api
participant CertSvc as AppCertificateService
participant OpenID as /.well-known/openid-configuration & jwks
participant Validator as Token Validator / Resource Server
Note over API,CertSvc: Startup / init
API->>CertSvc: GetAppCertificate()
CertSvc->>CertSvc: Load PEMs & cache X509
CertSvc-->>API: X509Certificate2
Note over API: Token issuance
API->>CertSvc: GetPrivateSecurityKey()
CertSvc-->>API: RsaSecurityKey (private)
API->>API: Sign JWT using RS256
API-->>Client: Return signed JWT
Note over Client,OpenID: Discovery
Client->>OpenID: GET /.well-known/openid-configuration
OpenID->>CertSvc: GetPublicSecurityKey()
CertSvc-->>OpenID: RsaSecurityKey (public)
OpenID-->>Client: issuer, jwks_uri
Note over Validator,OpenID: Validation flow
Validator->>OpenID: GET jwks_uri
OpenID-->>Validator: JWK (public RSA)
Validator->>Validator: Validate JWT signature with public key
Validator-->>Client: Access allowed / denied
Estimated Code Review Effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Infrastructure/Services/AppCertificateService.cs (1)
16-31: Thread-safety issue in lazy initialization ofappCert.
GetAppCertificate()has a classic check-then-act race: two threads can both seeappCert is null, both load the certificate, and one silently overwrites the other's assignment. While not catastrophic, this can cause subtle issues on platforms where theX509Certificate2fromCreateFromPemFileneeds special handling (e.g., ephemeral keys on Linux).Consider using
Lazy<T>or a simple lock for thread-safe initialization:♻️ Suggested refactor
public static class AppCertificateService { - private static X509Certificate2? appCert; + private static readonly Lazy<X509Certificate2> appCert = new(LoadCertificate); public static X509Certificate2 GetAppCertificate() { - if (appCert is not null) - return appCert; + return appCert.Value; + } - var certPath = Path.Combine(AppContext.BaseDirectory, "AppCertificate.Cert.pem"); - var keyPath = Path.Combine(AppContext.BaseDirectory, "AppCertificate.Private.pem"); - - appCert = X509Certificate2.CreateFromPemFile(certPath, keyPath); - - if (AppEnvironment.IsDevelopment() is false && appCert.Thumbprint is "189C12DB3EEF0A151E3F596DCD807CD2ECA0A26C") - throw new InvalidOperationException("You are using the default self-signed certificate in non-development environment. Please use a secure certificate in production."); - - return appCert; - } + private static X509Certificate2 LoadCertificate() + { + var certPath = Path.Combine(AppContext.BaseDirectory, "AppCertificate.Cert.pem"); + var keyPath = Path.Combine(AppContext.BaseDirectory, "AppCertificate.Private.pem"); + + var cert = X509Certificate2.CreateFromPemFile(certPath, keyPath); + + if (AppEnvironment.IsDevelopment() is false && cert.Thumbprint is "189C12DB3EEF0A151E3F596DCD807CD2ECA0A26C") + throw new InvalidOperationException("You are using the default self-signed certificate in non-development environment. Please use a secure certificate in production."); + + return cert; + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Infrastructure/Services/AppCertificateService.cs` around lines 16 - 31, GetAppCertificate contains a race on the shared field appCert: two threads can both see appCert null and call X509Certificate2.CreateFromPemFile, leading to duplicate/overwritten instances; fix by making initialization thread-safe (either replace appCert with a Lazy<X509Certificate2> initialized with a factory that calls X509Certificate2.CreateFromPemFile, or implement a lock and double-check pattern inside GetAppCertificate to ensure only one thread creates and assigns appCert), keeping the existing thumbprint/env check after the single creation; reference symbols: GetAppCertificate, appCert, X509Certificate2.CreateFromPemFile.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/AppCertificate.md`:
- Around line 49-51: Fix the typo in the README header line that currently reads
"# 3. Generate a self-signed X.509 certificate (valid for 1 years)" by changing
"1 years" to "1 year"; optionally consider updating the parenthetical to a
clearer duration like "365 days" or "3650 days (10 years)" if you prefer a
longer non-production validity while keeping the note that production certs
should be rotated regularly.
- Around line 26-36: Update the Data Protection section to clarify that
ProtectKeysWithCertificate (and the public/private certificate pair) is used to
encrypt the data protection key ring (the persisted XML keys), not the
application payloads themselves; state that cookies/anti-forgery tokens are
encrypted/decrypted by symmetric keys derived from that key ring, while the
certificate protects the key ring for cross-instance/load-balanced scenarios,
and mention the public key encrypts the key ring while the private key decrypts
it (or signs/unwraps depending on implementation).
In
`@src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Infrastructure/Services/AppCertificateService.cs`:
- Around line 36-47: GetPrivateSecurityKey() and GetPublicSecurityKey()
currently call GetAppCertificate().GetRSAPrivateKey()/GetRSAPublicKey() on every
invocation, creating new unmanaged RSA instances that are leaked; change this by
adding static readonly (or static) fields (e.g., _privateSecurityKey and
_publicSecurityKey) and initialize them lazily (using ??= or Lazy<T>) inside
GetPrivateSecurityKey() and GetPublicSecurityKey() so the RsaSecurityKey
wrapping the RSA is created only once and reused; keep GetAppCertificate() as
the source but ensure the RSA is obtained once and stored in the static
RsaSecurityKey fields to prevent repeated unmanaged handle allocation.
In
`@src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Program.Middlewares.cs`:
- Around line 93-110: The MapOpenIdConfiguration method advertises a jwks_uri
but never serves it; add a second app.MapGet for "/.well-known/jwks" inside
MapOpenIdConfiguration that returns a JSON object with a "keys" array containing
the previously created jwk (the jwk variable from ConvertFromRSASecurityKey) so
consumers can fetch the public key; ensure the endpoint is anonymous/public (no
auth) and returns application/json with the shape { keys = new[] { jwk } } and
keep it alongside the existing "/.well-known/openid-configuration" mapping.
- Around line 95-97: The JWKS entry sets jwk.Kid = "Boilerplate" but the signing
key used in AppJwtSecureDataFormat.Protect() is an RsaSecurityKey without KeyId,
so produced JWTs lack a matching kid; fix by assigning the same KeyId
("Boilerplate") to the RsaSecurityKey returned by
AppCertificateService.GetPrivateSecurityKey() (or set KeyId on that key instance
right before creating new SigningCredentials in
AppJwtSecureDataFormat.Protect()), ensuring the RsaSecurityKey.KeyId matches the
published jwk.Kid and the SigningCredentials include the key id.
---
Nitpick comments:
In
`@src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Infrastructure/Services/AppCertificateService.cs`:
- Around line 16-31: GetAppCertificate contains a race on the shared field
appCert: two threads can both see appCert null and call
X509Certificate2.CreateFromPemFile, leading to duplicate/overwritten instances;
fix by making initialization thread-safe (either replace appCert with a
Lazy<X509Certificate2> initialized with a factory that calls
X509Certificate2.CreateFromPemFile, or implement a lock and double-check pattern
inside GetAppCertificate to ensure only one thread creates and assigns appCert),
keeping the existing thumbprint/env check after the single creation; reference
symbols: GetAppCertificate, appCert, X509Certificate2.CreateFromPemFile.
src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/AppCertificate.md
Show resolved
Hide resolved
src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/AppCertificate.md
Outdated
Show resolved
Hide resolved
...ilerplate/src/Server/Boilerplate.Server.Api/Infrastructure/Services/AppCertificateService.cs
Show resolved
Hide resolved
...mplates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Program.Middlewares.cs
Outdated
Show resolved
Hide resolved
...mplates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Program.Middlewares.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Updates the Bit.Boilerplate server template to move JWT signing/validation and Data Protection key protection from a shared symmetric secret to an X.509 certificate (public/private key pair), and starts exposing OIDC discovery metadata for downstream JWT validation.
Changes:
- Removed
JwtIssuerSigningKeySecretconfiguration and related validation from server settings. - Protected ASP.NET Core Data Protection keys with an X.509 certificate and switched JWT signing/validation to RS256 using that certificate.
- Added certificate artifacts/docs and introduced an OIDC discovery endpoint stub.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Web/appsettings.json | Removes JWT symmetric signing secret from web config. |
| src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Web/Infrastructure/Services/SimpleJwtSecureDataFormat.cs | Updates comments to reflect new validation approach in Server.Api. |
| src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Web/Boilerplate.Server.Web.csproj | Copies certificate artifacts into Server.Web output (needed for integrated hosting). |
| src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/appsettings.json | Removes JWT symmetric signing secret from API config. |
| src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/ServerApiSettings.cs | Removes secret length/default-value validation and the secret property. |
| src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Program.Services.cs | Protects Data Protection keys with the app certificate. |
| src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Program.Middlewares.cs | Adds OIDC discovery endpoint mapping (currently incomplete). |
| src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Infrastructure/Services/AppCertificateService.cs | Adds certificate-loading helpers and RSA key extraction for JWT + DP. |
| src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Features/Identity/Services/AppJwtSecureDataFormat.cs | Switches JWT signing/validation from HS512 to RS256 using certificate keys. |
| src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Boilerplate.Server.Api.csproj | Ensures certificate PEM files are copied to output. |
| src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/AppCertificate.md | Documents certificate generation and intended OIDC/JWKS integration. |
| src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/AppCertificate.Public.pem | Adds public key PEM (template artifact). |
| src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/AppCertificate.Private.pem | Adds private key PEM (template artifact). |
| src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/AppCertificate.Cert.pem | Adds certificate PEM (template artifact). |
...mplates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Program.Middlewares.cs
Show resolved
Hide resolved
...ilerplate/src/Server/Boilerplate.Server.Api/Infrastructure/Services/AppCertificateService.cs
Show resolved
Hide resolved
...tes/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/AppCertificate.Private.pem
Outdated
Show resolved
Hide resolved
src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/AppCertificate.md
Outdated
Show resolved
Hide resolved
...mplates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Program.Middlewares.cs
Outdated
Show resolved
Hide resolved
...ilerplate/src/Server/Boilerplate.Server.Api/Infrastructure/Services/AppCertificateService.cs
Show resolved
Hide resolved
...plate/src/Server/Boilerplate.Server.Api/Features/Identity/Services/AppJwtSecureDataFormat.cs
Show resolved
Hide resolved
...plate/src/Server/Boilerplate.Server.Api/Features/Identity/Services/AppJwtSecureDataFormat.cs
Show resolved
Hide resolved
src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/AppCertificate.md
Show resolved
Hide resolved
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
♻️ Duplicate comments (1)
src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/AppCertificate.md (1)
26-36: Data Protection description is slightly misleading.This was previously flagged:
ProtectKeysWithCertificateencrypts the data protection key ring (persisted XML keys), not the application payloads directly. Cookies/anti-forgery tokens are encrypted by symmetric keys derived from that key ring.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/AppCertificate.md` around lines 26 - 36, The documentation text is misleading: update AppCertificate.md so it clarifies that ProtectKeysWithCertificate protects/encrypts the data protection key ring (the persisted XML keys), not the application payloads directly; explicitly state that cookies/anti-forgery tokens are encrypted by symmetric keys derived from that key ring and mention the key ring term (“data protection key ring / persisted XML keys”) and the API name ProtectKeysWithCertificate to make intent and mechanics clear.
🧹 Nitpick comments (4)
src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/AppCertificate.md (1)
74-111: Example code shows twoTokenValidationParametersassignments inside oneAddJwtBearerblock — clarify they're alternatives.The two assignments to
options.TokenValidationParametersseparated by// OR(line 96) are inside the same lambda, so the second would overwrite the first. Consider structuring these as two separate code blocks (one for strict validation, one for relaxed) to make the alternatives clearer for readers.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/AppCertificate.md` around lines 74 - 111, The example currently assigns options.TokenValidationParameters twice inside the same AddJwtBearer lambda (so the second overwrites the first); split into two separate, clearly labeled code examples instead: one AddJwtBearer snippet showing the strict TokenValidationParameters configuration (with ClockSkew, RequireSignedTokens, ValidateAudience/ValidateIssuer, ValidAudience/ValidIssuer, etc.) and a separate snippet showing the relaxed configuration (ValidateAudience = false and ValidateIssuer/ValidIssuer), or keep only the desired configuration in the single AddJwtBearer block for clarity; update the comments to indicate these are alternatives and ensure only one TokenValidationParameters assignment exists per example.src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Program.Middlewares.cs (1)
100-116: Add.AllowAnonymous()to the OpenID discovery endpoints for explicit security intent.The discovery endpoints (
/.well-known/openid-configurationand/.well-known/jwks) are correctly accessible without authentication today, since noFallbackPolicyis currently configured. However, explicitly marking these endpoints with.AllowAnonymous()is a best practice that:
- Makes the security intent explicit for future maintainers
- Protects against accidental breakage if a fallback authorization policy is added later
- Aligns with OpenID Connect specifications, where discovery endpoints must be public
Proposed change
app.MapGet("/.well-known/openid-configuration", (HttpRequest request) => { var baseUrl = request.GetBaseUrl(); return new { issuer = app.Configuration["Identity:Issuer"], jwks_uri = new Uri(baseUrl, ".well-known/jwks"), }; - }); + }).AllowAnonymous(); app.MapGet("/.well-known/jwks", () => { return new { keys = new[] { jwk } }; - }); + }).AllowAnonymous();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Program.Middlewares.cs` around lines 100 - 116, The OpenID discovery endpoints defined via app.MapGet("/.well-known/openid-configuration", ...) and app.MapGet("/.well-known/jwks", ...) should explicitly allow anonymous access; update both MapGet route registrations to chain .AllowAnonymous() so the discovery JSON (including the jwk variable returned in the jwks handler) remains public regardless of any future fallback authorization policies.src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Web/Boilerplate.Server.Web.csproj (2)
24-24:PackageReferencemixed into aProjectReferenceitem group.The
JwtBearerPackageReferenceis placed in the item group that primarily holdsProjectReferenceentries (lines 22–29), while the dedicatedPackageReferenceitem group already exists at lines 15–20. Moving it there keeps the grouping consistent.♻️ Proposed reorganization
<ItemGroup> <PackageReference Include="Bit.BlazorES2019" /> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" /> <PackageReference Condition=" '$(offlineDb)' == 'true' OR '$(offlineDb)' == ''" Include="Microsoft.EntityFrameworkCore.Tools" PrivateAssets="all" /> <PackageReference Condition=" '$(sentry)' == 'true' OR '$(sentry)' == '' " Include="Sentry.AspNetCore" /> + <PackageReference Condition=" '$(api)' == 'Standalone' " Include="Microsoft.AspNetCore.Authentication.JwtBearer" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\Boilerplate.Server.Shared\Boilerplate.Server.Shared.csproj" /> - <PackageReference Condition=" '$(api)' == 'Standalone' " Include="Microsoft.AspNetCore.Authentication.JwtBearer" /> <ProjectReference Condition=" '$(api)' == 'Integrated' OR '$(api)' == ''" Include="..\Boilerplate.Server.Api\Boilerplate.Server.Api.csproj" /> <ProjectReference Include="..\..\Client\Boilerplate.Client.Web\Boilerplate.Client.Web.csproj" /> <ProjectReference Include="..\..\Client\Boilerplate.Client.Core\Boilerplate.Client.Core.csproj" /> </ItemGroup>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Web/Boilerplate.Server.Web.csproj` at line 24, Move the conditional PackageReference for Microsoft.AspNetCore.Authentication.JwtBearer out of the ProjectReference item group and into the existing PackageReference item group; locate the element that reads <PackageReference Condition=" '$(api)' == 'Standalone' " Include="Microsoft.AspNetCore.Authentication.JwtBearer" /> and cut/paste it into the other <ItemGroup> that contains the other <PackageReference> entries so package references are grouped together and ProjectReference groups remain separate.
44-48:DependentUponself-reference when glob matchesAppCertificate.md.The glob
AppCertificate*will also matchAppCertificate.mditself, so that file gets<DependentUpon>AppCertificate.md</DependentUpon>— a self-reference. Visual Studio typically handles this silently (renders the file at the top level), but it's avoidable by excluding the markdown file from the glob and adding it as a plain entry.♻️ Proposed fix to avoid self-referential DependentUpon
- <None Include="..\Boilerplate.Server.Api\AppCertificate*"> - <Link>%(Filename)%(Extension)</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - <DependentUpon>AppCertificate.md</DependentUpon> - </None> + <None Include="..\Boilerplate.Server.Api\AppCertificate.md"> + <Link>%(Filename)%(Extension)</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="..\Boilerplate.Server.Api\AppCertificate*" Exclude="..\Boilerplate.Server.Api\AppCertificate.md"> + <Link>%(Filename)%(Extension)</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + <DependentUpon>AppCertificate.md</DependentUpon> + </None>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Web/Boilerplate.Server.Web.csproj` around lines 44 - 48, The project file uses a glob <None Include="..\Boilerplate.Server.Api\AppCertificate*"> with <DependentUpon>AppCertificate.md</DependentUpon>, which creates a self-reference because the glob also matches AppCertificate.md; fix this by excluding the markdown from the glob and adding it as a separate item: modify the globbed item (the <None Include="..\Boilerplate.Server.Api\AppCertificate*"> element) to add an Exclude="..\Boilerplate.Server.Api\AppCertificate.md" attribute, and then add a new standalone <None Include="..\Boilerplate.Server.Api\AppCertificate.md"> element without the DependentUpon so AppCertificate.md is a top-level file while other AppCertificate* files retain the DependentUpon behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In
`@src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/AppCertificate.md`:
- Around line 26-36: The documentation text is misleading: update
AppCertificate.md so it clarifies that ProtectKeysWithCertificate
protects/encrypts the data protection key ring (the persisted XML keys), not the
application payloads directly; explicitly state that cookies/anti-forgery tokens
are encrypted by symmetric keys derived from that key ring and mention the key
ring term (“data protection key ring / persisted XML keys”) and the API name
ProtectKeysWithCertificate to make intent and mechanics clear.
---
Nitpick comments:
In
`@src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/AppCertificate.md`:
- Around line 74-111: The example currently assigns
options.TokenValidationParameters twice inside the same AddJwtBearer lambda (so
the second overwrites the first); split into two separate, clearly labeled code
examples instead: one AddJwtBearer snippet showing the strict
TokenValidationParameters configuration (with ClockSkew, RequireSignedTokens,
ValidateAudience/ValidateIssuer, ValidAudience/ValidIssuer, etc.) and a separate
snippet showing the relaxed configuration (ValidateAudience = false and
ValidateIssuer/ValidIssuer), or keep only the desired configuration in the
single AddJwtBearer block for clarity; update the comments to indicate these are
alternatives and ensure only one TokenValidationParameters assignment exists per
example.
In
`@src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Program.Middlewares.cs`:
- Around line 100-116: The OpenID discovery endpoints defined via
app.MapGet("/.well-known/openid-configuration", ...) and
app.MapGet("/.well-known/jwks", ...) should explicitly allow anonymous access;
update both MapGet route registrations to chain .AllowAnonymous() so the
discovery JSON (including the jwk variable returned in the jwks handler) remains
public regardless of any future fallback authorization policies.
In
`@src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Web/Boilerplate.Server.Web.csproj`:
- Line 24: Move the conditional PackageReference for
Microsoft.AspNetCore.Authentication.JwtBearer out of the ProjectReference item
group and into the existing PackageReference item group; locate the element that
reads <PackageReference Condition=" '$(api)' == 'Standalone' "
Include="Microsoft.AspNetCore.Authentication.JwtBearer" /> and cut/paste it into
the other <ItemGroup> that contains the other <PackageReference> entries so
package references are grouped together and ProjectReference groups remain
separate.
- Around line 44-48: The project file uses a glob <None
Include="..\Boilerplate.Server.Api\AppCertificate*"> with
<DependentUpon>AppCertificate.md</DependentUpon>, which creates a self-reference
because the glob also matches AppCertificate.md; fix this by excluding the
markdown from the glob and adding it as a separate item: modify the globbed item
(the <None Include="..\Boilerplate.Server.Api\AppCertificate*"> element) to add
an Exclude="..\Boilerplate.Server.Api\AppCertificate.md" attribute, and then add
a new standalone <None Include="..\Boilerplate.Server.Api\AppCertificate.md">
element without the DependentUpon so AppCertificate.md is a top-level file while
other AppCertificate* files retain the DependentUpon behavior.
ℹ️ Review info
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
📒 Files selected for processing (11)
src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/AppCertificate.mdsrc/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Infrastructure/Extensions/HttpContextExtensions.cssrc/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Infrastructure/Services/AppCertificateService.cssrc/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Program.Middlewares.cssrc/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.AppHost/Program.cssrc/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Shared/Infrastructure/Extensions/HttpContextExtensions.cssrc/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Web/Boilerplate.Server.Web.csprojsrc/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Web/Infrastructure/Services/SimpleJwtSecureDataFormat.cssrc/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Web/Program.Middlewares.cssrc/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Web/Program.Services.cssrc/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Web/appsettings.json
💤 Files with no reviewable changes (2)
- src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Infrastructure/Extensions/HttpContextExtensions.cs
- src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Web/Infrastructure/Services/SimpleJwtSecureDataFormat.cs
closes #12120
Summary by CodeRabbit
New Features
Security
Documentation
Breaking Changes