package org.cloudfoundry.identity.uaa.zone; import org.cloudfoundry.identity.uaa.audit.event.EntityDeletedEvent; import org.cloudfoundry.identity.uaa.authentication.UaaAuthentication; import org.cloudfoundry.identity.uaa.authentication.UaaAuthenticationTestFactory; import org.cloudfoundry.identity.uaa.constants.OriginKeys; import org.cloudfoundry.identity.uaa.oauth.UaaOauth2Authentication; import org.cloudfoundry.identity.uaa.oauth.client.ClientConstants; import org.cloudfoundry.identity.uaa.test.JdbcTestBase; import org.cloudfoundry.identity.uaa.test.UaaTestAccounts; import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.oauth2.common.util.RandomValueStringGenerator; import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.ClientAlreadyExistsException; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.NoSuchClientException; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.client.BaseClientDetails; import org.springframework.util.StringUtils; import java.sql.Timestamp; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import static org.cloudfoundry.identity.uaa.oauth.client.ClientConstants.REQUIRED_USER_GROUPS; import static org.cloudfoundry.identity.uaa.oauth.client.ClientDetailsModification.SECRET; import static org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder.isUaa; import static org.cloudfoundry.identity.uaa.zone.MultitenantJdbcClientDetailsService.DEFAULT_DELETE_STATEMENT; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; public class MultitenantJdbcClientDetailsServiceTests extends JdbcTestBase { private MultitenantJdbcClientDetailsService service; private static final String SELECT_SQL = "select client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, lastmodified, required_user_groups from oauth_client_details where client_id=?"; private static final String INSERT_SQL = "insert into oauth_client_details (client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, autoapprove, identity_zone_id, lastmodified, required_user_groups) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?)"; private UaaTestAccounts testAccounts = UaaTestAccounts.standard(null); private IdentityZone otherIdentityZone; private RandomValueStringGenerator generate = new RandomValueStringGenerator(); @Rule public ExpectedException expectedEx = ExpectedException.none(); private String dbRequestedUserGroups = "uaa.user,uaa.something"; private BaseClientDetails clientDetails; private JdbcTemplate template; @Before public void setup() throws Exception { jdbcTemplate.update("DELETE FROM oauth_client_details"); Authentication authentication = mock(Authentication.class); SecurityContextHolder.getContext().setAuthentication(authentication); template = spy(jdbcTemplate); service = spy(new MultitenantJdbcClientDetailsService(template)); otherIdentityZone = new IdentityZone(); otherIdentityZone.setId("testzone"); otherIdentityZone.setName("testzone"); otherIdentityZone.setSubdomain("testzone"); clientDetails = new BaseClientDetails(); String clientId = "client-with-id-" + new RandomValueStringGenerator(36).generate(); clientDetails.setClientId(clientId); } @Test public void event_calls_delete_method() throws Exception { ClientDetails client = addClientToDb(generate.generate()); service.onApplicationEvent(new EntityDeletedEvent<>(client, mock(UaaAuthentication.class))); verify(service, times(1)).deleteByClient(eq(client.getClientId()), eq(IdentityZoneHolder.get().getId())); } @Test public void delete_by_client_id() throws Exception { //this test ensures that one method calls the other, rather than having its own implementation for (IdentityZone zone : Arrays.asList(IdentityZone.getUaa(), otherIdentityZone)) { IdentityZoneHolder.set(zone); try { service.removeClientDetails("some-client-id"); } catch (Exception e) { } verify(service, times(1)).deleteByClient(eq("some-client-id"), eq(zone.getId())); reset(service); } } @Test public void delete_by_client_respects_zone_id_param() throws Exception { //this test ensures that one method calls the other, rather than having its own implementation for (IdentityZone zone : Arrays.asList(IdentityZone.getUaa(), otherIdentityZone)) { reset(service); reset(template); doReturn(1).when(template).update(anyString(),anyString(),anyString()); IdentityZoneHolder.set(zone); try { service.deleteByClient("some-client-id", "zone-id"); } catch (Exception e) { } verify(service, times(1)).deleteByClient(eq("some-client-id"), eq("zone-id")); verify(template, times(1)).update(DEFAULT_DELETE_STATEMENT, "some-client-id", "zone-id"); } } @Test public void delete_by_client_id_and_zone() throws Exception { List<ClientDetails> defaultZoneClients = new LinkedList<>(); addClientsInCurrentZone(defaultZoneClients, 5); for (IdentityZone zone : Arrays.asList(IdentityZone.getUaa(), otherIdentityZone)) { IdentityZoneHolder.set(zone); List<ClientDetails> clients = new LinkedList<>(); addClientsInCurrentZone(clients, 10); assertEquals((isUaa() ? 5 : 0) + clients.size(), countClientsInZone(zone.getId())); clients.removeIf( client -> { assertEquals("We deleted exactly one row", 1, service.deleteByClient(client.getClientId(), zone.getId())); assertEquals("Our client count decreased by 1", (isUaa() ? 5 : 0) + (clients.size()-1), countClientsInZone(zone.getId())); assertFalse("Client "+client.getClientId()+ " was deleted.", clientExists(client.getClientId(), zone.getId())); return true; }); assertEquals(0, clients.size()); assertEquals(isUaa() ? 5 : 0, countClientsInZone(zone.getId())); } } public void addClientsInCurrentZone(List<ClientDetails> clients, int count) { for (int i = 0; i < count; i++) { clients.add(addClientToDb(i + "-" + generate.generate())); } } @Test public void test_can_delete_zone_clients() throws Exception { String id = generate.generate(); for (IdentityZone zone : Arrays.asList(IdentityZone.getUaa(), otherIdentityZone)) { IdentityZoneHolder.set(zone); addClientToDb(id); assertThat(countClientsInZone(IdentityZoneHolder.get().getId()), is(1)); } service.onApplicationEvent(new EntityDeletedEvent<>(otherIdentityZone, null)); assertThat(countClientsInZone(otherIdentityZone.getId()), is(0)); } public int countClientsInZone(String zoneId) { return jdbcTemplate.queryForObject("select count(*) from oauth_client_details where identity_zone_id=?", new Object[] {zoneId}, Integer.class); } public boolean clientExists(String clientId, String zoneId) { return jdbcTemplate.queryForObject("select count(*) from oauth_client_details where client_id = ? and identity_zone_id=?", new Object[] {clientId, zoneId}, Integer.class) == 1; } @Test public void test_cannot_delete_uaa_zone_clients() throws Exception { String id = generate.generate(); addClientToDb(id); String zoneId = IdentityZoneHolder.get().getId(); assertThat(countClientsInZone(zoneId), is(1)); service.onApplicationEvent(new EntityDeletedEvent<>(IdentityZoneHolder.get(), null)); assertThat(countClientsInZone(zoneId), is(1)); } public ClientDetails addClientToDb(String id) { BaseClientDetails clientDetails = new BaseClientDetails(); clientDetails.setClientId(id); clientDetails.setClientSecret("secret"); service.addClientDetails(clientDetails); return service.loadClientByClientId(id); } @Test(expected = NoSuchClientException.class) public void testLoadingClientForNonExistingClientId() { service.loadClientByClientId("nonExistingClientId"); } @Test public void testLoadingClientIdWithNoDetails() { int rowsInserted = jdbcTemplate.update(INSERT_SQL, "clientIdWithNoDetails", null, null, null, null, null, null, null, null, null, IdentityZoneHolder.get().getId(), new Timestamp(System.currentTimeMillis()), dbRequestedUserGroups ); assertEquals(1, rowsInserted); ClientDetails clientDetails = service .loadClientByClientId("clientIdWithNoDetails"); assertEquals("clientIdWithNoDetails", clientDetails.getClientId()); assertFalse(clientDetails.isSecretRequired()); assertNull(clientDetails.getClientSecret()); assertFalse(clientDetails.isScoped()); assertEquals(0, clientDetails.getScope().size()); assertEquals(2, clientDetails.getAuthorizedGrantTypes().size()); assertNull(clientDetails.getRegisteredRedirectUri()); assertEquals(0, clientDetails.getAuthorities().size()); assertEquals(null, clientDetails.getAccessTokenValiditySeconds()); assertEquals(null, clientDetails.getAccessTokenValiditySeconds()); } @Test public void testLoadingClientIdWithAdditionalInformation() { long time = System.currentTimeMillis(); time = time - (time % 1000); Timestamp lastModifiedDate = new Timestamp(time); jdbcTemplate.update(INSERT_SQL, "clientIdWithAddInfo", null, null, null, null, null, null, null, null, null, IdentityZoneHolder.get().getId(), lastModifiedDate, dbRequestedUserGroups); jdbcTemplate .update("update oauth_client_details set additional_information=? where client_id=?", "{\"foo\":\"bar\"}", "clientIdWithAddInfo"); ClientDetails clientDetails = service .loadClientByClientId("clientIdWithAddInfo"); assertEquals("clientIdWithAddInfo", clientDetails.getClientId()); Map<String, Object> additionalInfoMap = new HashMap<>(); additionalInfoMap.put("foo", "bar"); additionalInfoMap.put("lastModified", lastModifiedDate); additionalInfoMap.put(REQUIRED_USER_GROUPS, StringUtils.commaDelimitedListToSet(dbRequestedUserGroups)); assertEquals(lastModifiedDate, clientDetails.getAdditionalInformation().get("lastModified")); assertEquals(additionalInfoMap, clientDetails.getAdditionalInformation()); } @Test public void autoApproveOnlyReturnedInField_andNotInAdditionalInfo() throws Exception { Timestamp lastModifiedDate = new Timestamp(System.currentTimeMillis()); String clientId = "client-with-autoapprove"; jdbcTemplate.update(INSERT_SQL, clientId, null, null, null, null, null, null, null, null, "foo.read", IdentityZoneHolder.get().getId(), lastModifiedDate, dbRequestedUserGroups); jdbcTemplate .update("update oauth_client_details set additional_information=? where client_id=?", "{\"autoapprove\":[\"bar.read\"]}", clientId); BaseClientDetails clientDetails = (BaseClientDetails) service .loadClientByClientId(clientId); assertEquals(clientId, clientDetails.getClientId()); assertNull(clientDetails.getAdditionalInformation().get(ClientConstants.AUTO_APPROVE)); assertThat(clientDetails.getAutoApproveScopes(), Matchers.hasItems("foo.read", "bar.read")); jdbcTemplate .update("update oauth_client_details set additional_information=? where client_id=?", "{\"autoapprove\":true}", clientId); clientDetails = (BaseClientDetails) service .loadClientByClientId(clientId); assertNull(clientDetails.getAdditionalInformation().get(ClientConstants.AUTO_APPROVE)); assertThat(clientDetails.getAutoApproveScopes(), Matchers.hasItems("true")); } @Test public void testLoadingClientIdWithSingleDetails() { jdbcTemplate.update(INSERT_SQL, "clientIdWithSingleDetails", "mySecret", "myResource", "myScope", "myAuthorizedGrantType", "myRedirectUri", "myAuthority", 100, 200, "true", IdentityZoneHolder.get().getId(), new Timestamp(System.currentTimeMillis()), dbRequestedUserGroups); ClientDetails clientDetails = service .loadClientByClientId("clientIdWithSingleDetails"); assertEquals("clientIdWithSingleDetails", clientDetails.getClientId()); assertTrue(clientDetails.isSecretRequired()); assertEquals("mySecret", clientDetails.getClientSecret()); assertTrue(clientDetails.isScoped()); assertEquals(1, clientDetails.getScope().size()); assertEquals("myScope", clientDetails.getScope().iterator().next()); assertEquals(1, clientDetails.getResourceIds().size()); assertEquals("myResource", clientDetails.getResourceIds().iterator() .next()); assertEquals(1, clientDetails.getAuthorizedGrantTypes().size()); assertEquals("myAuthorizedGrantType", clientDetails .getAuthorizedGrantTypes().iterator().next()); assertEquals("myRedirectUri", clientDetails.getRegisteredRedirectUri() .iterator().next()); assertEquals(1, clientDetails.getAuthorities().size()); assertEquals("myAuthority", clientDetails.getAuthorities().iterator() .next().getAuthority()); assertEquals(new Integer(100), clientDetails.getAccessTokenValiditySeconds()); assertEquals(new Integer(200), clientDetails.getRefreshTokenValiditySeconds()); } @Test public void load_groups_generates_empty_collection() { for (String s : Arrays.asList(null, "")) { String clientId = "clientId-" + new RandomValueStringGenerator().generate(); jdbcTemplate.update(INSERT_SQL, clientId, "mySecret", "myResource", "myScope", "myAuthorizedGrantType", "myRedirectUri", "myAuthority", 100, 200, "true", IdentityZoneHolder.get().getId(), new Timestamp(System.currentTimeMillis()), s); ClientDetails updatedClient = service.loadClientByClientId(clientId); Object userGroups = updatedClient.getAdditionalInformation().get(REQUIRED_USER_GROUPS); assertNotNull(userGroups); assertTrue(userGroups instanceof Collection); assertEquals(0, ((Collection)userGroups).size()); } } @Test public void additional_information_does_not_override_user_group_column() throws Exception { String[] groups = {"group1", "group2"}; List<String> requiredGroups = Arrays.asList(groups); clientDetails.addAdditionalInformation(REQUIRED_USER_GROUPS, requiredGroups); service.addClientDetails(clientDetails); assertEquals(1,jdbcTemplate.update("UPDATE oauth_client_details SET additional_information = ? WHERE client_id = ?", JsonUtils.writeValueAsString(clientDetails.getAdditionalInformation()), clientDetails.getClientId())); assertEquals(1,jdbcTemplate.update("UPDATE oauth_client_details SET required_user_groups = ? WHERE client_id = ?", "group1,group2,group3", clientDetails.getClientId())); ClientDetails updateClient = service.loadClientByClientId(clientDetails.getClientId()); assertThat((Collection<String>)updateClient.getAdditionalInformation().get(REQUIRED_USER_GROUPS), containsInAnyOrder("group1", "group2", "group3")); } @Test public void create_sets_required_user_groups() { String[] groups = {"group1", "group2"}; List<String> requiredGroups = Arrays.asList(groups); clientDetails.addAdditionalInformation(REQUIRED_USER_GROUPS, requiredGroups); service.addClientDetails(clientDetails); validateRequiredGroups(clientDetails.getClientId(), groups); groups = new String[] {"group1", "group2", "group3"}; requiredGroups = Arrays.asList(groups); clientDetails.addAdditionalInformation(REQUIRED_USER_GROUPS, requiredGroups); service.updateClientDetails(clientDetails); validateRequiredGroups(clientDetails.getClientId(), groups); } public void validateRequiredGroups(String clientId, String... expectedGroups) { String requiredUserGroups = jdbcTemplate.queryForObject("select required_user_groups from oauth_client_details where client_id = ?", String.class, clientId); assertNotNull(requiredUserGroups); Collection<String> savedGroups = StringUtils.commaDelimitedListToSet(requiredUserGroups); assertThat(savedGroups, containsInAnyOrder(expectedGroups)); String additionalInformation = jdbcTemplate.queryForObject("select additional_information from oauth_client_details where client_id = ?", String.class, clientId); for (String s : expectedGroups) { assertThat(additionalInformation, not(containsString(s))); } } @Test public void testLoadingClientIdWithMultipleDetails() { jdbcTemplate.update(INSERT_SQL, "clientIdWithMultipleDetails", "mySecret", "myResource1,myResource2", "myScope1,myScope2", "myAuthorizedGrantType1,myAuthorizedGrantType2", "myRedirectUri1,myRedirectUri2", "myAuthority1,myAuthority2", 100, 200, "read,write", IdentityZoneHolder.get().getId(), new Timestamp(System.currentTimeMillis()), dbRequestedUserGroups); ClientDetails clientDetails = service .loadClientByClientId("clientIdWithMultipleDetails"); assertNotNull(clientDetails.getAdditionalInformation()); Object requiredUserGroups = clientDetails.getAdditionalInformation().get(REQUIRED_USER_GROUPS); assertNotNull(requiredUserGroups); assertTrue(requiredUserGroups instanceof Collection); assertThat((Collection<String>)requiredUserGroups, containsInAnyOrder("uaa.user","uaa.something")); assertEquals("clientIdWithMultipleDetails", clientDetails.getClientId()); assertTrue(clientDetails.isSecretRequired()); assertEquals("mySecret", clientDetails.getClientSecret()); assertTrue(clientDetails.isScoped()); assertEquals(2, clientDetails.getResourceIds().size()); Iterator<String> resourceIds = clientDetails.getResourceIds() .iterator(); assertEquals("myResource1", resourceIds.next()); assertEquals("myResource2", resourceIds.next()); assertEquals(2, clientDetails.getScope().size()); Iterator<String> scope = clientDetails.getScope().iterator(); assertEquals("myScope1", scope.next()); assertEquals("myScope2", scope.next()); assertEquals(2, clientDetails.getAuthorizedGrantTypes().size()); Iterator<String> grantTypes = clientDetails.getAuthorizedGrantTypes() .iterator(); assertEquals("myAuthorizedGrantType1", grantTypes.next()); assertEquals("myAuthorizedGrantType2", grantTypes.next()); assertEquals(2, clientDetails.getRegisteredRedirectUri().size()); Iterator<String> redirectUris = clientDetails .getRegisteredRedirectUri().iterator(); assertEquals("myRedirectUri1", redirectUris.next()); assertEquals("myRedirectUri2", redirectUris.next()); assertEquals(2, clientDetails.getAuthorities().size()); Iterator<GrantedAuthority> authorities = clientDetails.getAuthorities() .iterator(); assertEquals("myAuthority1", authorities.next().getAuthority()); assertEquals("myAuthority2", authorities.next().getAuthority()); assertEquals(new Integer(100), clientDetails.getAccessTokenValiditySeconds()); assertEquals(new Integer(200), clientDetails.getRefreshTokenValiditySeconds()); assertTrue(clientDetails.isAutoApprove("read")); } @Test public void testAddClientWithNoDetails() { BaseClientDetails clientDetails = new BaseClientDetails(); clientDetails.setClientId("addedClientIdWithNoDetails"); service.addClientDetails(clientDetails); Map<String, Object> map = jdbcTemplate.queryForMap(SELECT_SQL, "addedClientIdWithNoDetails"); assertEquals("addedClientIdWithNoDetails", map.get("client_id")); assertTrue(map.containsKey("client_secret")); assertEquals(null, map.get("client_secret")); } @Test public void testAddClientWithSalt() throws Exception { String id = "addedClientIdWithSalt"; BaseClientDetails clientDetails = new BaseClientDetails(); clientDetails.setClientId(id); clientDetails.setClientSecret("secret"); clientDetails.addAdditionalInformation(ClientConstants.TOKEN_SALT, "salt"); service.addClientDetails(clientDetails); clientDetails = (BaseClientDetails)service.loadClientByClientId(id); assertNotNull(clientDetails); assertEquals("salt", clientDetails.getAdditionalInformation().get(ClientConstants.TOKEN_SALT)); clientDetails.addAdditionalInformation(ClientConstants.TOKEN_SALT, "newsalt"); service.updateClientDetails(clientDetails); clientDetails = (BaseClientDetails)service.loadClientByClientId(id); assertNotNull(clientDetails); assertEquals("newsalt", clientDetails.getAdditionalInformation().get(ClientConstants.TOKEN_SALT)); } @Test(expected = ClientAlreadyExistsException.class) public void testInsertDuplicateClient() { BaseClientDetails clientDetails = new BaseClientDetails(); clientDetails.setClientId("duplicateClientIdWithNoDetails"); service.addClientDetails(clientDetails); service.addClientDetails(clientDetails); } @Test public void testUpdateClientSecret() { BaseClientDetails clientDetails = new BaseClientDetails(); clientDetails.setClientId("newClientIdWithNoDetails"); service.setPasswordEncoder(new PasswordEncoder() { public boolean matches(CharSequence rawPassword, String encodedPassword) { return true; } public String encode(CharSequence rawPassword) { return "BAR"; } }); service.addClientDetails(clientDetails); service.updateClientSecret(clientDetails.getClientId(), "foo"); Map<String, Object> map = jdbcTemplate.queryForMap(SELECT_SQL, "newClientIdWithNoDetails"); assertEquals("newClientIdWithNoDetails", map.get("client_id")); assertTrue(map.containsKey("client_secret")); assertEquals("BAR", map.get("client_secret")); } @Test public void testDeleteClientSecret() { String clientId = "client_id_test_delete"; BaseClientDetails clientDetails = new BaseClientDetails(); clientDetails.setClientId(clientId); clientDetails.setClientSecret(SECRET); service.addClientDetails(clientDetails); service.addClientSecret(clientId, "new_secret"); Map<String, Object> map = jdbcTemplate.queryForMap(SELECT_SQL, clientId); String clientSecretBeforeDelete = (String) map.get("client_secret"); assertNotNull(clientSecretBeforeDelete); assertEquals(2, clientSecretBeforeDelete.split(" ").length); service.deleteClientSecret(clientId); map = jdbcTemplate.queryForMap(SELECT_SQL, clientId); String clientSecret = (String) map.get("client_secret"); assertNotNull(clientSecret); assertEquals(1, clientSecret.split(" ").length); assertEquals(clientSecretBeforeDelete.split(" ")[1], clientSecret); } @Test public void testDeleteClientSecretForInvalidClient() { expectedEx.expect(NoSuchClientException.class); expectedEx.expectMessage("No client with requested id: invalid_client_id"); service.deleteClientSecret("invalid_client_id"); } @Test public void testUpdateClientRedirectURI() { BaseClientDetails clientDetails = new BaseClientDetails(); clientDetails.setClientId("newClientIdWithNoDetails"); service.addClientDetails(clientDetails); String[] redirectURI = { "http://localhost:8080", "http://localhost:9090" }; clientDetails.setRegisteredRedirectUri(new HashSet<String>(Arrays .asList(redirectURI))); service.updateClientDetails(clientDetails); Map<String, Object> map = jdbcTemplate.queryForMap(SELECT_SQL, "newClientIdWithNoDetails"); assertEquals("newClientIdWithNoDetails", map.get("client_id")); assertTrue(map.containsKey("web_server_redirect_uri")); assertEquals("http://localhost:8080,http://localhost:9090", map.get("web_server_redirect_uri")); } @Test(expected = NoSuchClientException.class) public void testUpdateNonExistentClient() { BaseClientDetails clientDetails = new BaseClientDetails(); clientDetails.setClientId("nosuchClientIdWithNoDetails"); service.updateClientDetails(clientDetails); } @Test public void testRemoveClient() { BaseClientDetails clientDetails = new BaseClientDetails(); clientDetails.setClientId("deletedClientIdWithNoDetails"); service.addClientDetails(clientDetails); service.removeClientDetails(clientDetails.getClientId()); int count = jdbcTemplate.queryForObject( "select count(*) from oauth_client_details where client_id=?", Integer.class, "deletedClientIdWithNoDetails"); assertEquals(0, count); } @Test(expected = NoSuchClientException.class) public void testRemoveNonExistentClient() { BaseClientDetails clientDetails = new BaseClientDetails(); clientDetails.setClientId("nosuchClientIdWithNoDetails"); service.removeClientDetails(clientDetails.getClientId()); } @Test public void testFindClients() { BaseClientDetails clientDetails = new BaseClientDetails(); clientDetails.setClientId("aclient"); service.addClientDetails(clientDetails); int count = service.listClientDetails().size(); assertEquals(1, count); } @Test public void testLoadingClientInOtherZoneFromOtherZone() { IdentityZoneHolder.set(otherIdentityZone); BaseClientDetails clientDetails = new BaseClientDetails(); clientDetails.setClientId("clientInOtherZone"); service.addClientDetails(clientDetails); assertNotNull(service.loadClientByClientId("clientInOtherZone")); } @Test(expected = NoSuchClientException.class) public void testLoadingClientInOtherZoneFromDefaultZoneFails() { IdentityZoneHolder.set(otherIdentityZone); BaseClientDetails clientDetails = new BaseClientDetails(); clientDetails.setClientId("clientInOtherZone"); service.addClientDetails(clientDetails); IdentityZoneHolder.clear(); service.loadClientByClientId("clientInOtherZone"); } @Test public void testAddingClientToOtherIdentityZoneShouldHaveOtherIdentityZoneId() { IdentityZoneHolder.set(otherIdentityZone); BaseClientDetails clientDetails = new BaseClientDetails(); String clientId = "clientInOtherZone"; clientDetails.setClientId(clientId); service.addClientDetails(clientDetails); String identityZoneId = jdbcTemplate.queryForObject("select identity_zone_id from oauth_client_details where client_id = ?", String.class,clientId); assertEquals(otherIdentityZone.getId(), identityZoneId.trim()); } @Test public void testAddingClientToDefaultIdentityZoneShouldHaveAnIdentityZoneId() { BaseClientDetails clientDetails = new BaseClientDetails(); String clientId = "clientInDefaultZone"; clientDetails.setClientId(clientId); service.addClientDetails(clientDetails); String identityZoneId = jdbcTemplate.queryForObject("select identity_zone_id from oauth_client_details where client_id = ?", String.class,clientId); assertEquals(IdentityZone.getUaa().getId(), identityZoneId.trim()); } @Test public void testCreatedByIdInCaseOfUser() throws Exception { String userId = "4097895b-ebc1-4732-b6e5-2c33dd2c7cd1"; Authentication oldAuth = authenticateAsUserAndReturnOldAuth(userId); BaseClientDetails clientDetails = new BaseClientDetails(); String clientId = "clientInDefaultZone"; clientDetails.setClientId(clientId); service.addClientDetails(clientDetails); assertEquals(userId, service.getCreatedByForClientAndZone(clientId, OriginKeys.UAA)); //Restore context SecurityContextHolder.getContext().setAuthentication(oldAuth); } @Test public void testCreatedByIdInCaseOfClient() throws Exception { String userId = "4097895b-ebc1-4732-b6e5-2c33dd2c7cd1"; Authentication oldAuth = authenticateAsUserAndReturnOldAuth(userId); BaseClientDetails clientDetails = new BaseClientDetails(); clientDetails.setClientId("client1"); service.addClientDetails(clientDetails); authenticateAsClient(); clientDetails = new BaseClientDetails(); String clientId = "client2"; clientDetails.setClientId(clientId); service.addClientDetails(clientDetails); assertEquals(userId, service.getCreatedByForClientAndZone(clientId, OriginKeys.UAA)); //Restore context SecurityContextHolder.getContext().setAuthentication(oldAuth); } @Test public void testNullCreatedById() throws Exception { Authentication authentication = mock(Authentication.class); when(authentication.getPrincipal()).thenReturn(null); SecurityContextHolder.getContext().setAuthentication(authentication); String client1 = "client1"; String client2 = "client2"; BaseClientDetails clientDetails = new BaseClientDetails(); clientDetails.setClientId(client1); service.addClientDetails(clientDetails); assertNull(service.getCreatedByForClientAndZone(client1, OriginKeys.UAA)); authenticateAsClient(); clientDetails = new BaseClientDetails(); clientDetails.setClientId(client2); service.addClientDetails(clientDetails); assertNull(service.getCreatedByForClientAndZone(client2, OriginKeys.UAA)); } private Authentication authenticateAsUserAndReturnOldAuth(String userId) { Authentication authentication = new OAuth2Authentication(new AuthorizationRequest("client", Arrays.asList("read")).createOAuth2Request(), UaaAuthenticationTestFactory.getAuthentication(userId, "joe", "joe@test.org")); Authentication currentAuth = SecurityContextHolder.getContext().getAuthentication(); SecurityContextHolder.getContext().setAuthentication(authentication); return currentAuth; } private void authenticateAsClient() { UaaOauth2Authentication authentication = mock(UaaOauth2Authentication.class); when(authentication.getZoneId()).thenReturn(OriginKeys.UAA); when(authentication.getPrincipal()).thenReturn("client1"); SecurityContextHolder.getContext().setAuthentication(authentication); } }