From 226694bb59526cc1237f27dc2f0a2af3ad08c47c Mon Sep 17 00:00:00 2001 From: Sergey Beryozkin Date: Tue, 8 Dec 2020 15:13:50 +0000 Subject: [PATCH] Update DefaultTokenStateManager to remove all session cookies when tokens are split --- .../runtime/CodeAuthenticationMechanism.java | 7 ++++++- .../runtime/DefaultTokenStateManager.java | 17 +++++++++++++-- .../io/quarkus/it/keycloak/CodeFlowTest.java | 21 +++++++++++++++++++ 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/CodeAuthenticationMechanism.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/CodeAuthenticationMechanism.java index eab1988037801..5fa03936d0d49 100644 --- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/CodeAuthenticationMechanism.java +++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/CodeAuthenticationMechanism.java @@ -484,10 +484,15 @@ private void removeCookie(RoutingContext context, TenantConfigContext configCont if (SESSION_COOKIE_NAME.equals(cookieName)) { resolver.getTokenStateManager().deleteTokens(context, configContext.oidcConfig, cookie.getValue()); } + removeCookie(cookie, configContext.oidcConfig); + } + } + static void removeCookie(ServerCookie cookie, OidcTenantConfig oidcConfig) { + if (cookie != null) { cookie.setValue(""); cookie.setMaxAge(0); - Authentication auth = configContext.oidcConfig.getAuthentication(); + Authentication auth = oidcConfig.getAuthentication(); if (auth.cookiePath.isPresent()) { cookie.setPath(auth.cookiePath.get()); } diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/DefaultTokenStateManager.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/DefaultTokenStateManager.java index 3d8b325dd4884..5828c17e3402b 100644 --- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/DefaultTokenStateManager.java +++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/DefaultTokenStateManager.java @@ -6,6 +6,7 @@ import io.quarkus.oidc.OidcTenantConfig; import io.quarkus.oidc.TokenStateManager; import io.vertx.core.http.Cookie; +import io.vertx.core.http.impl.ServerCookie; import io.vertx.ext.web.RoutingContext; @ApplicationScoped @@ -55,11 +56,11 @@ public AuthorizationCodeTokens getTokens(RoutingContext routingContext, OidcTena accessToken = tokens[1]; refreshToken = tokens[2]; } else { - Cookie atCookie = routingContext.request().getCookie(getAccessTokenCookieName(oidcConfig.getTenantId().get())); + Cookie atCookie = getAccessTokenCookie(routingContext, oidcConfig); if (atCookie != null) { accessToken = atCookie.getValue(); } - Cookie rtCookie = routingContext.request().getCookie(getRefreshTokenCookieName(oidcConfig.getTenantId().get())); + Cookie rtCookie = getRefreshTokenCookie(routingContext, oidcConfig); if (rtCookie != null) { refreshToken = rtCookie.getValue(); } @@ -71,6 +72,18 @@ public AuthorizationCodeTokens getTokens(RoutingContext routingContext, OidcTena @Override public void deleteTokens(RoutingContext routingContext, OidcTenantConfig oidcConfig, String tokenState) { + if (oidcConfig.tokenStateManager.splitTokens) { + CodeAuthenticationMechanism.removeCookie(getAccessTokenCookie(routingContext, oidcConfig), oidcConfig); + CodeAuthenticationMechanism.removeCookie(getRefreshTokenCookie(routingContext, oidcConfig), oidcConfig); + } + } + + private static ServerCookie getAccessTokenCookie(RoutingContext routingContext, OidcTenantConfig oidcConfig) { + return (ServerCookie) routingContext.request().getCookie(getAccessTokenCookieName(oidcConfig.getTenantId().get())); + } + + private static ServerCookie getRefreshTokenCookie(RoutingContext routingContext, OidcTenantConfig oidcConfig) { + return (ServerCookie) routingContext.request().getCookie(getRefreshTokenCookieName(oidcConfig.getTenantId().get())); } private static String getAccessTokenCookieName(String tenantId) { diff --git a/integration-tests/oidc-code-flow/src/test/java/io/quarkus/it/keycloak/CodeFlowTest.java b/integration-tests/oidc-code-flow/src/test/java/io/quarkus/it/keycloak/CodeFlowTest.java index d78977d7c61d9..350f27a389c43 100644 --- a/integration-tests/oidc-code-flow/src/test/java/io/quarkus/it/keycloak/CodeFlowTest.java +++ b/integration-tests/oidc-code-flow/src/test/java/io/quarkus/it/keycloak/CodeFlowTest.java @@ -619,6 +619,27 @@ public void testDefaultSessionManagerSplitTokens() throws IOException, Interrupt Cookie rtTokenCookie = getSessionRtCookie(page.getWebClient(), "tenant-split-tokens"); checkSingleTokenCookie(rtTokenCookie, "Refresh"); + // verify all the cookies are cleared after the session timeout + webClient.getOptions().setRedirectEnabled(false); + webClient.getCache().clear(); + + await().atLeast(6, TimeUnit.SECONDS) + .pollDelay(Duration.ofSeconds(6)) + .until(new Callable() { + @Override + public Boolean call() throws Exception { + WebResponse webResponse = webClient + .loadWebResponse(new WebRequest(URI.create("http://localhost:8081/index.html").toURL())); + assertEquals(302, webResponse.getStatusCode()); + assertNull(getSessionCookie(webClient, null)); + return true; + } + }); + + assertNull(getSessionCookie(page.getWebClient(), "tenant-split-tokens")); + assertNull(getSessionAtCookie(page.getWebClient(), "tenant-split-tokens")); + assertNull(getSessionRtCookie(page.getWebClient(), "tenant-split-tokens")); + webClient.getCookieManager().clearCookies(); } }