Fix introspection error for pairwise access tokens

When access tokens containing a pairwise sub are introspected, user
related checks are using that sub to fetch the UserModel instead of
fetching the user from the UserSession. No corresponding user is found
(or possibly even another user) and the token is reported inactive.

Resolves: KEYCLOAK-5494
This commit is contained in:
Martin Hardselius 2017-09-15 10:17:45 +02:00
parent 685acb786a
commit a4315f4076
2 changed files with 30 additions and 11 deletions

View file

@ -203,17 +203,6 @@ public class TokenManager {
return false; return false;
} }
UserModel user = session.users().getUserById(token.getSubject(), realm);
if (user == null) {
return false;
}
if (!user.isEnabled()) {
return false;
}
if (token.getIssuedAt() < session.users().getNotBeforeOfUser(realm, user)) {
return false;
}
ClientModel client = realm.getClientByClientId(token.getIssuedFor()); ClientModel client = realm.getClientByClientId(token.getIssuedFor());
if (client == null || !client.isEnabled() || token.getIssuedAt() < client.getNotBefore()) { if (client == null || !client.isEnabled() || token.getIssuedAt() < client.getNotBefore()) {
return false; return false;
@ -224,6 +213,16 @@ public class TokenManager {
return true; return true;
} }
UserModel user = userSession.getUser();
if (user == null) {
return false;
}
if (!user.isEnabled()) {
return false;
}
if (token.getIssuedAt() < session.users().getNotBeforeOfUser(realm, user)) {
return false;
}
userSession = new UserSessionCrossDCManager(session).getUserSessionWithClient(realm, token.getSessionState(), true, client.getId()); userSession = new UserSessionCrossDCManager(session).getUserSessionWithClient(realm, token.getSessionState(), true, client.getId());
if (AuthenticationManager.isOfflineSessionValid(realm, userSession)) { if (AuthenticationManager.isOfflineSessionValid(realm, userSession)) {

View file

@ -18,6 +18,8 @@
package org.keycloak.testsuite.client; package org.keycloak.testsuite.client;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -44,9 +46,11 @@ import org.keycloak.testsuite.util.ClientManager;
import org.keycloak.testsuite.util.OAuthClient; import org.keycloak.testsuite.util.OAuthClient;
import org.keycloak.testsuite.util.UserInfoClientUtil; import org.keycloak.testsuite.util.UserInfoClientUtil;
import org.keycloak.testsuite.util.UserManager; import org.keycloak.testsuite.util.UserManager;
import org.keycloak.util.JsonSerialization;
import javax.ws.rs.client.Client; import javax.ws.rs.client.Client;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Base64; import java.util.Base64;
import java.util.Collections; import java.util.Collections;
@ -407,6 +411,22 @@ public class OIDCPairwiseClientRegistrationTest extends AbstractClientRegistrati
Assert.assertEquals(idToken.getIssuedFor(), refreshedIdToken.getIssuedFor()); Assert.assertEquals(idToken.getIssuedFor(), refreshedIdToken.getIssuedFor());
} }
@Test
public void introspectPairwiseAccessToken() throws Exception {
// Create a pairwise client
OIDCClientRepresentation pairwiseClient = createPairwise();
// Login to pairwise client
OAuthClient.AccessTokenResponse accessTokenResponse = login(pairwiseClient, "test-user@localhost", "password");
String introspectionResponse = oauth.introspectAccessTokenWithClientCredential(pairwiseClient.getClientId(), pairwiseClient.getClientSecret(), accessTokenResponse.getAccessToken());
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(introspectionResponse);
Assert.assertEquals(true, jsonNode.get("active").asBoolean());
Assert.assertEquals("test-user@localhost", jsonNode.get("email").asText());
}
@Test @Test
public void refreshPairwiseTokenDeletedUser() throws Exception { public void refreshPairwiseTokenDeletedUser() throws Exception {
String userId = createUser(REALM_NAME, "delete-me@localhost", "password"); String userId = createUser(REALM_NAME, "delete-me@localhost", "password");