From 62c5bc0e9153a79d080cb54ca5f60753b7e7d0cf Mon Sep 17 00:00:00 2001 From: Stian Thorgersen Date: Tue, 17 Nov 2015 09:36:42 +0100 Subject: [PATCH] KEYCLOAK-1749 Rotate registration access token, add registration access token to admin console --- .../registration/ClientRegistration.java | 5 ++-- .../client/registration/HttpUtil.java | 20 ++++++++++--- .../messages/admin-messages_en.properties | 5 +++- .../admin/resources/js/controllers/clients.js | 13 +++++++- .../theme/base/admin/resources/js/services.js | 11 +++++++ .../partials/client-credentials-generic.html | 2 +- .../partials/client-credentials-jwt.html | 2 +- .../partials/client-credentials-secret.html | 2 +- .../partials/client-credentials.html | 5 ++++ .../client-registration-access-token.html | 18 +++++++++++ .../keycloak/admin/resources/css/styles.css | 5 ++++ .../models/utils/KeycloakModelUtils.java | 24 ++++++++++----- .../clientregistration/ClientRegAuth.java | 6 ++++ .../ClientRegistrationService.java | 6 ++++ .../DefaultClientRegistrationProvider.java | 15 ++++++++-- .../clientregistration/TokenGenerator.java | 27 ----------------- .../oidc/OIDCClientRegistrationProvider.java | 1 - .../resources/admin/ClientResource.java | 18 +++++++++++ .../client/AdapterInstallationConfigTest.java | 22 ++++++++++++++ .../client/RegistrationAccessTokenTest.java | 30 ++++++++++++++++++- 20 files changed, 187 insertions(+), 50 deletions(-) create mode 100644 forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-registration-access-token.html delete mode 100644 services/src/main/java/org/keycloak/services/clientregistration/TokenGenerator.java diff --git a/client-api/src/main/java/org/keycloak/client/registration/ClientRegistration.java b/client-api/src/main/java/org/keycloak/client/registration/ClientRegistration.java index e59de7634c..f932226440 100644 --- a/client-api/src/main/java/org/keycloak/client/registration/ClientRegistration.java +++ b/client-api/src/main/java/org/keycloak/client/registration/ClientRegistration.java @@ -55,9 +55,10 @@ public class ClientRegistration { return resultStream != null ? deserialize(resultStream, AdapterConfig.class) : null; } - public void update(ClientRepresentation client) throws ClientRegistrationException { + public ClientRepresentation update(ClientRepresentation client) throws ClientRegistrationException { String content = serialize(client); - httpUtil.doPut(content, DEFAULT, client.getClientId()); + InputStream resultStream = httpUtil.doPut(content, DEFAULT, client.getClientId()); + return resultStream != null ? deserialize(resultStream, ClientRepresentation.class) : null; } public void delete(ClientRepresentation client) throws ClientRegistrationException { diff --git a/client-api/src/main/java/org/keycloak/client/registration/HttpUtil.java b/client-api/src/main/java/org/keycloak/client/registration/HttpUtil.java index 699d378020..6444749782 100644 --- a/client-api/src/main/java/org/keycloak/client/registration/HttpUtil.java +++ b/client-api/src/main/java/org/keycloak/client/registration/HttpUtil.java @@ -80,7 +80,9 @@ class HttpUtil { responseStream.close(); return null; } else { - responseStream.close(); + if (responseStream != null) { + responseStream.close(); + } throw new HttpErrorException(response.getStatusLine()); } } catch (IOException e) { @@ -88,7 +90,7 @@ class HttpUtil { } } - void doPut(String content, String... path) throws ClientRegistrationException { + InputStream doPut(String content, String... path) throws ClientRegistrationException { try { HttpPut request = new HttpPut(getUrl(baseUri, path)); @@ -100,10 +102,20 @@ class HttpUtil { HttpResponse response = httpClient.execute(request); if (response.getEntity() != null) { - response.getEntity().getContent().close(); + response.getEntity().getContent(); } - if (response.getStatusLine().getStatusCode() != 200) { + InputStream responseStream = null; + if (response.getEntity() != null) { + responseStream = response.getEntity().getContent(); + } + + if (response.getStatusLine().getStatusCode() == 200) { + return responseStream; + } else { + if (responseStream != null) { + responseStream.close(); + } throw new HttpErrorException(response.getStatusLine()); } } catch (IOException e) { diff --git a/forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties b/forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties index bcbc98dc2d..a9e74f7020 100644 --- a/forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties +++ b/forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties @@ -270,7 +270,10 @@ client-certificate-import=Client Certificate Import import-client-certificate=Import Client Certificate jwt-import.key-alias.tooltip=Archive alias for your certificate. secret=Secret -regenerate-secret=Regenerate Secret +regenerate-secret=Regenerate Secretsecret=Secret +registrationAccessToken=Registration access token +registrationAccessToken.regenerate=Regenerate registration access token +registrationAccessToken.tooltip=The registration access token provides access for clients to the client registration service. add-role=Add Role role-name=Role Name composite=Composite diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js index c5f631609b..971b0c47a8 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js @@ -30,7 +30,7 @@ module.controller('ClientRoleListCtrl', function($scope, $location, realm, clien }); }); -module.controller('ClientCredentialsCtrl', function($scope, $location, realm, client, clientAuthenticatorProviders, clientConfigProperties, Client) { +module.controller('ClientCredentialsCtrl', function($scope, $location, realm, client, clientAuthenticatorProviders, clientConfigProperties, Client, ClientRegistrationAccessToken, Notifications) { $scope.realm = realm; $scope.client = angular.copy(client); $scope.clientAuthenticatorProviders = clientAuthenticatorProviders; @@ -68,6 +68,17 @@ module.controller('ClientCredentialsCtrl', function($scope, $location, realm, cl } }, true); + $scope.regenerateRegistrationAccessToken = function() { + var secret = ClientRegistrationAccessToken.update({ realm : $scope.realm.realm, client : $scope.client.id }, + function(data) { + Notifications.success('The registration access token has been updated.'); + $scope.client['registrationAccessToken'] = data.registrationAccessToken; + }, + function() { + Notifications.error('Failed to update the registration access token'); + } + ); + }; }); module.controller('ClientSecretCtrl', function($scope, $location, ClientSecret, Notifications) { diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js index 065f831877..34fdc9d744 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js @@ -981,6 +981,17 @@ module.factory('ClientSecret', function($resource) { }); }); +module.factory('ClientRegistrationAccessToken', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients/:client/registration-access-token', { + realm : '@realm', + client : '@client' + }, { + update : { + method : 'POST' + } + }); +}); + module.factory('ClientOrigins', function($resource) { return $resource(authUrl + '/admin/realms/:realm/clients/:client/allowed-origins', { realm : '@realm', diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-generic.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-generic.html index 631939c9bf..1d59078d1a 100644 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-generic.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-generic.html @@ -1,5 +1,5 @@
-
+
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-jwt.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-jwt.html index aa032033dc..8c581d7bc2 100644 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-jwt.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-jwt.html @@ -1,5 +1,5 @@
- +
{{:: 'certificate.tooltip' | translate}} diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-secret.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-secret.html index 2bd53dbedf..744ea80dac 100644 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-secret.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-secret.html @@ -1,5 +1,5 @@
- +
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-credentials.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-credentials.html index 96f16cad72..b1b1062dfb 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-credentials.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-credentials.html @@ -28,6 +28,11 @@
+
+ +
+
+
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-registration-access-token.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-registration-access-token.html new file mode 100644 index 0000000000..55a3546dbd --- /dev/null +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-registration-access-token.html @@ -0,0 +1,18 @@ +
+ +
+ +
+
+
+ +
+
+ +
+
+
+ {{:: 'registrationAccessToken.tooltip' | translate}} +
+ +
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/admin/resources/css/styles.css b/forms/common-themes/src/main/resources/theme/keycloak/admin/resources/css/styles.css index c0e8fb277a..500ed89990 100644 --- a/forms/common-themes/src/main/resources/theme/keycloak/admin/resources/css/styles.css +++ b/forms/common-themes/src/main/resources/theme/keycloak/admin/resources/css/styles.css @@ -22,6 +22,11 @@ table { margin-top: 20px; } +.no-margin-top { + margin-top: 0px !important; +} + + /*********** Loading ***********/ diff --git a/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java b/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java index ad5997a9a0..c35c58ecc8 100755 --- a/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java +++ b/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java @@ -1,6 +1,7 @@ package org.keycloak.models.utils; import org.bouncycastle.openssl.PEMWriter; +import org.keycloak.common.util.Base64Url; import org.keycloak.models.AuthenticationExecutionModel; import org.keycloak.models.AuthenticationFlowModel; import org.keycloak.models.ClientModel; @@ -26,12 +27,7 @@ import org.keycloak.common.util.PemUtils; import javax.crypto.spec.SecretKeySpec; import java.io.IOException; import java.io.StringWriter; -import java.security.Key; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.PublicKey; +import java.security.*; import java.security.cert.X509Certificate; import java.util.HashMap; import java.util.LinkedList; @@ -47,6 +43,8 @@ import java.util.UUID; */ public final class KeycloakModelUtils { + private static final int RANDOM_PASSWORD_BYTES = 32; + private KeycloakModelUtils() { } @@ -178,12 +176,22 @@ public final class KeycloakModelUtils { return rep; } - public static UserCredentialModel generateSecret(ClientModel app) { + public static UserCredentialModel generateSecret(ClientModel client) { UserCredentialModel secret = UserCredentialModel.generateSecret(); - app.setSecret(secret.getValue()); + client.setSecret(secret.getValue()); return secret; } + public static void generateRegistrationAccessToken(ClientModel client) { + client.setRegistrationSecret(generatePassword()); + } + + public static String generatePassword() { + byte[] buf = new byte[RANDOM_PASSWORD_BYTES]; + new SecureRandom().nextBytes(buf); + return Base64Url.encode(buf); + } + public static String getDefaultClientAuthenticatorType() { return "client-secret"; } diff --git a/services/src/main/java/org/keycloak/services/clientregistration/ClientRegAuth.java b/services/src/main/java/org/keycloak/services/clientregistration/ClientRegAuth.java index 496434993c..cf13235cfc 100644 --- a/services/src/main/java/org/keycloak/services/clientregistration/ClientRegAuth.java +++ b/services/src/main/java/org/keycloak/services/clientregistration/ClientRegAuth.java @@ -24,6 +24,7 @@ public class ClientRegAuth { private AccessToken.Access bearerRealmAccess; private boolean authenticated = false; + private boolean registrationAccessToken = false; public ClientRegAuth(KeycloakSession session, EventBuilder event) { this.session = session; @@ -48,6 +49,7 @@ public class ClientRegAuth { if (split[1].indexOf('.') == -1) { token = split[1]; authenticated = true; + registrationAccessToken = true; } else { AuthenticationManager.AuthResult authResult = new AppAuthManager().authenticateBearerToken(session, realm); bearerRealmAccess = authResult.getToken().getResourceAccess(Constants.REALM_MANAGEMENT_CLIENT_ID); @@ -59,6 +61,10 @@ public class ClientRegAuth { return authenticated; } + public boolean isRegistrationAccessToken() { + return registrationAccessToken; + } + public void requireCreate() { if (!authenticated) { event.error(Errors.NOT_ALLOWED); diff --git a/services/src/main/java/org/keycloak/services/clientregistration/ClientRegistrationService.java b/services/src/main/java/org/keycloak/services/clientregistration/ClientRegistrationService.java index ea508def4f..2aed3f1938 100644 --- a/services/src/main/java/org/keycloak/services/clientregistration/ClientRegistrationService.java +++ b/services/src/main/java/org/keycloak/services/clientregistration/ClientRegistrationService.java @@ -1,5 +1,6 @@ package org.keycloak.services.clientregistration; +import org.jboss.resteasy.spi.NotFoundException; import org.keycloak.events.EventBuilder; import org.keycloak.models.KeycloakSession; import org.keycloak.services.ErrorResponseException; @@ -28,6 +29,11 @@ public class ClientRegistrationService { checkSsl(); ClientRegistrationProvider provider = session.getProvider(ClientRegistrationProvider.class, providerId); + + if (provider == null) { + throw new NotFoundException("Client registration provider not found"); + } + provider.setEvent(event); provider.setAuth(new ClientRegAuth(session, event)); return provider; diff --git a/services/src/main/java/org/keycloak/services/clientregistration/DefaultClientRegistrationProvider.java b/services/src/main/java/org/keycloak/services/clientregistration/DefaultClientRegistrationProvider.java index 603ed089da..0fad9c2f07 100644 --- a/services/src/main/java/org/keycloak/services/clientregistration/DefaultClientRegistrationProvider.java +++ b/services/src/main/java/org/keycloak/services/clientregistration/DefaultClientRegistrationProvider.java @@ -5,6 +5,7 @@ import org.keycloak.events.EventType; import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.ModelDuplicateException; +import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.models.utils.ModelToRepresentation; import org.keycloak.models.utils.RepresentationToModel; import org.keycloak.representations.idm.ClientRepresentation; @@ -38,7 +39,7 @@ public class DefaultClientRegistrationProvider implements ClientRegistrationProv try { ClientModel clientModel = RepresentationToModel.createClient(session, session.getContext().getRealm(), client, true); - clientModel.setRegistrationSecret(TokenGenerator.createRegistrationAccessToken()); + KeycloakModelUtils.generateRegistrationAccessToken(clientModel); client = ModelToRepresentation.toRepresentation(clientModel); URI uri = session.getContext().getUri().getAbsolutePathBuilder().path(clientModel.getId()).build(); @@ -59,6 +60,10 @@ public class DefaultClientRegistrationProvider implements ClientRegistrationProv ClientModel client = session.getContext().getRealm().getClientByClientId(clientId); auth.requireView(client); + if (auth.isRegistrationAccessToken()) { + KeycloakModelUtils.generateRegistrationAccessToken(client); + } + event.client(client.getClientId()).success(); return Response.ok(ModelToRepresentation.toRepresentation(client)).build(); } @@ -74,8 +79,14 @@ public class DefaultClientRegistrationProvider implements ClientRegistrationProv RepresentationToModel.updateClient(rep, client); + if (auth.isRegistrationAccessToken()) { + KeycloakModelUtils.generateRegistrationAccessToken(client); + } + + rep = ModelToRepresentation.toRepresentation(client); + event.client(client.getClientId()).success(); - return Response.status(Response.Status.OK).build(); + return Response.ok(rep).build(); } @DELETE diff --git a/services/src/main/java/org/keycloak/services/clientregistration/TokenGenerator.java b/services/src/main/java/org/keycloak/services/clientregistration/TokenGenerator.java deleted file mode 100644 index 3c49d0f0ea..0000000000 --- a/services/src/main/java/org/keycloak/services/clientregistration/TokenGenerator.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.keycloak.services.clientregistration; - -import org.keycloak.common.util.Base64Url; - -import java.security.SecureRandom; - -/** - * @author Stian Thorgersen - */ -public class TokenGenerator { - - private static final int REGISTRATION_ACCESS_TOKEN_BYTES = 32; - - private TokenGenerator() { - } - - public String createInitialAccessToken() { - return null; - } - - public static String createRegistrationAccessToken() { - byte[] buf = new byte[REGISTRATION_ACCESS_TOKEN_BYTES]; - new SecureRandom().nextBytes(buf); - return Base64Url.encode(buf); - } - -} diff --git a/services/src/main/java/org/keycloak/services/clientregistration/oidc/OIDCClientRegistrationProvider.java b/services/src/main/java/org/keycloak/services/clientregistration/oidc/OIDCClientRegistrationProvider.java index 4d131cc913..b27ddb0383 100644 --- a/services/src/main/java/org/keycloak/services/clientregistration/oidc/OIDCClientRegistrationProvider.java +++ b/services/src/main/java/org/keycloak/services/clientregistration/oidc/OIDCClientRegistrationProvider.java @@ -15,7 +15,6 @@ import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.services.ErrorResponse; import org.keycloak.services.clientregistration.ClientRegAuth; import org.keycloak.services.clientregistration.ClientRegistrationProvider; -import org.keycloak.services.clientregistration.TokenGenerator; import javax.ws.rs.Consumes; import javax.ws.rs.POST; diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java index 5d76778196..da3eeb0cd4 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java @@ -214,6 +214,24 @@ public class ClientResource { return rep; } + /** + * Generate a new registration access token for the client + * + * @return + */ + @Path("registration-access-token") + @POST + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public ClientRepresentation regenerateRegistrationAccessToken() { + auth.requireManage(); + + KeycloakModelUtils.generateRegistrationAccessToken(client); + ClientRepresentation rep = ModelToRepresentation.toRepresentation(client); + adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).representation(rep).success(); + return rep; + } + /** * Get the client secret * diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/AdapterInstallationConfigTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/AdapterInstallationConfigTest.java index b8bdb412a3..bf98364dbd 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/AdapterInstallationConfigTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/AdapterInstallationConfigTest.java @@ -5,6 +5,7 @@ import org.junit.Test; import org.keycloak.client.registration.Auth; import org.keycloak.client.registration.ClientRegistrationException; import org.keycloak.client.registration.HttpErrorException; +import org.keycloak.common.enums.SslRequired; import org.keycloak.representations.adapters.config.AdapterConfig; import org.keycloak.representations.idm.ClientRepresentation; @@ -20,11 +21,14 @@ public class AdapterInstallationConfigTest extends AbstractClientRegistrationTes private ClientRepresentation client; private ClientRepresentation client2; private ClientRepresentation clientPublic; + private String publicKey; @Before public void before() throws Exception { super.before(); + publicKey = adminClient.realm(REALM_NAME).toRepresentation().getPublicKey(); + client = new ClientRepresentation(); client.setEnabled(true); client.setClientId("RegistrationAccessTokenTest"); @@ -66,6 +70,16 @@ public class AdapterInstallationConfigTest extends AbstractClientRegistrationTes AdapterConfig config = reg.getAdapterConfig(client.getClientId()); assertNotNull(config); + + assertEquals(testContext.getAuthServerContextRoot() + "/auth", config.getAuthServerUrl()); + assertEquals("test", config.getRealm()); + + assertEquals(1, config.getCredentials().size()); + assertEquals(client.getSecret(), config.getCredentials().get("secret")); + + assertEquals(publicKey, config.getRealmKey()); + assertEquals(client.getClientId(), config.getResource()); + assertEquals(SslRequired.EXTERNAL.name().toLowerCase(), config.getSslRequired()); } @Test @@ -98,6 +112,14 @@ public class AdapterInstallationConfigTest extends AbstractClientRegistrationTes AdapterConfig config = reg.getAdapterConfig(clientPublic.getClientId()); assertNotNull(config); + + assertEquals("test", config.getRealm()); + + assertEquals(0, config.getCredentials().size()); + + assertEquals(publicKey, config.getRealmKey()); + assertEquals(clientPublic.getClientId(), config.getResource()); + assertEquals(SslRequired.EXTERNAL.name().toLowerCase(), config.getSslRequired()); } } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/RegistrationAccessTokenTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/RegistrationAccessTokenTest.java index d76da19bcb..be880bf293 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/RegistrationAccessTokenTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/RegistrationAccessTokenTest.java @@ -33,10 +33,33 @@ public class RegistrationAccessTokenTest extends AbstractClientRegistrationTest reg.auth(Auth.token(client.getRegistrationAccessToken())); } + private ClientRepresentation assertRead(String id, String registrationAccess, boolean expectSuccess) throws ClientRegistrationException { + if (expectSuccess) { + reg.auth(Auth.token(registrationAccess)); + ClientRepresentation rep = reg.get(client.getClientId()); + assertNotNull(rep); + return rep; + } else { + reg.auth(Auth.token(registrationAccess)); + try { + reg.get(client.getClientId()); + fail("Expected 403"); + } catch (ClientRegistrationException e) { + assertEquals(403, ((HttpErrorException) e.getCause()).getStatusLine().getStatusCode()); + } + } + return null; + } + @Test public void getClientWithRegistrationToken() throws ClientRegistrationException { ClientRepresentation rep = reg.get(client.getClientId()); assertNotNull(rep); + assertNotEquals(client.getRegistrationAccessToken(), rep.getRegistrationAccessToken()); + + // check registration access token is updated + assertRead(client.getClientId(), client.getRegistrationAccessToken(), false); + assertRead(client.getClientId(), rep.getRegistrationAccessToken(), true); } @Test @@ -53,9 +76,14 @@ public class RegistrationAccessTokenTest extends AbstractClientRegistrationTest @Test public void updateClientWithRegistrationToken() throws ClientRegistrationException { client.setRootUrl("http://newroot"); - reg.update(client); + ClientRepresentation rep = reg.update(client); assertEquals("http://newroot", getClient(client.getId()).getRootUrl()); + assertNotEquals(client.getRegistrationAccessToken(), rep.getRegistrationAccessToken()); + + // check registration access token is updated + assertRead(client.getClientId(), client.getRegistrationAccessToken(), false); + assertRead(client.getClientId(), rep.getRegistrationAccessToken(), true); } @Test