@mark-robustelli
Thank you Mark for responding and I would like to take this opportunity to provide more clarity on what we have implemented and what we want to achieve.
Use Case: Hybrid SSO Across Physically Isolated Tenants
We maintain N physically isolated FusionAuth tenants (each with its own database) and within each tenant multiple Applications. Instead of provisioning the same email in every tenant, we have a single “Control-Plane” tenant called Simfinix, where each user logs in exactly once.
Our backend enriches each FusionAuth user record with a custom field, user.data.tenants, listing which physical tenants and which Applications in those tenants they’re allowed to access. When a user switches context, the backend is supposed to silently obtain a new access token signed by that specific tenant’s FusionAuth instance and scoped to the chosen Application—no re-login required.
However, at present we are unable to achieve this. When we call /api/jwt/issue on the target tenant, FusionAuth looks for the Application Portal-Simfinix (which only exists in the Simfinix tenant) and returns “application not found,” so we never receive a token signed by the intended tenant-context.
Topology Example:
yaml
Copy
Edit
Tenants
├── Simfinix (OIDC IdP)
│ └── Apps: Portal-Simfinix (identity provider)
├── TenantA
│ └── Apps: AppA, AppB, AppC
└── TenantB
└── Apps: AppA, AppB, AppC
User: xxx@gmail.com
├── authenticatedTenant: Simfinix
└── user.data.tenants (custom FusionAuth field):
[
{
tenantId: TenantA_ID,
applications: [AppA_ID, AppC_ID]
},
{
tenantId: TenantB_ID,
applications: [AppB_ID]
}
]
Key Points:
Single login in Simfinix → backend stores one refresh_token_simfinix.
Silent-login flow per tenant: backend uses that token to perform an OIDC authorize request with prompt=none in the target tenant and exchanges the code for refresh_token and access_token issued by that tenant.
A call to /api/jwt/issue or a refresh_token grant against the chosen tenant should issue a JWT signed by that tenant and scoped to the selected Application.
Current blocker: FusionAuth is searching for “Portal-Simfinix” in the target tenant’s Applications (because that’s the client_id we’re passing) and fails with “application not found,” so we never get the tenant-signed JWT.
Once resolved, users will experience “log in once → switch anywhere,” with each tenant remaining fully isolated and all tokens correctly signed by the appropriate tenant.
Note: the property user.data.tenants lives on the FusionAuth User object (under its data map) and is fully custom—FusionAuth doesn’t provide it out-of-the-box, but we extend the User entity to include it.