refactor: merge tenant isolation into single HandlerInterceptor
All checks were successful
CI / build (push) Successful in 38s
CI / docker (push) Successful in 37s

Replace TenantResolutionFilter + TenantOwnershipValidator (15 manual
calls across 5 controllers) with a single TenantIsolationInterceptor
that uses Spring HandlerMapping path variables for fail-closed tenant
isolation. New endpoints with {tenantId}, {environmentId}, or {appId}
path variables are automatically isolated without manual code.

Simplify OrgResolver from dual-token fetch to single token — Logto
merges all scopes into either token type.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-05 15:48:04 +02:00
parent 051f7fdae9
commit 1ef8c9dceb
13 changed files with 205 additions and 218 deletions

View File

@@ -38,9 +38,8 @@ export function OrgResolver({ children }: { children: React.ReactNode }) {
useEffect(() => {
if (!me) return;
// Read scopes from access tokens:
// - org-scoped resource token → tenant-level scopes (apps:manage, observe:read, etc.)
// - global resource token → platform-level scopes (platform:admin)
// Read scopes from a single access token (org-scoped when an org is selected,
// global otherwise). Logto merges all applicable scopes into either token.
fetchConfig().then(async (config) => {
if (!config.logtoResource) return;
@@ -55,18 +54,12 @@ export function OrgResolver({ children }: { children: React.ReactNode }) {
};
try {
const [orgToken, globalToken] = await Promise.all([
currentOrgId
? getAccessToken(config.logtoResource, currentOrgId).catch(() => undefined)
: Promise.resolve(undefined),
getAccessToken(config.logtoResource).catch(() => undefined),
]);
const token = await (currentOrgId
? getAccessToken(config.logtoResource, currentOrgId)
: getAccessToken(config.logtoResource)
).catch(() => undefined);
const merged = new Set([
...extractScopes(orgToken),
...extractScopes(globalToken),
]);
setScopes(merged);
setScopes(new Set(extractScopes(token)));
} catch {
setScopes(new Set());
}