AutoMate Technisch Help

Multi-Tenancy

Alle AutoMate.API endpoints ontvangen automatisch tenant context via de x-tenant-id HTTP request header. De tenant ID wordt nooit als request body parameter geaccepteerd — dit is een architectureel principe dat consistent doorgevoerd is in alle endpoints.

Hoe het werkt

De TenantGuard global pre-processor (API/Src/AutoMate.API/Processors/TenantGuardProcessor.cs) verwerkt elk inkomend request:

Ja

Nee

Nee

Ja

Nee

Ja

Nee

Ja

Nee

Ja

Nee

Ja

Nee

Ja

Inkomend request

Anonymous endpoint?

Doorgaan

Lees x-tenant-id header

Header aanwezig?

Fallback: tenantid JWT claim

Geldig GUID?

400 Bad Request

Header tenant != token tenant?

SetTenantId op IMultiTenantService

Caller is MSP?

403 Forbidden

Header tenant in klantenlijst?

Heeft MultiTenantRole?

Push TenantId naar Serilog LogContext

Stap-voor-stap

  1. Anonymous endpoints worden automatisch overgeslagen — de guard controleert op IAllowAnonymous metadata.

  2. Tenant extractie: de x-tenant-id header wordt gelezen. Voor de /useroles route valt de guard terug op de tenantid claim uit het JWT token.

  3. Validatie: lege waarde of Guid.Empty resulteert in 400 Bad Request. Ongeldig GUID formaat resulteert eveneens in 400 Bad Request.

  4. Cross-tenant autorisatie (MSP scenario): als de header tenant ID verschilt van de token tenant ID, controleert de guard:

    • De aanroeper heeft een tenant record in de database

    • Het TenantType van de aanroeper is MSP

    • De aanroeper heeft de Automate365.Customers.ReadWrite rol

    • De gevraagde tenant bevindt zich in CustomerTenants van de MSP

  5. Context doorgeven: IMultiTenantService.SetTenantId() en SetTenantName() worden aangeroepen zodat downstream handlers de tenant context via DI kunnen opvragen.

  6. Logging: de tenant ID wordt gepusht naar de Serilog LogContext als TenantId property, en opgeslagen in HttpContext.Items["TenantId"].

IMultiTenantService

De interface IMultiTenantService (API/AutoMate.API.Shared/IMultiTenantService.cs) biedt toegang tot de tenant context in endpoints en services:

public interface IMultiTenantService { Guid GetTenantId(); string? GetTenantName(); void SetTenantId(Guid tenantId); Guid? TryGetTenantId(); string GetUserIdentifier(); void SetUserIdentifier(string userIdentifier); void SetUserIdentifier(Guid tenantId, Guid userId); void SetTenantName(string name); }

IMultiTenantService is geregistreerd als Scoped service:

builder.Services.AddScoped<IMultiTenantService, MultiTenantService>();

Gebruik in endpoints

public class GetEmployeesEndpoint : EndpointWithoutRequest<GetEmployeesResponse> { private readonly IMultiTenantService _multiTenantService; public GetEmployeesEndpoint(IMultiTenantService multiTenantService) { _multiTenantService = multiTenantService; } public override void Configure() { Get("/api/iam/employees"); } public override async Task HandleAsync(CancellationToken ct) { var tenantId = _multiTenantService.GetTenantId(); // tenantId is al gevalideerd door TenantGuard } }

Gebruik TryGetTenantId() wanneer de tenant context optioneel is. Gebruik GetTenantId() wanneer de tenant vereist is — deze method gooit een exception als de tenant niet is ingesteld.

Tenant configuratie opslag

Tenant configuraties worden opgeslagen in Azure Table Storage. De verbinding wordt geconfigureerd via TenantConfigurationStorage in de applicatieconfiguratie. ITenantRepository biedt toegang tot tenant records inclusief TenantType en CustomerTenants.

Richtlijnen voor nieuwe endpoints

  • Inject altijd IMultiTenantService en gebruik GetTenantId() om de tenant op te halen

  • Neem de tenant ID nooit op als property in request DTOs of request bodies

  • De TenantGuard valideert automatisch — geen extra validatiecode nodig in endpoints

  • Vermeld in de endpoint beschrijving: "Tenant ID wordt opgehaald uit de x-tenant-id header"

Last modified: 10 June 2026