quarkusio/quarkus · error · RuntimeException
Invalid tenant id
Error message
Invalid tenant id
What it means
SessionExpiredOidcRedirectFilter filters OIDC redirects and validates that the redirect belongs to the 'tenant-refresh' tenant. When the OIDC tenant id in the redirect context is anything else, it throws to fail fast, since the filter was designed exclusively for the tenant-refresh session-expired flow.
Source
Thrown at integration-tests/oidc-code-flow/src/main/java/io/quarkus/it/keycloak/SessionExpiredOidcRedirectFilter.java:27
import io.quarkus.oidc.OidcRedirectFilter;
import io.quarkus.oidc.Redirect;
import io.quarkus.oidc.Redirect.Location;
import io.quarkus.oidc.TenantFeature;
import io.quarkus.oidc.common.runtime.OidcCommonUtils;
import io.quarkus.oidc.runtime.OidcUtils;
import io.smallrye.jwt.build.Jwt;
@ApplicationScoped
@Unremovable
@TenantFeature("tenant-refresh")
@Redirect(Location.SESSION_EXPIRED_PAGE)
public class SessionExpiredOidcRedirectFilter implements OidcRedirectFilter {
@Override
public void filter(OidcRedirectContext context) {
if (!"tenant-refresh".equals(context.oidcTenantConfig().tenantId.get())) {
throw new RuntimeException("Invalid tenant id");
}
if (!context.redirectUri().contains("/session-expired-page")) {
throw new RuntimeException("Invalid redirect URI");
}
AuthorizationCodeTokens tokens = context.routingContext().get(AuthorizationCodeTokens.class.getName());
String userName = OidcCommonUtils.decodeJwtContent(tokens.getIdToken()).getString(Claims.preferred_username.name());
String jwe = Jwt.preferredUserName(userName).jwe()
.encryptWithSecret(context.oidcTenantConfig().credentials.secret.get());
OidcUtils.createCookie(context.routingContext(), context.oidcTenantConfig(), "session_expired",
jwe + "|" + context.oidcTenantConfig().tenantId.get(), 10);
context.additionalQueryParams().add("session-expired", "true");
}
}
View on GitHub (pinned to e1c734241f)
Solutions
- Scope the filter to the intended tenant (e.g. register it only for tenant-refresh via tenant-specific configuration)
- Update the tenant-id comparison to match the actual configured tenant id
- Verify quarkus.oidc.<tenant>.tenant-id in application.properties matches 'tenant-refresh'
Example fix
// before
if (!"tenant-refresh".equals(context.oidcTenantConfig().tenantId.get())) {
throw new RuntimeException("Invalid tenant id");
}
// after
if (!"tenant-refresh".equals(context.oidcTenantConfig().tenantId.get())) {
// skip instead of failing for other tenants
return;
} Defensive patterns
Strategy: validation
Validate before calling
String tenantId = context.oidcTenantConfig().tenantId.get();
if (!"tenant-refresh".equals(tenantId)) {
return; // skip unrelated tenants instead of throwing
} Try / catch
try {
redirectFilter.filter(context);
} catch (RuntimeException e) {
if (e.getMessage().equals("Invalid tenant id")) {
// filter applied to wrong tenant; scope its registration
}
} Prevention
- Scope OidcRedirectFilter registration to the intended tenant
- Keep tenant ids in application.properties in sync with filter checks
- Add a test covering redirects from other tenants
When it happens
Trigger: The filter is registered globally (via @OidcRedirectFilter or config) and an OIDC redirect is produced for a tenant other than 'tenant-refresh'.
Common situations: Multiple OIDC tenants configured but the filter not scoped to one tenant; filter class picked up for all redirects; renaming tenant ids in application.properties without updating the filter.
Related errors
- Failed to find a matching OidcTenantConfig for tenant:
- OidcProviderClient can not be injected
- /tenant-absolute-redirect/callback is a callback method
- Tenant id must have been set by either the session or state
- An exception should have been thrown because authentication
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/fcacf4296e83c749.
Report an issue: GitHub.