Skip to content

Add .NET server_token_refresh sample#30

Merged
ksroda-sa merged 8 commits into
mainfrom
feature/dotnet-token-refresh-sample
Apr 23, 2026
Merged

Add .NET server_token_refresh sample#30
ksroda-sa merged 8 commits into
mainfrom
feature/dotnet-token-refresh-sample

Conversation

@ksroda-sa

Copy link
Copy Markdown
Collaborator

Summary

Adds the second .NET sample — server_token_refresh — demonstrating server-side refresh-token handling on top of ASP.NET Core cookie auth + OpenID Connect middleware.

  • samples/dotnet/token-refresh/ — Minimal API on https://localhost:4260 using Duende.IdentityModel for the token-endpoint call
  • Parallels the Node server_token_refresh sample: manual POST /refresh form + automatic refresh via the cookie auth OnValidatePrincipal event

Approach

  • Duende.IdentityModel helpersGetDiscoveryDocumentAsync + RequestRefreshTokenAsync — instead of hand-rolled HttpClient calls. Showcases how .NET developers typically integrate with OIDC providers beyond what the built-in middleware covers.
  • IHttpClientFactory seam — tests swap in a fake HttpMessageHandler to intercept discovery/JWKS/token traffic.
  • Refresh persisted in the encrypted auth cookie via SaveTokens = true; AuthenticationProperties.UpdateTokenValue(...) writes fresh tokens back on each refresh.
  • Auto-refresh trigger: CookieAuthenticationOptions.Events.OnValidatePrincipal fires on every authenticated request; the handler refreshes when expires_at - now < 60s and sets ctx.ShouldRenew = true so the cookie re-emits with updated tokens.
  • Same conventions as login-auth-code: port 4260, RequireEnv helper, Env.TraversePath().NoClobber().Load(), MapInboundClaims = false, no per-sample .gitignore.

🤖 Generated with Claude Code

ksroda-sa and others added 4 commits April 23, 2026 11:58
…notes

Code review caught that RefreshTokensAsync fetches the discovery
document on every refresh call. For a teaching sample that's fine,
but readers copying the pattern to prod would eat an extra round-trip
per refresh. README production-notes now says so.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ksroda-sa ksroda-sa requested a review from Copilot April 23, 2026 10:51
@ksroda-sa ksroda-sa marked this pull request as ready for review April 23, 2026 10:51

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new .NET server_token_refresh sample demonstrating refresh-token handling with ASP.NET Core cookie auth + OpenID Connect, aligned with the existing Node scenario.

Changes:

  • Added samples/dotnet/token-refresh sample app implementing manual refresh (POST /refresh) and auto-refresh via CookieAuthenticationEvents.OnValidatePrincipal.
  • Added an integration test project for the new sample with a fake token/discovery endpoint handler.
  • Wired the new .NET scenario into the repo’s snippet and scenario manifests (snippets.json, snippet-manifest.yaml, samples/dotnet/manifest.yaml).

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
snippets.json Registers the new .NET snippet steps for server_token_refresh.
snippet-manifest.yaml Adds dotnet to the server_token_refresh scenario frameworks list.
samples/dotnet/token-refresh/token-refresh.sln New solution for the sample and its tests.
samples/dotnet/token-refresh/src/token-refresh.csproj New web project with OIDC + Duende.IdentityModel dependencies.
samples/dotnet/token-refresh/src/Program.cs Implements cookie+OIDC login, manual refresh, and auto-refresh-on-validate logic.
samples/dotnet/token-refresh/tests/token-refresh.tests.csproj New xUnit test project for the sample.
samples/dotnet/token-refresh/tests/TestAuthHandler.cs Test auth handler that injects tokens into AuthenticationProperties.
samples/dotnet/token-refresh/tests/FakeTokenEndpointHandler.cs Fake discovery/JWKS/token endpoints + test IHttpClientFactory.
samples/dotnet/token-refresh/tests/AuthIntegrationTests.cs Integration tests covering root/login/refresh/logout flows.
samples/dotnet/token-refresh/README.md Sample documentation and production notes.
samples/dotnet/token-refresh/.env.example Example env configuration for running the sample.
samples/dotnet/manifest.yaml Adds the server_token_refresh scenario metadata for .NET.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread samples/dotnet/token-refresh/src/Program.cs
Comment thread samples/dotnet/token-refresh/src/Program.cs
Comment thread samples/dotnet/token-refresh/src/Program.cs
ksroda-sa and others added 4 commits April 23, 2026 13:02
- Catch exceptions from RefreshTokensAsync in /refresh handler so
  discovery/network failures render the error page instead of 500ing
  (addresses Copilot PR #30 review)
- Set ClientCredentialStyle.PostBody on RefreshTokenRequest to match
  ASP.NET Core OIDC middleware default; fixes 401 Unauthorized from
  SecureAuth clients configured with client_secret_post

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The manifestLib fallback caused .NET snippets to emit a NuGet package
name as "install", which the Quickstart UI renders as `npm install <pkg>`.
Non-npm projects (.NET) declare packages in .csproj and install via the
run_command's dotnet restore, so leave install empty.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The refresh step uses Duende.IdentityModel types, but the `using`
lived outside any @snippet tag so the Quickstart UI never showed it.
Include the imports (and rename step 1's description) so readers see
the required package.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ksroda-sa ksroda-sa merged commit f413fb3 into main Apr 23, 2026
27 checks passed
@ksroda-sa ksroda-sa deleted the feature/dotnet-token-refresh-sample branch April 23, 2026 11:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants