KEYCLOAK-13186 Remove role information from RefreshTokens

We now no longer expose role assignment information into the RefreshToken.

Previously RefreshTokens contained information about the realm and
client specific roles which are assigned to a user. Since the role
information is usually either taken from the AccessToken, IDToken or
the User-Info endpoint and the RefreshToken is an internal format which
is opaque to the client, it would be a waste of space to keep that
information in the RefreshToken.

See:
https://lists.jboss.org/pipermail/keycloak-dev/2019-April/011936.html
This commit is contained in:
Thomas Darimont 2020-03-03 13:21:36 +01:00 committed by Marek Posolda
parent ad3b9fc389
commit cd51ff3474
2 changed files with 33 additions and 15 deletions

View file

@ -34,8 +34,7 @@ public class RefreshToken extends AccessToken {
} }
/** /**
* Deep copies issuer, subject, issuedFor, sessionState, realmAccess, and resourceAccess * Deep copies issuer, subject, issuedFor, sessionState from AccessToken.
* from AccessToken.
* *
* @param token * @param token
*/ */
@ -48,15 +47,6 @@ public class RefreshToken extends AccessToken {
this.nonce = token.nonce; this.nonce = token.nonce;
this.audience = new String[] { token.issuer }; this.audience = new String[] { token.issuer };
this.scope = token.scope; this.scope = token.scope;
if (token.realmAccess != null) {
realmAccess = token.realmAccess.clone();
}
if (token.resourceAccess != null) {
resourceAccess = new HashMap<>();
for (Map.Entry<String, Access> entry : token.resourceAccess.entrySet()) {
resourceAccess.put(entry.getKey(), entry.getValue().clone());
}
}
} }
@Override @Override

View file

@ -76,6 +76,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson; import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson;
import static org.keycloak.testsuite.admin.ApiUtil.findUserByUsername; import static org.keycloak.testsuite.admin.ApiUtil.findUserByUsername;
import static org.keycloak.testsuite.arquillian.AuthServerTestEnricher.AUTH_SERVER_SSL_REQUIRED; import static org.keycloak.testsuite.arquillian.AuthServerTestEnricher.AUTH_SERVER_SSL_REQUIRED;
@ -149,8 +150,6 @@ public class RefreshTokenTest extends AbstractKeycloakTest {
response.close(); response.close();
} }
events.clear(); events.clear();
} }
@Test @Test
@ -161,6 +160,35 @@ public class RefreshTokenTest extends AbstractKeycloakTest {
events.clear(); events.clear();
} }
@Test
public void refreshTokenStructure() {
oauth.nonce("123456");
oauth.doLogin("test-user@localhost", "password");
EventRepresentation loginEvent = events.expectLogin().assertEvent();
String sessionId = loginEvent.getSessionId();
String codeId = loginEvent.getDetails().get(Details.CODE_ID);
String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
OAuthClient.AccessTokenResponse tokenResponse = oauth.doAccessTokenRequest(code, "password");
AccessToken token = oauth.verifyToken(tokenResponse.getAccessToken());
assertEquals("123456", token.getNonce());
String refreshTokenString = tokenResponse.getRefreshToken();
RefreshToken refreshToken = oauth.parseRefreshToken(refreshTokenString);
events.expectCodeToToken(codeId, sessionId).assertEvent();
assertNotNull(refreshTokenString);
assertEquals("123456", refreshToken.getNonce());
assertNull("RealmAccess should be null for RefreshTokens", refreshToken.getRealmAccess());
assertTrue("ResourceAccess should be null for RefreshTokens", refreshToken.getResourceAccess().isEmpty());
}
@Test @Test
public void refreshTokenRequest() throws Exception { public void refreshTokenRequest() throws Exception {
oauth.nonce("123456"); oauth.nonce("123456");
@ -221,10 +249,10 @@ public class RefreshTokenTest extends AbstractKeycloakTest {
assertEquals(findUserByUsername(adminClient.realm("test"), "test-user@localhost").getId(), refreshedToken.getSubject()); assertEquals(findUserByUsername(adminClient.realm("test"), "test-user@localhost").getId(), refreshedToken.getSubject());
Assert.assertNotEquals("test-user@localhost", refreshedToken.getSubject()); Assert.assertNotEquals("test-user@localhost", refreshedToken.getSubject());
Assert.assertTrue(refreshedToken.getRealmAccess().isUserInRole("user")); assertTrue(refreshedToken.getRealmAccess().isUserInRole("user"));
assertEquals(1, refreshedToken.getResourceAccess(oauth.getClientId()).getRoles().size()); assertEquals(1, refreshedToken.getResourceAccess(oauth.getClientId()).getRoles().size());
Assert.assertTrue(refreshedToken.getResourceAccess(oauth.getClientId()).isUserInRole("customer-user")); assertTrue(refreshedToken.getResourceAccess(oauth.getClientId()).isUserInRole("customer-user"));
EventRepresentation refreshEvent = events.expectRefresh(tokenEvent.getDetails().get(Details.REFRESH_TOKEN_ID), sessionId).assertEvent(); EventRepresentation refreshEvent = events.expectRefresh(tokenEvent.getDetails().get(Details.REFRESH_TOKEN_ID), sessionId).assertEvent();
Assert.assertNotEquals(tokenEvent.getDetails().get(Details.TOKEN_ID), refreshEvent.getDetails().get(Details.TOKEN_ID)); Assert.assertNotEquals(tokenEvent.getDetails().get(Details.TOKEN_ID), refreshEvent.getDetails().get(Details.TOKEN_ID));