.NET: Support ClaimsIdentity-based scoping of agent sessions #5696
.NET: Support ClaimsIdentity-based scoping of agent sessions #5696
Conversation
Add helper for decorator pattern for AgentSessionStore
Add support for using the ASP.Net Core ambient `ClaimsIdentity` User, along with a user-specified claim type to scope the session store based on authenticated identity.
10d1da1 to
f798c0b
Compare
There was a problem hiding this comment.
Automated Code Review
Reviewers: 4 | Confidence: 81%
✓ Correctness
The PR introduces a well-structured decorator pattern for AgentSessionStore (DelegatingAgentSessionStore) and a concrete implementation that scopes sessions by user identity claims (UserIdentityScopedSessionStore). The code correctly follows the existing DelegatingAIAgent pattern, properly handles strict/non-strict modes, and all operations delegate correctly to the inner store with scoped conversation IDs. No correctness bugs found.
✓ Security Reliability
The PR introduces a well-structured decorator pattern for session stores with identity scoping. The security design is sound: strict mode defaults to true (secure by default), null checks are in place, and the delegation pattern is correctly implemented. One moderate defense-in-depth concern exists around the composite key format used for session scoping, where the separator character could theoretically allow key collisions between different user/conversationId combinations.
✓ Test Coverage
The test coverage for both
DelegatingAgentSessionStoreandUserIdentityScopedSessionStoreis solid, covering constructor validation, delegation behavior, strict/non-strict modes, null HttpContext, custom claim types, and multi-user isolation. Two minor gaps exist: (1)UserIdentityScopedSessionStoretests never verify that theCancellationTokenpassed by the caller is forwarded to the inner store (all assertions useIt.IsAny<CancellationToken>()), and (2) there is no test for a claim that exists but has an empty-string value, which would produce the same scoped key as the non-strict no-claim scenario, representing a potential silent collision.
✗ Design Approach
The main design issue is in the new non-strict path for
UserIdentityScopedSessionStore: the docs say missing claims should "proceed without scoping," but the implementation and tests currently re-key those sessions by prepending an empty scope. That silently changes storage identity for anonymous or missing-claim requests instead of preserving the existing conversation key shape.
Flagged Issues
-
UserIdentityScopedSessionStoredocuments non-strict mode as "operations proceed without scoping when the claim is absent" (lines 35-37), but the implementation and tests lock in":{conversationId}"as the scoped key. Because downstream stores likeInMemoryAgentSessionStore.GetKeyalready derive their own key prefix, this silently remaps missing-claim traffic fromagentId:conversationIdtoagentId::conversationIdinstead of leaving it unscoped.
Automated review by lokitoth's agents
There was a problem hiding this comment.
Pull request overview
This PR introduces a decorator foundation for .NET AgentSessionStore implementations and adds an ASP.NET Core-specific session store that scopes conversation/session keys by the current user’s claim from HttpContext, enabling per-user session isolation in multi-user/tenant hosting scenarios.
Changes:
- Added
DelegatingAgentSessionStoreas a decorator-style base for session store composition. - Added
UserIdentityScopedSessionStore(ASP.NET Core) to scope session keys by a selected claim from the ambientHttpContextuser. - Added unit tests and solution/project wiring for the new stores and new ASP.NET Core hosting project.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| dotnet/src/Microsoft.Agents.AI.Hosting/DelegatingAgentSessionStore.cs | Introduces a delegating/decorator base AgentSessionStore implementation. |
| dotnet/src/Microsoft.Agents.AI.Hosting.AspNetCore/UserIdentityScopedSessionStore.cs | Adds an ASP.NET Core session store decorator that scopes keys using IHttpContextAccessor claims. |
| dotnet/src/Microsoft.Agents.AI.Hosting.AspNetCore/Microsoft.Agents.AI.Hosting.AspNetCore.csproj | New ASP.NET Core hosting project/package for the identity-scoped store. |
| dotnet/tests/Microsoft.Agents.AI.Hosting.UnitTests/DelegatingAgentSessionStoreTests.cs | Unit coverage for the delegating store pass-through behavior. |
| dotnet/tests/Microsoft.Agents.AI.Hosting.UnitTests/UserIdentityScopedSessionStoreTests.cs | Unit coverage for claim-based scoping and strict/non-strict behavior. |
| dotnet/tests/Microsoft.Agents.AI.Hosting.UnitTests/Microsoft.Agents.AI.Hosting.UnitTests.csproj | Adds a project reference to the new ASP.NET Core hosting project. |
| dotnet/agent-framework-dotnet.slnx | Includes the new ASP.NET Core hosting project in the solution and minor whitespace normalization. |
Motivation and Context
The current Hosting helpers rely on a single shared
AgentSessionStore, relying onconversationIdorcontextIdcoming from the incoming request, regardless of authentication status. This makes it difficult to use in multi-user/tenant environments.Description
AgentSessionStorewithDelegatingAgentSessionStore- analogous toDelegatingAIAgent->AIAgentUserIdentityScopedSessionStore, which will pick up the ambientClaimsIdentityuser from the ASP.NetHttpContext, grab the first claim matching a user-specified type, and use the value, if any, to scope theAgentSessionto the identity.Contribution Checklist
[ ] Is this a breaking change? If yes, add "[BREAKING]" prefix to the title of the PR.