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 c671607..5e48c7b 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
@@ -38,6 +38,7 @@ import org.keycloak.models.GroupModel;
import org.keycloak.models.KeyManager;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.ModelException;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
@@ -130,15 +131,24 @@ public class TokenManager {
if (TokenUtil.TOKEN_TYPE_OFFLINE.equals(oldToken.getType())) {
UserSessionManager sessionManager = new UserSessionManager(session);
- clientSession = sessionManager.findOfflineClientSession(realm, oldToken.getClientSession(), oldToken.getSessionState());
+ clientSession = sessionManager.findOfflineClientSession(realm, oldToken.getClientSession());
if (clientSession != null) {
userSession = clientSession.getUserSession();
+ if (userSession == null) {
+ throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Offline user session not found", "Offline user session not found");
+ }
+
+ String userSessionId = oldToken.getSessionState();
+ if (!userSessionId.equals(userSession.getId())) {
+ throw new ModelException("User session don't match. Offline client session " + clientSession.getId() + ", It's user session " + userSession.getId() +
+ " Wanted user session: " + userSessionId);
+ }
+
// Revoke timeouted offline userSession
if (userSession.getLastSessionRefresh() < Time.currentTime() - realm.getOfflineSessionIdleTimeout()) {
sessionManager.revokeOfflineUserSession(userSession);
- userSession = null;
- clientSession = null;
+ throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Offline user session not active", "Offline user session session not active");
}
}
} else {
diff --git a/services/src/main/java/org/keycloak/services/managers/UserSessionManager.java b/services/src/main/java/org/keycloak/services/managers/UserSessionManager.java
index e3ee409..4c8c2fe 100644
--- a/services/src/main/java/org/keycloak/services/managers/UserSessionManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/UserSessionManager.java
@@ -72,18 +72,8 @@ public class UserSessionManager {
}
// userSessionId is provided from offline token. It's used just to verify if it match the ID from clientSession representation
- public ClientSessionModel findOfflineClientSession(RealmModel realm, String clientSessionId, String userSessionId) {
- ClientSessionModel clientSession = kcSession.sessions().getOfflineClientSession(realm, clientSessionId);
- if (clientSession == null) {
- return null;
- }
-
- if (!userSessionId.equals(clientSession.getUserSession().getId())) {
- throw new ModelException("User session don't match. Offline client session " + clientSession.getId() + ", It's user session " + clientSession.getUserSession().getId() +
- " Wanted user session: " + userSessionId);
- }
-
- return clientSession;
+ public ClientSessionModel findOfflineClientSession(RealmModel realm, String clientSessionId) {
+ return kcSession.sessions().getOfflineClientSession(realm, clientSessionId);
}
public Set<ClientModel> findClientsWithOfflineToken(RealmModel realm, UserModel user) {
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderOfflineTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderOfflineTest.java
index b9f4f2a..fb4b3af 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderOfflineTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderOfflineTest.java
@@ -107,7 +107,7 @@ public class UserSessionProviderOfflineTest {
// Assert all previously saved offline sessions found
for (Map.Entry<String, String> entry : offlineSessions.entrySet()) {
- Assert.assertTrue(sessionManager.findOfflineClientSession(realm, entry.getKey(), entry.getValue()) != null);
+ Assert.assertTrue(sessionManager.findOfflineClientSession(realm, entry.getKey()) != null);
UserSessionModel offlineSession = session.sessions().getUserSession(realm, entry.getValue());
boolean found = false;
@@ -187,7 +187,7 @@ public class UserSessionProviderOfflineTest {
resetSession();
- ClientSessionModel offlineClientSession = sessionManager.findOfflineClientSession(fooRealm, clientSession.getId(), userSession.getId());
+ ClientSessionModel offlineClientSession = sessionManager.findOfflineClientSession(fooRealm, clientSession.getId());
Assert.assertEquals("foo-app", offlineClientSession.getClient().getClientId());
Assert.assertEquals("user3", offlineClientSession.getUserSession().getUser().getUsername());
Assert.assertEquals(offlineClientSession.getId(), offlineClientSession.getUserSession().getClientSessions().get(0).getId());
@@ -206,7 +206,7 @@ public class UserSessionProviderOfflineTest {
// Assert nothing loaded
fooRealm = session.realms().getRealm("foo");
- Assert.assertNull(sessionManager.findOfflineClientSession(fooRealm, clientSession.getId(), userSession.getId()));
+ Assert.assertNull(sessionManager.findOfflineClientSession(fooRealm, clientSession.getId()));
Assert.assertEquals(0, session.sessions().getOfflineSessionsCount(fooRealm, fooRealm.getClientByClientId("foo-app")));
// Cleanup
@@ -338,7 +338,7 @@ public class UserSessionProviderOfflineTest {
// Assert all previously saved offline sessions found
for (Map.Entry<String, String> entry : offlineSessions.entrySet()) {
- Assert.assertTrue(sessionManager.findOfflineClientSession(realm, entry.getKey(), entry.getValue()) != null);
+ Assert.assertTrue(sessionManager.findOfflineClientSession(realm, entry.getKey()) != null);
}
UserSessionModel session0 = session.sessions().getOfflineUserSession(realm, origSessions[0].getId());
@@ -379,9 +379,9 @@ public class UserSessionProviderOfflineTest {
for (Map.Entry<String, String> entry : offlineSessions.entrySet()) {
String userSessionId = entry.getValue();
if (userSessionId.equals(session1.getId())) {
- Assert.assertFalse(sessionManager.findOfflineClientSession(realm, entry.getKey(), userSessionId) != null);
+ Assert.assertFalse(sessionManager.findOfflineClientSession(realm, entry.getKey()) != null);
} else {
- Assert.assertTrue(sessionManager.findOfflineClientSession(realm, entry.getKey(), userSessionId) != null);
+ Assert.assertTrue(sessionManager.findOfflineClientSession(realm, entry.getKey()) != null);
}
}
Assert.assertEquals(1, persister.getUserSessionsCount(true));
@@ -394,7 +394,7 @@ public class UserSessionProviderOfflineTest {
resetSession();
for (Map.Entry<String, String> entry : offlineSessions.entrySet()) {
- Assert.assertTrue(sessionManager.findOfflineClientSession(realm, entry.getKey(), entry.getValue()) == null);
+ Assert.assertTrue(sessionManager.findOfflineClientSession(realm, entry.getKey()) == null);
}
Assert.assertEquals(0, persister.getUserSessionsCount(true));
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OfflineTokenTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OfflineTokenTest.java
index 36cab0b..223a3f6 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OfflineTokenTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OfflineTokenTest.java
@@ -285,7 +285,7 @@ public class OfflineTokenTest extends AbstractKeycloakTest {
oauth.scope(OAuth2Constants.OFFLINE_ACCESS);
oauth.clientId("offline-client");
OAuthClient.AccessTokenResponse tokenResponse = oauth.doGrantAccessTokenRequest("secret1", "test-user@localhost", "password");
- tokenResponse.getErrorDescription();
+ Assert.assertNull(tokenResponse.getErrorDescription());
AccessToken token = oauth.verifyToken(tokenResponse.getAccessToken());
String offlineTokenString = tokenResponse.getRefreshToken();
RefreshToken offlineToken = oauth.verifyRefreshToken(offlineTokenString);