Mendix Expert Developer study materials
Mendix Expert Developer study resources

Tenant Isolation in a Shared Mendix SaaS

Mendix Expert Developer · Put your knowledge to work in context.

All case studies

Tenant Isolation in a Shared Mendix SaaS

A shared-database SaaS application hosts 52 housing associations. Every tenant-scoped entity has an association to Tenant, but AuditLog and Setting do not. Entity access on Case uses the XPath constraint [Tenant = '[%CurrentUser%]/Tenant']. Module roles are User, TenantAdmin, Integration, and Administrator. Tenant admins are assigned both TenantAdmin and Administrator because they need to manage users. UAT found that a user from tenant A could open a CaseNote of tenant B by pasting a URL with that object's GUID. The published REST API uses a single integration user with Administrator and accepts a tenantId query parameter. The team wants to enable demo users in production for a pilot. Security testing is manual and only covers the login page. The app is on Mendix Cloud and uses SAML SSO for end users.

1. Identify the root causes of the cross-tenant CaseNote exposure and recommend the access-control design for tenant isolation.

Read the worked answer

The GUID exposure is not a URL problem; it is an entity-access gap. CaseNote must have its own entity access rule constrained through the association path to Tenant, for example via Case/Tenant. If CaseNote has no rule, or only a microflow page rule, a user who knows a GUID can retrieve it through a page, a REST call or a microflow that does not apply access. The second cause is the Administrator module role. Tenant admins assigned Administrator receive unconstrained entity access across all tenants, so the XPath on Case is bypassed as soon as the role is added. Create a TenantAdministrator role with tenant-scoped entity access for User, Tenant and configuration entities, and reserve Administrator for platform operators only. Do not grant Administrator to customer-facing users. For system microflows that must cross tenants, use a separate module role and explicitly disable entity access only inside that microflow, with a documented purpose. Enforce the same rule on every tenant-scoped entity, including associations and child entities, because access on the parent does not automatically protect a child retrieved by GUID. Add a validation test that retrieves a known foreign GUID as each role and expects an empty result or an access exception.

2. Redesign the published REST API so it cannot be used to read another tenant's data, and address the demo-user pilot risk.

Read the worked answer

Stop accepting tenantId as an authorization input. The API should authenticate a client or user, derive the tenant from a trusted claim in the token or from the authenticated user's Tenant association, and ignore or reject a conflicting tenantId parameter. Use separate API client credentials per tenant where feasible, mapped to a small Integration role that has tenant-scoped entity access. Do not run published REST operations as Administrator, and do not disable entity access in the operation microflow unless the operation is a platform-level task. If you use a custom authentication microflow, validate the token signature, expiry and tenant claim before creating the session. Add rate limiting and log the tenant, client and object IDs for every request. For the demo-user pilot, do not enable anonymous or demo users in production with a shared password. If a pilot requires a demo tenant, create a dedicated tenant, a dedicated demo user with a strong unique password, restrict it to the demo tenant and expire it automatically. Disable demo users in the production configuration and make the setting environment-specific. The test should call the API with tenant A's token and tenant B's object GUID and expect not found or forbidden, not a filtered empty list that still reveals existence.

3. Describe an automated security test plan that would catch this class of defect before release.

Read the worked answer

Build tests around identities and object IDs, not around page navigation. Create at least two tenants, each with a normal user, a tenant admin and an API client. For every tenant-scoped entity, seed one object per tenant and record its GUID. Then run a test microflow or integration test as tenant A that attempts to retrieve tenant B's object by GUID through each access path: direct entity retrieve, association traversal, page URL, published REST and any microflow exposed as a page or service. Assert that the result is empty or that an access exception is thrown. Repeat for tenant admins to prove the Administrator role is not attached. Include a test that the REST API rejects a tenantId that differs from the token claim. Run these tests in the CI pipeline against a disposable acceptance database, because security regressions are easy to reintroduce when a new entity is added. Add a model review checklist: every new tenant-scoped entity needs an entity-access rule with a Tenant path, and every new published REST operation needs an authentication and authorization test. Finally, test demo-user configuration per environment so production cannot accidentally inherit the pilot setting.