diff --git a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
index 8ccb497..46cec15 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
@@ -329,14 +329,6 @@ public class TokenManager {
}
}
- public RefreshToken verifyRefreshToken(KeycloakSession session, RealmModel realm, String encodedRefreshToken) throws OAuthErrorException {
- return verifyRefreshToken(session, realm, encodedRefreshToken, true);
- }
-
- public RefreshToken verifyRefreshToken(KeycloakSession session, RealmModel realm, String encodedRefreshToken, boolean checkExpiration) throws OAuthErrorException {
- return verifyRefreshToken(session, realm, null, null, encodedRefreshToken, true);
- }
-
public RefreshToken verifyRefreshToken(KeycloakSession session, RealmModel realm, ClientModel client, HttpRequest request, String encodedRefreshToken, boolean checkExpiration) throws OAuthErrorException {
try {
RefreshToken refreshToken = toRefreshToken(session, encodedRefreshToken);
@@ -355,8 +347,12 @@ public class TokenManager {
}
}
+ if (!client.getClientId().equals(refreshToken.getIssuedFor())) {
+ throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token. Token client and authorized client don't match");
+ }
+
// KEYCLOAK-6771 Certificate Bound Token
- if (client != null && OIDCAdvancedConfigWrapper.fromClientModel(client).isUseMtlsHokToken()) {
+ if (OIDCAdvancedConfigWrapper.fromClientModel(client).isUseMtlsHokToken()) {
if (!MtlsHoKTokenUtil.verifyTokenBindingWithClientCertificate(refreshToken, request, session)) {
throw new OAuthErrorException(OAuthErrorException.UNAUTHORIZED_CLIENT, MtlsHoKTokenUtil.CERT_VERIFY_ERROR_DESC);
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/LogoutTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/LogoutTest.java
index a12d684..70f6142 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/LogoutTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/LogoutTest.java
@@ -107,6 +107,27 @@ public class LogoutTest extends AbstractKeycloakTest {
}
}
+
+ @Test
+ public void postLogoutFailWithCredentialsOfDifferentClient() throws Exception {
+ oauth.doLogin("test-user@localhost", "password");
+
+ String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
+
+ oauth.clientSessionState("client-session");
+ OAuthClient.AccessTokenResponse tokenResponse = oauth.doAccessTokenRequest(code, "password");
+ String refreshTokenString = tokenResponse.getRefreshToken();
+
+ oauth.clientId("test-app-scope");
+
+ // Assert logout fails with 400 when trying to use different client credentials
+ try (CloseableHttpResponse response = oauth.doLogout(refreshTokenString, "password")) {
+ assertThat(response, Matchers.statusCodeIsHC(Status.BAD_REQUEST));
+ }
+
+ oauth.clientId("test-app");
+ }
+
@Test
public void postLogoutWithValidIdToken() throws Exception {
oauth.doLogin("test-user@localhost", "password");