{"record":{"id":"affebde725d96ae6","repo":"quarkusio/quarkus","slug":"invalid-redirect-uri","errorCode":null,"errorMessage":"Invalid redirect URI","messagePattern":"Invalid redirect URI","errorType":"http","errorClass":"RuntimeException","httpStatus":500,"severity":"error","filePath":"integration-tests/oidc-code-flow/src/main/java/io/quarkus/it/keycloak/SessionExpiredOidcRedirectFilter.java","lineNumber":31,"sourceCode":"import io.quarkus.oidc.common.runtime.OidcCommonUtils;\nimport io.quarkus.oidc.runtime.OidcUtils;\nimport io.smallrye.jwt.build.Jwt;\n\n@ApplicationScoped\n@Unremovable\n@TenantFeature(\"tenant-refresh\")\n@Redirect(Location.SESSION_EXPIRED_PAGE)\npublic class SessionExpiredOidcRedirectFilter implements OidcRedirectFilter {\n\n    @Override\n    public void filter(OidcRedirectContext context) {\n\n        if (!\"tenant-refresh\".equals(context.oidcTenantConfig().tenantId.get())) {\n            throw new RuntimeException(\"Invalid tenant id\");\n        }\n\n        if (!context.redirectUri().contains(\"/session-expired-page\")) {\n            throw new RuntimeException(\"Invalid redirect URI\");\n        }\n\n        AuthorizationCodeTokens tokens = context.routingContext().get(AuthorizationCodeTokens.class.getName());\n        String userName = OidcCommonUtils.decodeJwtContent(tokens.getIdToken()).getString(Claims.preferred_username.name());\n        String jwe = Jwt.preferredUserName(userName).jwe()\n                .encryptWithSecret(context.oidcTenantConfig().credentials.secret.get());\n        OidcUtils.createCookie(context.routingContext(), context.oidcTenantConfig(), \"session_expired\",\n                jwe + \"|\" + context.oidcTenantConfig().tenantId.get(), 10);\n\n        context.additionalQueryParams().add(\"session-expired\", \"true\");\n    }\n\n}\n","sourceCodeStart":13,"sourceCodeEnd":45,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/integration-tests/oidc-code-flow/src/main/java/io/quarkus/it/keycloak/SessionExpiredOidcRedirectFilter.java#L13-L45","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nif (!context.redirectUri().contains(\"/session-expired-page\")) {\n    throw new RuntimeException(\"Invalid redirect URI\");\n}\n// after\nif (!context.redirectUri().contains(\"/session-expired-page\")) {\n    return; // let unrelated redirects pass through untouched\n}","handlingStrategy":"validation","validationCode":"if (!context.redirectUri().contains(\"/session-expired-page\")) {\n    return; // not a session-expired redirect; leave untouched\n}","typeGuard":null,"tryCatchPattern":"try {\n    redirectFilter.filter(context);\n} catch (RuntimeException e) {\n    if (e.getMessage().equals(\"Invalid redirect URI\")) {\n        // redirect path changed; update the filter's expected path\n    }\n}","preventionTips":["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"],"tags":["oidc","redirect","integration-test"],"backgroundTag":"invalid-redirect-uri","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}