.NET: AuthN & AuthZ sample with asp.net service and web client#4354
.NET: AuthN & AuthZ sample with asp.net service and web client#4354westey-m wants to merge 4 commits intomicrosoft:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds a comprehensive authentication and authorization sample demonstrating how to secure an AI agent REST API using OAuth 2.0 / OpenID Connect standards. The sample addresses issue #1488 by showcasing dependency injection, user context access in tools, JWT Bearer authentication, and policy-based authorization.
Changes:
- Added a three-component sample (WebClient, AgentService, Keycloak) orchestrated with Docker Compose
- Demonstrates accessing user identity in agent tools via scoped IUserContext service
- Includes GitHub Codespaces support with auto-detection and configuration
- Shows JWT Bearer token validation and scope-based authorization policies
Reviewed changes
Copilot reviewed 24 out of 24 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| docker-compose.yml | Orchestrates Keycloak, AgentService, and WebClient with health checks and Codespaces support |
| keycloak/dev-realm.json | Pre-configured Keycloak realm with test users, scopes, and client definitions |
| keycloak/setup-redirect-uris.sh | Auto-configures Codespaces redirect URIs for OIDC flows |
| README.md | Comprehensive documentation for setup, usage, and key concepts |
| AuthClientServer.AgentService/* | Minimal API with JWT authentication, authorization policies, and DI-based agent |
| AuthClientServer.WebClient/* | Razor Pages app with OIDC login, token forwarding, and chat UI |
| UserContext.cs | Scoped service for accessing current user identity from JWT claims |
| TodoService.cs | Per-user TODO list demonstrating user-aware tool implementation |
| Dockerfiles | Multi-stage builds with proper CPM support via Directory.Packages.props |
| Directory.Packages.props | Added JWT Bearer and OpenIdConnect package versions |
| agent-framework-dotnet.slnx | Solution file updated to include new projects |
| ### Option 1: Docker Compose (Recommended) | ||
|
|
||
| ```bash | ||
| cd samples/AuthClientServer |
There was a problem hiding this comment.
The path shown here is incomplete. Users following this command from the repository root will encounter an error. Change this to: cd dotnet/samples/05-end-to-end/AuthClientServer
| cd samples/AuthClientServer | |
| cd dotnet/samples/05-end-to-end/AuthClientServer |
| CLIENT_UUID=$(curl -sf "$KEYCLOAK_URL/admin/realms/dev/clients?clientId=web-client" \ | ||
| -H "Authorization: Bearer $TOKEN" \ | ||
| | sed -n 's/.*"id":"\([^"]*\)".*/\1/p') | ||
|
|
There was a problem hiding this comment.
Missing error handling for CLIENT_UUID extraction. If the curl command fails or the client is not found, CLIENT_UUID will be empty, causing the subsequent PUT request to target an invalid endpoint. Add validation after line 35:
if [ -z "$CLIENT_UUID" ]; then
echo "ERROR: Failed to find web-client UUID" >&2
exit 1
fi
| if [ -z "$CLIENT_UUID" ]; then | |
| echo "ERROR: Failed to find web-client UUID" >&2 | |
| exit 1 | |
| fi |
| // --------------------------------------------------------------------------- | ||
| // CORS: allow the WebClient origin | ||
| // --------------------------------------------------------------------------- | ||
| builder.Services.AddCors(options => | ||
| options.AddDefaultPolicy(policy => | ||
| policy.WithOrigins("http://localhost:8080") | ||
| .AllowAnyHeader() | ||
| .AllowAnyMethod())); |
There was a problem hiding this comment.
CORS configuration is unnecessary and potentially misleading in this sample. The WebClient calls the AgentService through server-side code (in Chat.cshtml.cs), not from browser JavaScript, so CORS is never checked. Additionally, if CORS were needed, this configuration only allows http://localhost:8080, which would not work in GitHub Codespaces where the actual origin would be the Codespaces tunnel URL. Consider removing this CORS configuration entirely to avoid confusion.
|
|
||
| WebApplication app = builder.Build(); | ||
|
|
||
| app.UseCors(); |
There was a problem hiding this comment.
This middleware is unnecessary since CORS is not needed for this sample. The WebClient makes server-side HTTP requests to the AgentService, not browser-based requests. Remove this line along with the CORS configuration above (lines 73-77).
| app.UseCors(); |
There was a problem hiding this comment.
The name of the project was AuthClientServer but the name of the Server project is AgentService and the Client WebClient.
Ideally suggest renaming the the project to be more clear that this is actually a Minimal Api approach (not MVC) or having both Server.MinimalApi and a Server.Mvc within the same sample for all the tastes.
There was a problem hiding this comment.
For the client might suggest adding Razor in the naming to be clear what is the tech chosen, worth adding a Blazor and a React.
Motivation and Context
#1488
Users are regularly asking about how to access user information in tools and how to authorize tools. This sample shows an example of how authorization and user access could be done from tools in an agent.
Using Keycloak as the auth provider, so that the sample can be run without any external dependencies, but it can easily be swapped out for another auth provider.
Description
Contribution Checklist