// Copyright (c) Microsoft. All rights reserved. using System; using System.Linq; using System.Security.Claims; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.Shared.Diagnostics; namespace Microsoft.Agents.AI.Hosting; /// /// A that extracts the session isolation key from a claim /// in the current user's identity, as provided by ASP.NET Core's . /// /// /// /// This provider is suitable for ASP.NET Core web applications where session isolation is based on /// authenticated user identity. It reads a specified claim type (e.g., name, email, or a custom identifier) /// from the ambient . /// /// /// If the is unavailable, the user is not authenticated, or the specified claim /// is missing, the provider returns . The consuming /// will then enforce strict or pass-through behavior based on its configuration. /// /// /// This class relies on , which uses /// to provide access to the current . /// /// public class ClaimsIdentitySessionIsolationKeyProvider : SessionIsolationKeyProvider { private readonly IHttpContextAccessor? _httpContextAccessor; private readonly string _claimType; /// /// Initializes a new instance of the class. /// /// /// The used to retrieve the current HTTP context and user claims. /// /// The options for configuring the provider. If null, defaults are used. /// /// is null, empty, or whitespace. /// public ClaimsIdentitySessionIsolationKeyProvider( IHttpContextAccessor? httpContextAccessor, ClaimsIdentitySessionIsolationKeyProviderOptions? options = null) { options ??= new ClaimsIdentitySessionIsolationKeyProviderOptions(); this._httpContextAccessor = httpContextAccessor; this._claimType = Throw.IfNullOrWhitespace(options.ClaimType); } /// /// Extracts the session isolation key from the current user's claims. /// /// The to monitor for cancellation requests. /// /// A task that represents the asynchronous operation. The task result contains the value of the /// configured claim type from the current user's identity, or if the claim /// is not present or the HTTP context is unavailable. /// /// /// This method retrieves the claim value from HttpContext.User.Claims. If multiple claims /// of the specified type exist, the first match is returned. /// public override ValueTask GetSessionIsolationKeyAsync(CancellationToken cancellationToken = default) { Claim? claim = this._httpContextAccessor? .HttpContext? .User?.Claims.FirstOrDefault(c => c.Type == this._claimType); return new ValueTask(claim?.Value); } }