quarkusio/quarkus · error · RuntimeException
Invalid redirect URI
Error message
Invalid redirect URI
What it means
SessionExpiredOidcRedirectFilter only rewrites redirects that target the '/session-expired-page'. When the redirect URI in the context does not contain that path, it throws, guarding against applying session-expired token encryption logic to unrelated OIDC redirects.
Source
Thrown at integration-tests/oidc-code-flow/src/main/java/io/quarkus/it/keycloak/SessionExpiredOidcRedirectFilter.java:31
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
- Ensure the filter only fires for redirects to /session-expired-page (scope it by tenant or by redirect path)
- Update the contains("/session-expired-page") check to match the actual page path
- Check the resource/config that sets the session-expired redirect URI for typos
Example fix
// before
if (!context.redirectUri().contains("/session-expired-page")) {
throw new RuntimeException("Invalid redirect URI");
}
// after
if (!context.redirectUri().contains("/session-expired-page")) {
return; // let unrelated redirects pass through untouched
} Defensive patterns
Strategy: validation
Validate before calling
if (!context.redirectUri().contains("/session-expired-page")) {
return; // not a session-expired redirect; leave untouched
} Try / catch
try {
redirectFilter.filter(context);
} catch (RuntimeException e) {
if (e.getMessage().equals("Invalid redirect URI")) {
// redirect path changed; update the filter's expected path
}
} Prevention
- Keep the session-expired page path in one shared constant used by resource and filter
- Re-check filter logic after renaming endpoints
- Scope the filter so it only sees session-expired redirects
When it happens
Trigger: An OIDC redirect passes through the filter whose redirect URI is not the session-expired page — e.g. a normal login redirect or a redirect for a different flow reached the same filter.
Common situations: Filter registered for all OIDC redirects instead of only session-expired ones; changed the session-expired page path in the resource or config without updating the filter; typo in the path constant.
Related errors
- /tenant-restore-path-absolute-redirect must be restored
- This method must not be invoked
- This method must not be invoked
- This method must not be invoked
- Invalid session expired page redirect
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/affebde725d96ae6.
Report an issue: GitHub.