{"record":{"id":"7ef60c820a87eb91","repo":"fullstackhero/dotnet-starter-kit","slug":"invalid-tenant-sessionservice","errorCode":null,"errorMessage":"Invalid tenant","messagePattern":"Invalid tenant","errorType":"exception","errorClass":"UnauthorizedException","httpStatus":401,"severity":"error","filePath":"src/Modules/Identity/Modules.Identity/Services/SessionService.cs","lineNumber":43,"sourceCode":"        IdentityDbContext db,\n        ICurrentUser currentUser,\n        IMultiTenantContextAccessor<AppTenantInfo> multiTenantContextAccessor,\n        ILogger<SessionService> logger,\n        TimeProvider timeProvider)\n    {\n        _db = db;\n        _currentUser = currentUser;\n        _multiTenantContextAccessor = multiTenantContextAccessor;\n        _logger = logger;\n        _timeProvider = timeProvider;\n        _uaParser = Parser.GetDefault();\n    }\n\n    private void EnsureValidTenant()\n    {\n        if (string.IsNullOrWhiteSpace(_multiTenantContextAccessor?.MultiTenantContext?.TenantInfo?.Id))\n        {\n            throw new UnauthorizedException(\"Invalid tenant\");\n        }\n    }\n\n    public async Task<UserSessionDto> CreateSessionAsync(\n        string userId,\n        string refreshTokenHash,\n        string ipAddress,\n        string userAgent,\n        DateTime expiresAt,\n        CancellationToken cancellationToken = default)\n    {\n        EnsureValidTenant();\n\n        var clientInfo = _uaParser.Parse(userAgent);\n\n        var session = UserSession.Create(\n            userId: userId,\n            refreshTokenHash: refreshTokenHash,","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/fullstackhero/dotnet-starter-kit/blob/3f2959e683e9f83f13e55e1678c9119f63c7e8e5/src/Modules/Identity/Modules.Identity/Services/SessionService.cs#L25-L61","documentation":"SessionService.EnsureValidTenant guards every session operation: if the Finbuckle multitenant context has no resolved TenantInfo.Id (blank/missing tenant), it throws UnauthorizedException('Invalid tenant'). Sessions are tenant-scoped, so no session work can proceed without a resolved tenant.","triggerScenarios":"Any SessionService call (CreateSessionAsync, GetUserSessionsAsync, GetTenantSessionsAsync, GetSessionAsync, RevokeSessionAsync, RevokeAllSessionsAsync, GetUserSessionsForAdminAsync) executed on a request where the __tenant__ identifier is absent or does not resolve to a known tenant.","commonSituations":"Client omitted the tenant header/claim; tenant identifier string misspelled; middleware order issue where multitenancy middleware didn't run; direct service invocation in tests without setting up MultiTenantContext.","solutions":["Send the tenant identifier on every request (e.g. X-Tenant header or __tenant__ route/query as configured in MultitenancyModule)","Verify the tenant id exists and matches a registered tenant","Check middleware ordering so Finbuckle multitenancy middleware runs before auth/endpoint resolution","In tests, initialize the IMultiTenantContextAccessor with a valid TenantInfo before calling the service"],"exampleFix":"// before\nclient.DefaultRequestHeaders.Add(\"Accept\", \"application/json\");\n// after\nclient.DefaultRequestHeaders.Add(\"X-Tenant\", \"tenant-xyz\");\nclient.DefaultRequestHeaders.Add(\"Accept\", \"application/json\");","handlingStrategy":"validation","validationCode":"var tenantId = httpContextAccessor.HttpContext?.GetMultiTenantContext<TenantInfo>()?.TenantInfo?.Id;\nif (string.IsNullOrWhiteSpace(tenantId))\n    return Results.Problem(statusCode: 401, detail: \"Tenant could not be resolved — supply a valid tenant identifier.\");","typeGuard":"bool HasResolvedTenant(IMultiTenantContextAccessor? a) =>\n    !string.IsNullOrWhiteSpace(a?.MultiTenantContext?.TenantInfo?.Id);","tryCatchPattern":"try\n{\n    await sessionService.GetUserSessionsAsync(userId, ct);\n}\ncatch (UnauthorizedException ex) when (ex.Message == \"Invalid tenant\")\n{\n    return Results.Problem(statusCode: 401, detail: \"Tenant could not be resolved — supply a valid tenant identifier.\");\n}","preventionTips":["Always send the tenant identifier header/route value on API calls","Verify Finbuckle middleware ordering in the host pipeline","Document the tenant resolution strategy (header vs route vs claim) for API consumers","In integration tests, seed the multitenant context before calling session services"],"tags":["multitenancy","auth","tenant-resolution"],"backgroundTag":"authentication-required","analyzedSha":"3f2959e683e9f83f13e55e1678c9119f63c7e8e5","analyzedAt":"2026-09-15T22:20:53.684Z","contentChangedAt":"2026-09-15T22:20:53.684Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}