fullstackhero/dotnet-starter-kit · error · UnauthorizedException

Invalid tenant

Error message

Invalid tenant

What it means

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.

Solutions

  1. Send the tenant identifier on every request (e.g. X-Tenant header or __tenant__ route/query as configured in MultitenancyModule)
  2. Verify the tenant id exists and matches a registered tenant
  3. Check middleware ordering so Finbuckle multitenancy middleware runs before auth/endpoint resolution
  4. In tests, initialize the IMultiTenantContextAccessor with a valid TenantInfo before calling the service

Example fix

// before
client.DefaultRequestHeaders.Add("Accept", "application/json");
// after
client.DefaultRequestHeaders.Add("X-Tenant", "tenant-xyz");
client.DefaultRequestHeaders.Add("Accept", "application/json");
Defensive patterns

Strategy: validation

Validate before calling

var tenantId = httpContextAccessor.HttpContext?.GetMultiTenantContext<TenantInfo>()?.TenantInfo?.Id;
if (string.IsNullOrWhiteSpace(tenantId))
    return Results.Problem(statusCode: 401, detail: "Tenant could not be resolved — supply a valid tenant identifier.");

Type guard

bool HasResolvedTenant(IMultiTenantContextAccessor? a) =>
    !string.IsNullOrWhiteSpace(a?.MultiTenantContext?.TenantInfo?.Id);

Try / catch

try
{
    await sessionService.GetUserSessionsAsync(userId, ct);
}
catch (UnauthorizedException ex) when (ex.Message == "Invalid tenant")
{
    return Results.Problem(statusCode: 401, detail: "Tenant could not be resolved — supply a valid tenant identifier.");
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15). Data as JSON: /api/errors/7ef60c820a87eb91. Report an issue: GitHub.

Appendix: source

Thrown at src/Modules/Identity/Modules.Identity/Services/SessionService.cs:43

        IdentityDbContext db,
        ICurrentUser currentUser,
        IMultiTenantContextAccessor<AppTenantInfo> multiTenantContextAccessor,
        ILogger<SessionService> logger,
        TimeProvider timeProvider)
    {
        _db = db;
        _currentUser = currentUser;
        _multiTenantContextAccessor = multiTenantContextAccessor;
        _logger = logger;
        _timeProvider = timeProvider;
        _uaParser = Parser.GetDefault();
    }

    private void EnsureValidTenant()
    {
        if (string.IsNullOrWhiteSpace(_multiTenantContextAccessor?.MultiTenantContext?.TenantInfo?.Id))
        {
            throw new UnauthorizedException("Invalid tenant");
        }
    }

    public async Task<UserSessionDto> CreateSessionAsync(
        string userId,
        string refreshTokenHash,
        string ipAddress,
        string userAgent,
        DateTime expiresAt,
        CancellationToken cancellationToken = default)
    {
        EnsureValidTenant();

        var clientInfo = _uaParser.Parse(userAgent);

        var session = UserSession.Create(
            userId: userId,
            refreshTokenHash: refreshTokenHash,

View on GitHub (pinned to 3f2959e683)