VYPR
Medium severity6.0GHSA Advisory· Published Oct 28, 2025· Updated Apr 15, 2026

CVE-2025-12390

CVE-2025-12390

Description

A flaw was found in Keycloak. In Keycloak where a user can accidentally get access to another user's session if both use the same device and browser. This happens because Keycloak sometimes reuses session identifiers and doesn’t clean up properly during logout when browser cookies are missing. As a result, one user may receive tokens that belong to another user.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.keycloak:keycloak-servicesMaven
< 26.0.026.0.0

Affected products

1

Patches

4
b46fab230824

Remove root auth session after backchannel logout

https://github.com/keycloak/keycloakGiuseppe GrazianoSep 23, 2024via ghsa
8 files changed · +65 40
  • services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java+1 2 modified
    @@ -308,8 +308,7 @@ public static BackchannelLogoutResponse backchannelLogout(KeycloakSession sessio
                         checkUserSessionOnlyHasLoggedOutClients(realm, userSession, logoutAuthSession);
             } finally {
                 logger.tracef("Removing logout session '%s' after backchannel logout", logoutAuthSession.getParentSession().getId());
    -            RootAuthenticationSessionModel rootAuthSession = logoutAuthSession.getParentSession();
    -            rootAuthSession.removeAuthenticationSessionByTabId(logoutAuthSession.getTabId());
    +            session.authenticationSessions().removeRootAuthenticationSession(realm, logoutAuthSession.getParentSession());
             }
     
             userSession.setState(UserSessionModel.State.LOGGED_OUT);
    
  • testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/BrowserTabUtil.java+5 1 modified
    @@ -79,6 +79,10 @@ public static BrowserTabUtil getInstanceAndSetEnv(WebDriver driver) {
             return instance;
         }
     
    +    public static void cleanup() {
    +        instances = new ArrayList<>();
    +    }
    +
         public WebDriver getDriver() {
             return driver;
         }
    @@ -155,4 +159,4 @@ private void assertValidIndex(int index) {
         public void close() {
             destroy();
         }
    -}
    \ No newline at end of file
    +}
    
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java+2 0 modified
    @@ -55,6 +55,7 @@
     import org.keycloak.testsuite.auth.page.login.UpdatePassword;
     import org.keycloak.testsuite.client.KeycloakTestingClient;
     import org.keycloak.testsuite.pages.LoginPasswordUpdatePage;
    +import org.keycloak.testsuite.util.BrowserTabUtil;
     import org.keycloak.testsuite.util.CryptoInitRule;
     import org.keycloak.testsuite.util.DroneUtils;
     import org.keycloak.testsuite.util.OAuthClient;
    @@ -258,6 +259,7 @@ public void afterAbstractKeycloakTest() throws Exception {
     
             // Remove all browsers from queue
             DroneUtils.resetQueue();
    +        BrowserTabUtil.cleanup();
         }
     
         protected TestCleanup getCleanup(String realmName) {
    
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ReAuthenticationTest.java+37 0 modified
    @@ -49,6 +49,7 @@
     import org.keycloak.testsuite.pages.LoginTotpPage;
     import org.keycloak.testsuite.pages.LoginUsernameOnlyPage;
     import org.keycloak.testsuite.pages.PasswordPage;
    +import org.keycloak.testsuite.util.BrowserTabUtil;
     import org.keycloak.testsuite.util.FederatedIdentityBuilder;
     import org.keycloak.testsuite.util.FlowUtil;
     import org.keycloak.testsuite.util.OAuthClient;
    @@ -366,6 +367,42 @@ public void loginAfterExpiredUserSession() {
             realmsResouce().realm(rep.getRealm()).update(rep);
         }
     
    +    @Test
    +    public void loginAfterLogoutWithDifferentSessionId() {
    +        BrowserTabUtil tabUtil = BrowserTabUtil.getInstanceAndSetEnv(driver);
    +
    +        assertThat(tabUtil.getCountOfTabs(), Matchers.is(1));
    +        oauth.openLoginForm();
    +        loginPage.assertCurrent();
    +
    +        tabUtil.newTab(oauth.getLoginFormUrl());
    +        assertThat(tabUtil.getCountOfTabs(), Matchers.equalTo(2));
    +        oauth.openLoginForm();
    +
    +        tabUtil.closeTab(tabUtil.getCountOfTabs() - 1);
    +        assertThat(tabUtil.getCountOfTabs(), Matchers.equalTo(1));
    +
    +        tabUtil.switchToTab(0);
    +        loginPage.assertCurrent();
    +
    +        loginPage.login("test-user@localhost", "password");
    +        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
    +        OAuthClient.AccessTokenResponse response1 = oauth.doAccessTokenRequest(code, "password");
    +        AccessToken accessToken1 = oauth.verifyToken(response1.getAccessToken());
    +
    +        oauth.doLogout(response1.getRefreshToken(), "password");
    +
    +        oauth.openLoginForm();
    +        loginPage.assertCurrent();
    +        loginPage.login("test-user@localhost", "password");
    +        code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
    +        OAuthClient.AccessTokenResponse response2 = oauth.doAccessTokenRequest(code, "password");
    +        AccessToken accessToken2 = oauth.verifyToken(response2.getAccessToken());
    +
    +        Assert.assertNotEquals(accessToken1.getId(), accessToken2.getId());
    +        Assert.assertNotEquals(accessToken1.getSessionId(), accessToken2.getSessionId());
    +    }
    +
         private void setupIdentityFirstFlow() {
             String newFlowAlias = "browser - identity first";
             testingClient.server("test").run(session -> FlowUtil.inCurrentRealm(session).copyBrowserFlow(newFlowAlias));
    
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/LogoutTest.java+3 20 modified
    @@ -146,30 +146,14 @@ public void postLogoutWithRefreshTokenAfterUserSessionLogoutAndLoginAgain() thro
     
             setTimeOffset(2);
     
    -        WaitUtils.waitForPageToLoad();
    -        loginPage.login("password");
    +        driver.navigate().refresh();
    +        oauth.fillLoginForm("test-user@localhost", "password");
     
             Assert.assertFalse(loginPage.isCurrent());
     
             String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
             OAuthClient.AccessTokenResponse tokenResponse2 = oauth.doAccessTokenRequest(code, "password");
     
    -        // POST logout with token should fail
    -        try (CloseableHttpResponse response = oauth.doLogout(refreshToken1, "password")) {
    -            assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatusLine().getStatusCode());
    -        }
    -
    -        String logoutUrl = oauth.getLogoutUrl()
    -                .idTokenHint(accessTokenResponse.getIdToken())
    -                .postLogoutRedirectUri(oauth.APP_AUTH_ROOT)
    -                .build();
    -
    -        // GET logout with ID token should fail as well
    -        try (CloseableHttpClient c = HttpClientBuilder.create().disableRedirectHandling().build();
    -             CloseableHttpResponse response = c.execute(new HttpGet(logoutUrl))) {
    -            assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatusLine().getStatusCode());
    -        }
    -
             // finally POST logout with VALID token should succeed
             try (CloseableHttpResponse response = oauth.doLogout(tokenResponse2.getRefreshToken(), "password")) {
                 MatcherAssert.assertThat(response, Matchers.statusCodeIsHC(Status.NO_CONTENT));
    @@ -178,7 +162,6 @@ public void postLogoutWithRefreshTokenAfterUserSessionLogoutAndLoginAgain() thro
             }
         }
     
    -
         @Test
         public void postLogoutFailWithCredentialsOfDifferentClient() throws Exception {
             oauth.doLogin("test-user@localhost", "password");
    @@ -247,7 +230,7 @@ private void backchannelLogoutRequest(String expectedRefreshAlg, String expected
               .idTokenHint(idTokenString)
               .postLogoutRedirectUri(oauth.APP_AUTH_ROOT)
               .build();
    -        
    +
             try (CloseableHttpClient c = HttpClientBuilder.create().disableRedirectHandling().build();
               CloseableHttpResponse response = c.execute(new HttpGet(logoutUrl))) {
                 MatcherAssert.assertThat(response, Matchers.statusCodeIsHC(Status.FOUND));
    
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/RefreshTokenTest.java+6 6 modified
    @@ -1070,8 +1070,8 @@ public void refreshTokenAfterUserLogoutAndLoginAgain() {
             try {
                 // Continue with login
                 setTimeOffset(2);
    -            WaitUtils.waitForPageToLoad();
    -            loginPage.login("password");
    +            driver.navigate().refresh();
    +            oauth.fillLoginForm("test-user@localhost", "password");
     
                 assertFalse(loginPage.isCurrent());
     
    @@ -1104,8 +1104,8 @@ public void refreshTokenAfterAdminLogoutAllAndLoginAgain() {
             try {
                 // Continue with login
                 setTimeOffset(2);
    -            WaitUtils.waitForPageToLoad();
    -            loginPage.login("password");
    +            driver.navigate().refresh();
    +            oauth.fillLoginForm("test-user@localhost", "password");
     
                 assertFalse(loginPage.isCurrent());
     
    @@ -1137,8 +1137,8 @@ public void refreshTokenAfterUserAdminLogoutEndpointAndLoginAgain() {
     
                 // Continue with login
                 setTimeOffset(2);
    -            WaitUtils.waitForPageToLoad();
    -            loginPage.login("password");
    +            driver.navigate().refresh();
    +            oauth.fillLoginForm("test-user@localhost", "password");
     
                 assertFalse(loginPage.isCurrent());
     
    
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/TokenIntrospectionTest.java+2 2 modified
    @@ -250,8 +250,8 @@ public void testIntrospectRefreshTokenAfterUserSessionLogoutAndLoginAgain() thro
     
             setTimeOffset(2);
     
    -        WaitUtils.waitForPageToLoad();
    -        loginPage.login("password");
    +        driver.navigate().refresh();
    +        oauth.fillLoginForm("test-user@localhost", "password");
             events.expectLogin().assertEvent();
     
             Assert.assertFalse(loginPage.isCurrent());
    
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/UserInfoTest.java+9 9 modified
    @@ -207,7 +207,7 @@ public void testSuccess_postMethod_body() throws Exception {
                 client.close();
             }
         }
    -    
    +
         @Test
         public void testSuccess_postMethod_charset_body() throws Exception {
             Client client = AdminClientUtil.createResteasyClient();
    @@ -531,7 +531,7 @@ public void testSuccessSignedResponsePS256() throws Exception {
         public void testSuccessSignedResponseRS256AcceptJWT() throws Exception {
             testSuccessSignedResponse(Algorithm.RS256, MediaType.APPLICATION_JWT);
         }
    - 
    +
         @Test
         public void testSessionExpired() {
             Client client = AdminClientUtil.createResteasyClient();
    @@ -607,8 +607,8 @@ public void testAccessTokenAfterUserSessionLogoutAndLoginAgain() {
     
             setTimeOffset(2);
     
    -        WaitUtils.waitForPageToLoad();
    -        loginPage.login("password");
    +        driver.navigate().refresh();
    +        oauth.fillLoginForm("test-user@localhost", "password");
             events.expectLogin().assertEvent();
     
             Assert.assertFalse(loginPage.isCurrent());
    @@ -630,7 +630,7 @@ public void testAccessTokenAfterUserSessionLogoutAndLoginAgain() {
                 response.close();
     
                 events.expect(EventType.USER_INFO_REQUEST_ERROR)
    -                    .error(Errors.INVALID_TOKEN)
    +                    .error(Errors.USER_SESSION_NOT_FOUND)
                         .user(Matchers.nullValue(String.class))
                         .session(Matchers.nullValue(String.class))
                         .detail(Details.AUTH_METHOD, Details.VALIDATE_ACCESS_TOKEN)
    @@ -1088,23 +1088,23 @@ private void testRolesAreNotInUserInfoResponse(UserInfo userInfo) {
             assertNull(userInfo.getOtherClaims().get("realm_access"));
             assertNull(userInfo.getOtherClaims().get("resource_access"));
         }
    -    
    +
         @Test
         public void test_noContentType() throws Exception {
             Client client = AdminClientUtil.createResteasyClient();
     
             try {
                 AccessTokenResponse accessTokenResponse = executeGrantAccessTokenRequest(client);
    -                    
    +
                 WebTarget userInfoTarget = UserInfoClientUtil.getUserInfoWebTarget(client);
                 Response response = userInfoTarget.request()
                         .header(HttpHeaders.AUTHORIZATION, "bearer " + accessTokenResponse.getToken())
                         .build("POST")
                         .invoke();
    -            
    +
                 Assert.assertEquals(200, response.getStatus());
                 Assert.assertEquals("OK", response.getStatusInfo().toString());
    -           	
    +
             } finally {
                 client.close();
             }
    
ef75a4dc50aa

Remove root auth session after backchannel logout

https://github.com/keycloak/keycloakGiuseppe GrazianoSep 23, 2024via ghsa
8 files changed · +65 40
  • services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java+1 2 modified
    @@ -307,8 +307,7 @@ public static BackchannelLogoutResponse backchannelLogout(KeycloakSession sessio
                         checkUserSessionOnlyHasLoggedOutClients(realm, userSession, logoutAuthSession);
             } finally {
                 logger.tracef("Removing logout session '%s' after backchannel logout", logoutAuthSession.getParentSession().getId());
    -            RootAuthenticationSessionModel rootAuthSession = logoutAuthSession.getParentSession();
    -            rootAuthSession.removeAuthenticationSessionByTabId(logoutAuthSession.getTabId());
    +            session.authenticationSessions().removeRootAuthenticationSession(realm, logoutAuthSession.getParentSession());
             }
     
             userSession.setState(UserSessionModel.State.LOGGED_OUT);
    
  • testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/BrowserTabUtil.java+5 1 modified
    @@ -79,6 +79,10 @@ public static BrowserTabUtil getInstanceAndSetEnv(WebDriver driver) {
             return instance;
         }
     
    +    public static void cleanup() {
    +        instances = new ArrayList<>();
    +    }
    +
         public WebDriver getDriver() {
             return driver;
         }
    @@ -155,4 +159,4 @@ private void assertValidIndex(int index) {
         public void close() {
             destroy();
         }
    -}
    \ No newline at end of file
    +}
    
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java+2 0 modified
    @@ -60,6 +60,7 @@
     import org.keycloak.testsuite.auth.page.login.UpdatePassword;
     import org.keycloak.testsuite.client.KeycloakTestingClient;
     import org.keycloak.testsuite.pages.LoginPasswordUpdatePage;
    +import org.keycloak.testsuite.util.BrowserTabUtil;
     import org.keycloak.testsuite.util.CryptoInitRule;
     import org.keycloak.testsuite.util.DroneUtils;
     import org.keycloak.testsuite.util.OAuthClient;
    @@ -254,6 +255,7 @@ public void afterAbstractKeycloakTest() throws Exception {
     
             // Remove all browsers from queue
             DroneUtils.resetQueue();
    +        BrowserTabUtil.cleanup();
         }
     
         protected TestCleanup getCleanup(String realmName) {
    
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ReAuthenticationTest.java+37 0 modified
    @@ -49,6 +49,7 @@
     import org.keycloak.testsuite.pages.LoginTotpPage;
     import org.keycloak.testsuite.pages.LoginUsernameOnlyPage;
     import org.keycloak.testsuite.pages.PasswordPage;
    +import org.keycloak.testsuite.util.BrowserTabUtil;
     import org.keycloak.testsuite.util.FederatedIdentityBuilder;
     import org.keycloak.testsuite.util.FlowUtil;
     import org.keycloak.testsuite.util.OAuthClient;
    @@ -365,6 +366,42 @@ public void loginAfterExpiredUserSession() {
             realmsResouce().realm(rep.getRealm()).update(rep);
         }
     
    +    @Test
    +    public void loginAfterLogoutWithDifferentSessionId() {
    +        BrowserTabUtil tabUtil = BrowserTabUtil.getInstanceAndSetEnv(driver);
    +
    +        Assert.assertThat(tabUtil.getCountOfTabs(), Matchers.is(1));
    +        oauth.openLoginForm();
    +        loginPage.assertCurrent();
    +
    +        tabUtil.newTab(oauth.getLoginFormUrl());
    +        Assert.assertThat(tabUtil.getCountOfTabs(), Matchers.equalTo(2));
    +        oauth.openLoginForm();
    +
    +        tabUtil.closeTab(tabUtil.getCountOfTabs() - 1);
    +        Assert.assertThat(tabUtil.getCountOfTabs(), Matchers.equalTo(1));
    +
    +        tabUtil.switchToTab(0);
    +        loginPage.assertCurrent();
    +
    +        loginPage.login("test-user@localhost", "password");
    +        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
    +        OAuthClient.AccessTokenResponse response1 = oauth.doAccessTokenRequest(code, "password");
    +        AccessToken accessToken1 = oauth.verifyToken(response1.getAccessToken());
    +
    +        oauth.doLogout(response1.getRefreshToken(), "password");
    +
    +        oauth.openLoginForm();
    +        loginPage.assertCurrent();
    +        loginPage.login("test-user@localhost", "password");
    +        code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
    +        OAuthClient.AccessTokenResponse response2 = oauth.doAccessTokenRequest(code, "password");
    +        AccessToken accessToken2 = oauth.verifyToken(response2.getAccessToken());
    +
    +        Assert.assertNotEquals(accessToken1.getId(), accessToken2.getId());
    +        Assert.assertNotEquals(accessToken1.getSessionId(), accessToken2.getSessionId());
    +    }
    +
         private void setupIdentityFirstFlow() {
             String newFlowAlias = "browser - identity first";
             testingClient.server("test").run(session -> FlowUtil.inCurrentRealm(session).copyBrowserFlow(newFlowAlias));
    
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/LogoutTest.java+3 20 modified
    @@ -145,30 +145,14 @@ public void postLogoutWithRefreshTokenAfterUserSessionLogoutAndLoginAgain() thro
     
             setTimeOffset(2);
     
    -        WaitUtils.waitForPageToLoad();
    -        loginPage.login("password");
    +        driver.navigate().refresh();
    +        oauth.fillLoginForm("test-user@localhost", "password");
     
             Assert.assertFalse(loginPage.isCurrent());
     
             String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
             OAuthClient.AccessTokenResponse tokenResponse2 = oauth.doAccessTokenRequest(code, "password");
     
    -        // POST logout with token should fail
    -        try (CloseableHttpResponse response = oauth.doLogout(refreshToken1, "password")) {
    -            assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatusLine().getStatusCode());
    -        }
    -
    -        String logoutUrl = oauth.getLogoutUrl()
    -                .idTokenHint(accessTokenResponse.getIdToken())
    -                .postLogoutRedirectUri(oauth.APP_AUTH_ROOT)
    -                .build();
    -
    -        // GET logout with ID token should fail as well
    -        try (CloseableHttpClient c = HttpClientBuilder.create().disableRedirectHandling().build();
    -             CloseableHttpResponse response = c.execute(new HttpGet(logoutUrl))) {
    -            assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatusLine().getStatusCode());
    -        }
    -
             // finally POST logout with VALID token should succeed
             try (CloseableHttpResponse response = oauth.doLogout(tokenResponse2.getRefreshToken(), "password")) {
                 assertThat(response, Matchers.statusCodeIsHC(Status.NO_CONTENT));
    @@ -177,7 +161,6 @@ public void postLogoutWithRefreshTokenAfterUserSessionLogoutAndLoginAgain() thro
             }
         }
     
    -
         @Test
         public void postLogoutFailWithCredentialsOfDifferentClient() throws Exception {
             oauth.doLogin("test-user@localhost", "password");
    @@ -246,7 +229,7 @@ private void backchannelLogoutRequest(String expectedRefreshAlg, String expected
               .idTokenHint(idTokenString)
               .postLogoutRedirectUri(oauth.APP_AUTH_ROOT)
               .build();
    -        
    +
             try (CloseableHttpClient c = HttpClientBuilder.create().disableRedirectHandling().build();
               CloseableHttpResponse response = c.execute(new HttpGet(logoutUrl))) {
                 assertThat(response, Matchers.statusCodeIsHC(Status.FOUND));
    
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/RefreshTokenTest.java+6 6 modified
    @@ -831,8 +831,8 @@ public void refreshTokenAfterUserLogoutAndLoginAgain() {
             try {
                 // Continue with login
                 setTimeOffset(2);
    -            WaitUtils.waitForPageToLoad();
    -            loginPage.login("password");
    +            driver.navigate().refresh();
    +            oauth.fillLoginForm("test-user@localhost", "password");
     
                 assertFalse(loginPage.isCurrent());
     
    @@ -865,8 +865,8 @@ public void refreshTokenAfterAdminLogoutAllAndLoginAgain() {
             try {
                 // Continue with login
                 setTimeOffset(2);
    -            WaitUtils.waitForPageToLoad();
    -            loginPage.login("password");
    +            driver.navigate().refresh();
    +            oauth.fillLoginForm("test-user@localhost", "password");
     
                 assertFalse(loginPage.isCurrent());
     
    @@ -898,8 +898,8 @@ public void refreshTokenAfterUserAdminLogoutEndpointAndLoginAgain() {
     
                 // Continue with login
                 setTimeOffset(2);
    -            WaitUtils.waitForPageToLoad();
    -            loginPage.login("password");
    +            driver.navigate().refresh();
    +            oauth.fillLoginForm("test-user@localhost", "password");
     
                 assertFalse(loginPage.isCurrent());
     
    
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/TokenIntrospectionTest.java+2 2 modified
    @@ -233,8 +233,8 @@ public void testIntrospectRefreshTokenAfterUserSessionLogoutAndLoginAgain() thro
     
             setTimeOffset(2);
     
    -        WaitUtils.waitForPageToLoad();
    -        loginPage.login("password");
    +        driver.navigate().refresh();
    +        oauth.fillLoginForm("test-user@localhost", "password");
             events.expectLogin().assertEvent();
     
             Assert.assertFalse(loginPage.isCurrent());
    
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/UserInfoTest.java+9 9 modified
    @@ -207,7 +207,7 @@ public void testSuccess_postMethod_body() throws Exception {
                 client.close();
             }
         }
    -    
    +
         @Test
         public void testSuccess_postMethod_charset_body() throws Exception {
             Client client = AdminClientUtil.createResteasyClient();
    @@ -516,7 +516,7 @@ public void testSuccessSignedResponsePS256() throws Exception {
         public void testSuccessSignedResponseRS256AcceptJWT() throws Exception {
             testSuccessSignedResponse(Algorithm.RS256, MediaType.APPLICATION_JWT);
         }
    - 
    +
         @Test
         public void testSessionExpired() {
             Client client = AdminClientUtil.createResteasyClient();
    @@ -592,8 +592,8 @@ public void testAccessTokenAfterUserSessionLogoutAndLoginAgain() {
     
             setTimeOffset(2);
     
    -        WaitUtils.waitForPageToLoad();
    -        loginPage.login("password");
    +        driver.navigate().refresh();
    +        oauth.fillLoginForm("test-user@localhost", "password");
             events.expectLogin().assertEvent();
     
             Assert.assertFalse(loginPage.isCurrent());
    @@ -615,7 +615,7 @@ public void testAccessTokenAfterUserSessionLogoutAndLoginAgain() {
                 response.close();
     
                 events.expect(EventType.USER_INFO_REQUEST_ERROR)
    -                    .error(Errors.INVALID_TOKEN)
    +                    .error(Errors.USER_SESSION_NOT_FOUND)
                         .user(Matchers.nullValue(String.class))
                         .session(Matchers.nullValue(String.class))
                         .detail(Details.AUTH_METHOD, Details.VALIDATE_ACCESS_TOKEN)
    @@ -1073,23 +1073,23 @@ private void testRolesAreNotInUserInfoResponse(UserInfo userInfo) {
             assertNull(userInfo.getOtherClaims().get("realm_access"));
             assertNull(userInfo.getOtherClaims().get("resource_access"));
         }
    -    
    +
         @Test
         public void test_noContentType() throws Exception {
             Client client = AdminClientUtil.createResteasyClient();
     
             try {
                 AccessTokenResponse accessTokenResponse = executeGrantAccessTokenRequest(client);
    -                    
    +
                 WebTarget userInfoTarget = UserInfoClientUtil.getUserInfoWebTarget(client);
                 Response response = userInfoTarget.request()
                         .header(HttpHeaders.AUTHORIZATION, "bearer " + accessTokenResponse.getToken())
                         .build("POST")
                         .invoke();
    -            
    +
                 Assert.assertEquals(200, response.getStatus());
                 Assert.assertEquals("OK", response.getStatusInfo().toString());
    -           	
    +
             } finally {
                 client.close();
             }
    
d82438a611f2

Remove root auth session after backchannel logout

https://github.com/keycloak/keycloakGiuseppe GrazianoSep 23, 2024via ghsa
8 files changed · +65 40
  • services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java+1 2 modified
    @@ -307,8 +307,7 @@ public static BackchannelLogoutResponse backchannelLogout(KeycloakSession sessio
                         checkUserSessionOnlyHasLoggedOutClients(realm, userSession, logoutAuthSession);
             } finally {
                 logger.tracef("Removing logout session '%s' after backchannel logout", logoutAuthSession.getParentSession().getId());
    -            RootAuthenticationSessionModel rootAuthSession = logoutAuthSession.getParentSession();
    -            rootAuthSession.removeAuthenticationSessionByTabId(logoutAuthSession.getTabId());
    +            session.authenticationSessions().removeRootAuthenticationSession(realm, logoutAuthSession.getParentSession());
             }
     
             userSession.setState(UserSessionModel.State.LOGGED_OUT);
    
  • testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/BrowserTabUtil.java+5 1 modified
    @@ -79,6 +79,10 @@ public static BrowserTabUtil getInstanceAndSetEnv(WebDriver driver) {
             return instance;
         }
     
    +    public static void cleanup() {
    +        instances = new ArrayList<>();
    +    }
    +
         public WebDriver getDriver() {
             return driver;
         }
    @@ -155,4 +159,4 @@ private void assertValidIndex(int index) {
         public void close() {
             destroy();
         }
    -}
    \ No newline at end of file
    +}
    
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java+2 0 modified
    @@ -56,6 +56,7 @@
     import org.keycloak.testsuite.auth.page.login.UpdatePassword;
     import org.keycloak.testsuite.client.KeycloakTestingClient;
     import org.keycloak.testsuite.pages.LoginPasswordUpdatePage;
    +import org.keycloak.testsuite.util.BrowserTabUtil;
     import org.keycloak.testsuite.util.CryptoInitRule;
     import org.keycloak.testsuite.util.DroneUtils;
     import org.keycloak.testsuite.util.OAuthClient;
    @@ -251,6 +252,7 @@ public void afterAbstractKeycloakTest() throws Exception {
     
             // Remove all browsers from queue
             DroneUtils.resetQueue();
    +        BrowserTabUtil.cleanup();
         }
     
         protected TestCleanup getCleanup(String realmName) {
    
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ReAuthenticationTest.java+37 0 modified
    @@ -49,6 +49,7 @@
     import org.keycloak.testsuite.pages.LoginTotpPage;
     import org.keycloak.testsuite.pages.LoginUsernameOnlyPage;
     import org.keycloak.testsuite.pages.PasswordPage;
    +import org.keycloak.testsuite.util.BrowserTabUtil;
     import org.keycloak.testsuite.util.FederatedIdentityBuilder;
     import org.keycloak.testsuite.util.FlowUtil;
     import org.keycloak.testsuite.util.OAuthClient;
    @@ -366,6 +367,42 @@ public void loginAfterExpiredUserSession() {
             realmsResouce().realm(rep.getRealm()).update(rep);
         }
     
    +    @Test
    +    public void loginAfterLogoutWithDifferentSessionId() {
    +        BrowserTabUtil tabUtil = BrowserTabUtil.getInstanceAndSetEnv(driver);
    +
    +        assertThat(tabUtil.getCountOfTabs(), Matchers.is(1));
    +        oauth.openLoginForm();
    +        loginPage.assertCurrent();
    +
    +        tabUtil.newTab(oauth.getLoginFormUrl());
    +        assertThat(tabUtil.getCountOfTabs(), Matchers.equalTo(2));
    +        oauth.openLoginForm();
    +
    +        tabUtil.closeTab(tabUtil.getCountOfTabs() - 1);
    +        assertThat(tabUtil.getCountOfTabs(), Matchers.equalTo(1));
    +
    +        tabUtil.switchToTab(0);
    +        loginPage.assertCurrent();
    +
    +        loginPage.login("test-user@localhost", "password");
    +        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
    +        OAuthClient.AccessTokenResponse response1 = oauth.doAccessTokenRequest(code, "password");
    +        AccessToken accessToken1 = oauth.verifyToken(response1.getAccessToken());
    +
    +        oauth.doLogout(response1.getRefreshToken(), "password");
    +
    +        oauth.openLoginForm();
    +        loginPage.assertCurrent();
    +        loginPage.login("test-user@localhost", "password");
    +        code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
    +        OAuthClient.AccessTokenResponse response2 = oauth.doAccessTokenRequest(code, "password");
    +        AccessToken accessToken2 = oauth.verifyToken(response2.getAccessToken());
    +
    +        Assert.assertNotEquals(accessToken1.getId(), accessToken2.getId());
    +        Assert.assertNotEquals(accessToken1.getSessionId(), accessToken2.getSessionId());
    +    }
    +
         private void setupIdentityFirstFlow() {
             String newFlowAlias = "browser - identity first";
             testingClient.server("test").run(session -> FlowUtil.inCurrentRealm(session).copyBrowserFlow(newFlowAlias));
    
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/LogoutTest.java+3 20 modified
    @@ -146,30 +146,14 @@ public void postLogoutWithRefreshTokenAfterUserSessionLogoutAndLoginAgain() thro
     
             setTimeOffset(2);
     
    -        WaitUtils.waitForPageToLoad();
    -        loginPage.login("password");
    +        driver.navigate().refresh();
    +        oauth.fillLoginForm("test-user@localhost", "password");
     
             Assert.assertFalse(loginPage.isCurrent());
     
             String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
             OAuthClient.AccessTokenResponse tokenResponse2 = oauth.doAccessTokenRequest(code, "password");
     
    -        // POST logout with token should fail
    -        try (CloseableHttpResponse response = oauth.doLogout(refreshToken1, "password")) {
    -            assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatusLine().getStatusCode());
    -        }
    -
    -        String logoutUrl = oauth.getLogoutUrl()
    -                .idTokenHint(accessTokenResponse.getIdToken())
    -                .postLogoutRedirectUri(oauth.APP_AUTH_ROOT)
    -                .build();
    -
    -        // GET logout with ID token should fail as well
    -        try (CloseableHttpClient c = HttpClientBuilder.create().disableRedirectHandling().build();
    -             CloseableHttpResponse response = c.execute(new HttpGet(logoutUrl))) {
    -            assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatusLine().getStatusCode());
    -        }
    -
             // finally POST logout with VALID token should succeed
             try (CloseableHttpResponse response = oauth.doLogout(tokenResponse2.getRefreshToken(), "password")) {
                 MatcherAssert.assertThat(response, Matchers.statusCodeIsHC(Status.NO_CONTENT));
    @@ -178,7 +162,6 @@ public void postLogoutWithRefreshTokenAfterUserSessionLogoutAndLoginAgain() thro
             }
         }
     
    -
         @Test
         public void postLogoutFailWithCredentialsOfDifferentClient() throws Exception {
             oauth.doLogin("test-user@localhost", "password");
    @@ -247,7 +230,7 @@ private void backchannelLogoutRequest(String expectedRefreshAlg, String expected
               .idTokenHint(idTokenString)
               .postLogoutRedirectUri(oauth.APP_AUTH_ROOT)
               .build();
    -        
    +
             try (CloseableHttpClient c = HttpClientBuilder.create().disableRedirectHandling().build();
               CloseableHttpResponse response = c.execute(new HttpGet(logoutUrl))) {
                 MatcherAssert.assertThat(response, Matchers.statusCodeIsHC(Status.FOUND));
    
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/RefreshTokenTest.java+6 6 modified
    @@ -1067,8 +1067,8 @@ public void refreshTokenAfterUserLogoutAndLoginAgain() {
             try {
                 // Continue with login
                 setTimeOffset(2);
    -            WaitUtils.waitForPageToLoad();
    -            loginPage.login("password");
    +            driver.navigate().refresh();
    +            oauth.fillLoginForm("test-user@localhost", "password");
     
                 assertFalse(loginPage.isCurrent());
     
    @@ -1101,8 +1101,8 @@ public void refreshTokenAfterAdminLogoutAllAndLoginAgain() {
             try {
                 // Continue with login
                 setTimeOffset(2);
    -            WaitUtils.waitForPageToLoad();
    -            loginPage.login("password");
    +            driver.navigate().refresh();
    +            oauth.fillLoginForm("test-user@localhost", "password");
     
                 assertFalse(loginPage.isCurrent());
     
    @@ -1134,8 +1134,8 @@ public void refreshTokenAfterUserAdminLogoutEndpointAndLoginAgain() {
     
                 // Continue with login
                 setTimeOffset(2);
    -            WaitUtils.waitForPageToLoad();
    -            loginPage.login("password");
    +            driver.navigate().refresh();
    +            oauth.fillLoginForm("test-user@localhost", "password");
     
                 assertFalse(loginPage.isCurrent());
     
    
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/TokenIntrospectionTest.java+2 2 modified
    @@ -250,8 +250,8 @@ public void testIntrospectRefreshTokenAfterUserSessionLogoutAndLoginAgain() thro
     
             setTimeOffset(2);
     
    -        WaitUtils.waitForPageToLoad();
    -        loginPage.login("password");
    +        driver.navigate().refresh();
    +        oauth.fillLoginForm("test-user@localhost", "password");
             events.expectLogin().assertEvent();
     
             Assert.assertFalse(loginPage.isCurrent());
    
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/UserInfoTest.java+9 9 modified
    @@ -207,7 +207,7 @@ public void testSuccess_postMethod_body() throws Exception {
                 client.close();
             }
         }
    -    
    +
         @Test
         public void testSuccess_postMethod_charset_body() throws Exception {
             Client client = AdminClientUtil.createResteasyClient();
    @@ -531,7 +531,7 @@ public void testSuccessSignedResponsePS256() throws Exception {
         public void testSuccessSignedResponseRS256AcceptJWT() throws Exception {
             testSuccessSignedResponse(Algorithm.RS256, MediaType.APPLICATION_JWT);
         }
    - 
    +
         @Test
         public void testSessionExpired() {
             Client client = AdminClientUtil.createResteasyClient();
    @@ -607,8 +607,8 @@ public void testAccessTokenAfterUserSessionLogoutAndLoginAgain() {
     
             setTimeOffset(2);
     
    -        WaitUtils.waitForPageToLoad();
    -        loginPage.login("password");
    +        driver.navigate().refresh();
    +        oauth.fillLoginForm("test-user@localhost", "password");
             events.expectLogin().assertEvent();
     
             Assert.assertFalse(loginPage.isCurrent());
    @@ -630,7 +630,7 @@ public void testAccessTokenAfterUserSessionLogoutAndLoginAgain() {
                 response.close();
     
                 events.expect(EventType.USER_INFO_REQUEST_ERROR)
    -                    .error(Errors.INVALID_TOKEN)
    +                    .error(Errors.USER_SESSION_NOT_FOUND)
                         .user(Matchers.nullValue(String.class))
                         .session(Matchers.nullValue(String.class))
                         .detail(Details.AUTH_METHOD, Details.VALIDATE_ACCESS_TOKEN)
    @@ -1088,23 +1088,23 @@ private void testRolesAreNotInUserInfoResponse(UserInfo userInfo) {
             assertNull(userInfo.getOtherClaims().get("realm_access"));
             assertNull(userInfo.getOtherClaims().get("resource_access"));
         }
    -    
    +
         @Test
         public void test_noContentType() throws Exception {
             Client client = AdminClientUtil.createResteasyClient();
     
             try {
                 AccessTokenResponse accessTokenResponse = executeGrantAccessTokenRequest(client);
    -                    
    +
                 WebTarget userInfoTarget = UserInfoClientUtil.getUserInfoWebTarget(client);
                 Response response = userInfoTarget.request()
                         .header(HttpHeaders.AUTHORIZATION, "bearer " + accessTokenResponse.getToken())
                         .build("POST")
                         .invoke();
    -            
    +
                 Assert.assertEquals(200, response.getStatus());
                 Assert.assertEquals("OK", response.getStatusInfo().toString());
    -           	
    +
             } finally {
                 client.close();
             }
    
5344aada5ee0

Remove root auth session after backchannel logout

https://github.com/keycloak/keycloakGiuseppe GrazianoSep 23, 2024via ghsa
8 files changed · +65 40
  • services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java+1 2 modified
    @@ -305,8 +305,7 @@ public static BackchannelLogoutResponse backchannelLogout(KeycloakSession sessio
                         checkUserSessionOnlyHasLoggedOutClients(realm, userSession, logoutAuthSession);
             } finally {
                 logger.tracef("Removing logout session '%s' after backchannel logout", logoutAuthSession.getParentSession().getId());
    -            RootAuthenticationSessionModel rootAuthSession = logoutAuthSession.getParentSession();
    -            rootAuthSession.removeAuthenticationSessionByTabId(logoutAuthSession.getTabId());
    +            session.authenticationSessions().removeRootAuthenticationSession(realm, logoutAuthSession.getParentSession());
             }
     
             userSession.setState(UserSessionModel.State.LOGGED_OUT);
    
  • testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/BrowserTabUtil.java+5 1 modified
    @@ -79,6 +79,10 @@ public static BrowserTabUtil getInstanceAndSetEnv(WebDriver driver) {
             return instance;
         }
     
    +    public static void cleanup() {
    +        instances = new ArrayList<>();
    +    }
    +
         public WebDriver getDriver() {
             return driver;
         }
    @@ -155,4 +159,4 @@ private void assertValidIndex(int index) {
         public void close() {
             destroy();
         }
    -}
    \ No newline at end of file
    +}
    
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java+2 0 modified
    @@ -56,6 +56,7 @@
     import org.keycloak.testsuite.auth.page.login.UpdatePassword;
     import org.keycloak.testsuite.client.KeycloakTestingClient;
     import org.keycloak.testsuite.pages.LoginPasswordUpdatePage;
    +import org.keycloak.testsuite.util.BrowserTabUtil;
     import org.keycloak.testsuite.util.CryptoInitRule;
     import org.keycloak.testsuite.util.DroneUtils;
     import org.keycloak.testsuite.util.OAuthClient;
    @@ -251,6 +252,7 @@ public void afterAbstractKeycloakTest() throws Exception {
     
             // Remove all browsers from queue
             DroneUtils.resetQueue();
    +        BrowserTabUtil.cleanup();
         }
     
         protected TestCleanup getCleanup(String realmName) {
    
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ReAuthenticationTest.java+37 0 modified
    @@ -49,6 +49,7 @@
     import org.keycloak.testsuite.pages.LoginTotpPage;
     import org.keycloak.testsuite.pages.LoginUsernameOnlyPage;
     import org.keycloak.testsuite.pages.PasswordPage;
    +import org.keycloak.testsuite.util.BrowserTabUtil;
     import org.keycloak.testsuite.util.FederatedIdentityBuilder;
     import org.keycloak.testsuite.util.FlowUtil;
     import org.keycloak.testsuite.util.OAuthClient;
    @@ -366,6 +367,42 @@ public void loginAfterExpiredUserSession() {
             realmsResouce().realm(rep.getRealm()).update(rep);
         }
     
    +    @Test
    +    public void loginAfterLogoutWithDifferentSessionId() {
    +        BrowserTabUtil tabUtil = BrowserTabUtil.getInstanceAndSetEnv(driver);
    +
    +        assertThat(tabUtil.getCountOfTabs(), Matchers.is(1));
    +        oauth.openLoginForm();
    +        loginPage.assertCurrent();
    +
    +        tabUtil.newTab(oauth.getLoginFormUrl());
    +        assertThat(tabUtil.getCountOfTabs(), Matchers.equalTo(2));
    +        oauth.openLoginForm();
    +
    +        tabUtil.closeTab(tabUtil.getCountOfTabs() - 1);
    +        assertThat(tabUtil.getCountOfTabs(), Matchers.equalTo(1));
    +
    +        tabUtil.switchToTab(0);
    +        loginPage.assertCurrent();
    +
    +        loginPage.login("test-user@localhost", "password");
    +        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
    +        OAuthClient.AccessTokenResponse response1 = oauth.doAccessTokenRequest(code, "password");
    +        AccessToken accessToken1 = oauth.verifyToken(response1.getAccessToken());
    +
    +        oauth.doLogout(response1.getRefreshToken(), "password");
    +
    +        oauth.openLoginForm();
    +        loginPage.assertCurrent();
    +        loginPage.login("test-user@localhost", "password");
    +        code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
    +        OAuthClient.AccessTokenResponse response2 = oauth.doAccessTokenRequest(code, "password");
    +        AccessToken accessToken2 = oauth.verifyToken(response2.getAccessToken());
    +
    +        Assert.assertNotEquals(accessToken1.getId(), accessToken2.getId());
    +        Assert.assertNotEquals(accessToken1.getSessionId(), accessToken2.getSessionId());
    +    }
    +
         private void setupIdentityFirstFlow() {
             String newFlowAlias = "browser - identity first";
             testingClient.server("test").run(session -> FlowUtil.inCurrentRealm(session).copyBrowserFlow(newFlowAlias));
    
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/LogoutTest.java+3 20 modified
    @@ -146,30 +146,14 @@ public void postLogoutWithRefreshTokenAfterUserSessionLogoutAndLoginAgain() thro
     
             setTimeOffset(2);
     
    -        WaitUtils.waitForPageToLoad();
    -        loginPage.login("password");
    +        driver.navigate().refresh();
    +        oauth.fillLoginForm("test-user@localhost", "password");
     
             Assert.assertFalse(loginPage.isCurrent());
     
             String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
             OAuthClient.AccessTokenResponse tokenResponse2 = oauth.doAccessTokenRequest(code, "password");
     
    -        // POST logout with token should fail
    -        try (CloseableHttpResponse response = oauth.doLogout(refreshToken1, "password")) {
    -            assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatusLine().getStatusCode());
    -        }
    -
    -        String logoutUrl = oauth.getLogoutUrl()
    -                .idTokenHint(accessTokenResponse.getIdToken())
    -                .postLogoutRedirectUri(oauth.APP_AUTH_ROOT)
    -                .build();
    -
    -        // GET logout with ID token should fail as well
    -        try (CloseableHttpClient c = HttpClientBuilder.create().disableRedirectHandling().build();
    -             CloseableHttpResponse response = c.execute(new HttpGet(logoutUrl))) {
    -            assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatusLine().getStatusCode());
    -        }
    -
             // finally POST logout with VALID token should succeed
             try (CloseableHttpResponse response = oauth.doLogout(tokenResponse2.getRefreshToken(), "password")) {
                 MatcherAssert.assertThat(response, Matchers.statusCodeIsHC(Status.NO_CONTENT));
    @@ -178,7 +162,6 @@ public void postLogoutWithRefreshTokenAfterUserSessionLogoutAndLoginAgain() thro
             }
         }
     
    -
         @Test
         public void postLogoutFailWithCredentialsOfDifferentClient() throws Exception {
             oauth.doLogin("test-user@localhost", "password");
    @@ -247,7 +230,7 @@ private void backchannelLogoutRequest(String expectedRefreshAlg, String expected
               .idTokenHint(idTokenString)
               .postLogoutRedirectUri(oauth.APP_AUTH_ROOT)
               .build();
    -        
    +
             try (CloseableHttpClient c = HttpClientBuilder.create().disableRedirectHandling().build();
               CloseableHttpResponse response = c.execute(new HttpGet(logoutUrl))) {
                 MatcherAssert.assertThat(response, Matchers.statusCodeIsHC(Status.FOUND));
    
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/RefreshTokenTest.java+6 6 modified
    @@ -942,8 +942,8 @@ public void refreshTokenAfterUserLogoutAndLoginAgain() {
             try {
                 // Continue with login
                 setTimeOffset(2);
    -            WaitUtils.waitForPageToLoad();
    -            loginPage.login("password");
    +            driver.navigate().refresh();
    +            oauth.fillLoginForm("test-user@localhost", "password");
     
                 assertFalse(loginPage.isCurrent());
     
    @@ -976,8 +976,8 @@ public void refreshTokenAfterAdminLogoutAllAndLoginAgain() {
             try {
                 // Continue with login
                 setTimeOffset(2);
    -            WaitUtils.waitForPageToLoad();
    -            loginPage.login("password");
    +            driver.navigate().refresh();
    +            oauth.fillLoginForm("test-user@localhost", "password");
     
                 assertFalse(loginPage.isCurrent());
     
    @@ -1009,8 +1009,8 @@ public void refreshTokenAfterUserAdminLogoutEndpointAndLoginAgain() {
     
                 // Continue with login
                 setTimeOffset(2);
    -            WaitUtils.waitForPageToLoad();
    -            loginPage.login("password");
    +            driver.navigate().refresh();
    +            oauth.fillLoginForm("test-user@localhost", "password");
     
                 assertFalse(loginPage.isCurrent());
     
    
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/TokenIntrospectionTest.java+2 2 modified
    @@ -244,8 +244,8 @@ public void testIntrospectRefreshTokenAfterUserSessionLogoutAndLoginAgain() thro
     
             setTimeOffset(2);
     
    -        WaitUtils.waitForPageToLoad();
    -        loginPage.login("password");
    +        driver.navigate().refresh();
    +        oauth.fillLoginForm("test-user@localhost", "password");
             events.expectLogin().assertEvent();
     
             Assert.assertFalse(loginPage.isCurrent());
    
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/UserInfoTest.java+9 9 modified
    @@ -207,7 +207,7 @@ public void testSuccess_postMethod_body() throws Exception {
                 client.close();
             }
         }
    -    
    +
         @Test
         public void testSuccess_postMethod_charset_body() throws Exception {
             Client client = AdminClientUtil.createResteasyClient();
    @@ -531,7 +531,7 @@ public void testSuccessSignedResponsePS256() throws Exception {
         public void testSuccessSignedResponseRS256AcceptJWT() throws Exception {
             testSuccessSignedResponse(Algorithm.RS256, MediaType.APPLICATION_JWT);
         }
    - 
    +
         @Test
         public void testSessionExpired() {
             Client client = AdminClientUtil.createResteasyClient();
    @@ -607,8 +607,8 @@ public void testAccessTokenAfterUserSessionLogoutAndLoginAgain() {
     
             setTimeOffset(2);
     
    -        WaitUtils.waitForPageToLoad();
    -        loginPage.login("password");
    +        driver.navigate().refresh();
    +        oauth.fillLoginForm("test-user@localhost", "password");
             events.expectLogin().assertEvent();
     
             Assert.assertFalse(loginPage.isCurrent());
    @@ -630,7 +630,7 @@ public void testAccessTokenAfterUserSessionLogoutAndLoginAgain() {
                 response.close();
     
                 events.expect(EventType.USER_INFO_REQUEST_ERROR)
    -                    .error(Errors.INVALID_TOKEN)
    +                    .error(Errors.USER_SESSION_NOT_FOUND)
                         .user(Matchers.nullValue(String.class))
                         .session(Matchers.nullValue(String.class))
                         .detail(Details.AUTH_METHOD, Details.VALIDATE_ACCESS_TOKEN)
    @@ -1088,23 +1088,23 @@ private void testRolesAreNotInUserInfoResponse(UserInfo userInfo) {
             assertNull(userInfo.getOtherClaims().get("realm_access"));
             assertNull(userInfo.getOtherClaims().get("resource_access"));
         }
    -    
    +
         @Test
         public void test_noContentType() throws Exception {
             Client client = AdminClientUtil.createResteasyClient();
     
             try {
                 AccessTokenResponse accessTokenResponse = executeGrantAccessTokenRequest(client);
    -                    
    +
                 WebTarget userInfoTarget = UserInfoClientUtil.getUserInfoWebTarget(client);
                 Response response = userInfoTarget.request()
                         .header(HttpHeaders.AUTHORIZATION, "bearer " + accessTokenResponse.getToken())
                         .build("POST")
                         .invoke();
    -            
    +
                 Assert.assertEquals(200, response.getStatus());
                 Assert.assertEquals("OK", response.getStatusInfo().toString());
    -           	
    +
             } finally {
                 client.close();
             }
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

14

News mentions

0

No linked articles in our index yet.