The logging package uses session strategies to identify users and group their API actions. Multiple strategies are available to support different authentication patterns.
Session Strategy Options
builder.Services.AddApiLogging(options =>
{
// Choose primary strategy
options.SessionStrategy = SessionStrategy.Hybrid; // Default
// Or use one of:
// SessionStrategy.Jwt
// SessionStrategy.HttpContext
// SessionStrategy.Manual
});Available Strategies
1. JWT Claims Strategy
Extracts user identity from JWT token claims. Best for APIs with token-based authentication.
options.SessionStrategy = SessionStrategy.Jwt;
// Configure which claims to look for
options.UserIdClaimTypes = new List<string>
{
ClaimTypes.NameIdentifier, // Standard .NET claim
"sub", // OpenID Connect subject
"user_id", // Custom claim
ClaimTypes.Name // Fallback
};
// Session ID from claims (optional)
options.SessionIdClaimTypes = new List<string> { "sid" };2. HttpContext Strategy
Looks for user/session identity in headers, cookies, or HttpContext.Items. Good for API key authentication or custom identity schemes.
options.SessionStrategy = SessionStrategy.HttpContext;
// Allow identity from headers
options.AllowHeaderIdentity = true;
options.UserIdHeaderNames = new List<string> { "X-User-Id", "X-Api-Key" };
options.SessionIdHeaderNames = new List<string> { "X-Session-Id" };
// Allow identity from cookies
options.AllowCookieIdentity = true;
options.UserIdCookieNames = new List<string> { "UserId" };
options.SessionIdCookieNames = new List<string> { "SessionId" };
// Tenant from headers/cookies
options.TenantIdHeaderNames = new List<string> { "X-Tenant-Id" };
options.TenantIdCookieNames = new List<string> { "TenantId" };3. Manual Strategy
Reads identity from HttpContext.Items. Use this when you set the identity programmatically.
options.SessionStrategy = SessionStrategy.Manual;
// In middleware or controller:
public class IdentityMiddleware
{
public async Task InvokeAsync(HttpContext context)
{
var userId = await GetUserIdFromSomewhere();
var sessionId = await GetSessionIdFromSomewhere();
context.Items["ApiLogging_UserId"] = userId;
context.Items["ApiLogging_SessionId"] = sessionId;
context.Items["ApiLogging_TenantId"] = "tenant-123";
await _next(context);
}
}4. Hybrid Strategy (Default)
Tries multiple strategies in order until one succeeds. This is the most flexible option.
options.SessionStrategy = SessionStrategy.Hybrid;
// Default order: JWT → HttpContext → Manual
// Customize the order:
options.SessionIdentificationOrder = new[]
{
SessionIdentifierType.JwtClaims,
SessionIdentifierType.HttpContext,
SessionIdentifierType.Manual
};Anonymous Sessions
Enable anonymous sessions for unauthenticated users:
options.AllowAnonymousSessions = true; options.AnonymousUserIdPrefix = "anon-"; // Anonymous users get auto-generated IDs like: // "anon-abc123def456"
Client-Provided Session IDs
Allow clients to provide their own session IDs via headers:
options.AllowClientProvidedSessionId = true;
options.SessionIdHeaderNames = new List<string> { "X-Session-Id" };
// Client sends: X-Session-Id: my-session-123Session Validation
// Require MongoDB ObjectId format for session IDs options.RequireObjectIdSessionIds = true; // Allow session ID without user ID (headless scenarios) options.AllowSessionIdWithoutUserId = true;
Session Timeouts
// Session becomes inactive after 30 minutes of no activity options.SessionInactivityTimeoutMinutes = 30; // Background service cleans up inactive sessions every hour options.SessionCleanupIntervalMinutes = 60;
Session Caching
Session lookups are cached to reduce database queries:
options.SessionLookupCacheEnabled = true; // Default: true options.SessionLookupCacheMinutes = 2; // Cache duration options.SessionLookupCacheSizeLimit = 1000; // 0 = unlimited
Multi-Tenant Configuration
// Configure tenant identification
options.TenantIdClaimType = "tenantId"; // JWT claim
options.TenantIdHeaderNames = new List<string> { "X-Tenant-Id" };
options.TenantIdCookieNames = new List<string> { "TenantId" };Complete Configuration Example
builder.Services.AddApiLogging(options =>
{
// Connection
options.ConnectionString = "mongodb://localhost:27017";
options.DatabaseName = "ApiLogs";
// Session strategy
options.SessionStrategy = SessionStrategy.Hybrid;
options.SessionIdentificationOrder = new[]
{
SessionIdentifierType.JwtClaims,
SessionIdentifierType.HttpContext
};
// JWT claims
options.UserIdClaimTypes = new List<string> { "sub", "user_id" };
options.SessionIdClaimTypes = new List<string> { "sid" };
// Headers/cookies fallback
options.AllowHeaderIdentity = true;
options.UserIdHeaderNames = new List<string> { "X-User-Id" };
options.SessionIdHeaderNames = new List<string> { "X-Session-Id" };
// Anonymous support
options.AllowAnonymousSessions = true;
options.AnonymousUserIdPrefix = "guest-";
// Timeouts
options.SessionInactivityTimeoutMinutes = 60;
options.SessionCleanupIntervalMinutes = 30;
// Caching
options.SessionLookupCacheEnabled = true;
options.SessionLookupCacheMinutes = 5;
});SessionIdentity Model
public class SessionIdentity
{
public string? UserId { get; set; }
public string? SessionId { get; set; }
public string? TenantId { get; set; }
public SessionIdentifierType Source { get; set; }
}
public enum SessionIdentifierType
{
JwtClaims,
HttpContext,
Manual
}Accessing Session Identity
The resolved session identity is stored in HttpContext.Items:
[HttpGet]
public IActionResult GetCurrentSession()
{
if (HttpContext.Items.TryGetValue(
ApiLoggingService.SessionIdentityItemKey,
out var obj) && obj is SessionIdentity identity)
{
return Ok(new
{
identity.UserId,
identity.SessionId,
identity.TenantId,
Source = identity.Source.ToString()
});
}
return NotFound();
}