Java tutorial
/* * Copyright 2013-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.cloudfoundry.uaa; import io.netty.util.AsciiString; import org.cloudfoundry.AbstractIntegrationTest; import org.cloudfoundry.uaa.clients.BatchChangeSecretRequest; import org.cloudfoundry.uaa.clients.BatchChangeSecretResponse; import org.cloudfoundry.uaa.clients.BatchCreateClientsRequest; import org.cloudfoundry.uaa.clients.BatchCreateClientsResponse; import org.cloudfoundry.uaa.clients.BatchDeleteClientsRequest; import org.cloudfoundry.uaa.clients.BatchUpdateClientsRequest; import org.cloudfoundry.uaa.clients.BatchUpdateClientsResponse; import org.cloudfoundry.uaa.clients.ChangeSecret; import org.cloudfoundry.uaa.clients.ChangeSecretRequest; import org.cloudfoundry.uaa.clients.Client; import org.cloudfoundry.uaa.clients.CreateClient; import org.cloudfoundry.uaa.clients.CreateClientAction; import org.cloudfoundry.uaa.clients.CreateClientRequest; import org.cloudfoundry.uaa.clients.CreateClientResponse; import org.cloudfoundry.uaa.clients.DeleteClientAction; import org.cloudfoundry.uaa.clients.DeleteClientRequest; import org.cloudfoundry.uaa.clients.GetClientRequest; import org.cloudfoundry.uaa.clients.GetMetadataRequest; import org.cloudfoundry.uaa.clients.GetMetadataResponse; import org.cloudfoundry.uaa.clients.ListClientsRequest; import org.cloudfoundry.uaa.clients.ListMetadatasRequest; import org.cloudfoundry.uaa.clients.ListMetadatasResponse; import org.cloudfoundry.uaa.clients.MixedActionsRequest; import org.cloudfoundry.uaa.clients.UpdateClient; import org.cloudfoundry.uaa.clients.UpdateClientAction; import org.cloudfoundry.uaa.clients.UpdateClientRequest; import org.cloudfoundry.uaa.clients.UpdateMetadataRequest; import org.cloudfoundry.uaa.clients.UpdateMetadataResponse; import org.cloudfoundry.uaa.clients.UpdateSecretAction; import org.cloudfoundry.uaa.clients.UpdateSecretClientAction; import org.cloudfoundry.util.PaginationUtils; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; import java.time.Duration; import java.util.Base64; import static org.assertj.core.api.Assertions.assertThat; import static org.cloudfoundry.uaa.tokens.GrantType.CLIENT_CREDENTIALS; import static org.cloudfoundry.uaa.tokens.GrantType.IMPLICIT; import static org.cloudfoundry.uaa.tokens.GrantType.PASSWORD; import static org.cloudfoundry.uaa.tokens.GrantType.REFRESH_TOKEN; public final class ClientsTest extends AbstractIntegrationTest { @Autowired private String clientId; @Autowired private UaaClient uaaClient; @Test public void batchChangeSecret() { String clientId1 = this.nameFactory.getClientId(); String clientId2 = this.nameFactory.getClientId(); String clientSecret = this.nameFactory.getClientSecret(); String newClientSecret1 = this.nameFactory.getClientSecret(); String newClientSecret2 = this.nameFactory.getClientSecret(); requestCreateClient(this.uaaClient, clientId1, clientSecret) .then(requestCreateClient(this.uaaClient, clientId2, clientSecret)) .then(this.uaaClient.clients() .batchChangeSecret(BatchChangeSecretRequest.builder() .changeSecrets( ChangeSecret.builder().clientId(clientId1).oldSecret(clientSecret) .secret(newClientSecret1).build(), ChangeSecret.builder().clientId(clientId2).oldSecret(clientSecret) .secret(newClientSecret2).build()) .build())) .flatMapIterable(BatchChangeSecretResponse::getClients).as(StepVerifier::create).expectNextCount(2) .expectComplete().verify(Duration.ofMinutes(5)); } @Test public void batchCreate() { String clientId1 = this.nameFactory.getClientId(); String clientId2 = this.nameFactory.getClientId(); String clientSecret = this.nameFactory.getClientSecret(); this.uaaClient.clients().batchCreate(BatchCreateClientsRequest.builder() .client(CreateClient.builder().approvalsDeleted(true).authorizedGrantType(PASSWORD) .clientId(clientId1).clientSecret(clientSecret).scopes("client.read", "client.write") .tokenSalt("test-token-salt").build()) .client(CreateClient.builder().approvalsDeleted(true).authorizedGrantTypes(PASSWORD, REFRESH_TOKEN) .clientId(clientId2).clientSecret(clientSecret).scope("client.write") .tokenSalt("filtered-test-token-salt").build()) .build()).flatMapIterable(BatchCreateClientsResponse::getClients) .filter(client -> clientId1.equals(client.getClientId())).as(StepVerifier::create) .consumeNextWith(response -> { assertThat(response.getAuthorizedGrantTypes()).containsExactly(PASSWORD, REFRESH_TOKEN); assertThat(response.getClientId()).isEqualTo(clientId1); assertThat(response.getScopes()).containsExactly("client.read", "client.write"); assertThat(response.getTokenSalt()).isEqualTo("test-token-salt"); }).expectComplete().verify(Duration.ofMinutes(5)); } @Test public void batchDelete() { String clientId1 = this.nameFactory.getClientId(); String clientId2 = this.nameFactory.getClientId(); String clientSecret = this.nameFactory.getClientSecret(); batchCreateClients(this.uaaClient, clientId1, clientId2, clientSecret) .flatMapIterable(BatchCreateClientsResponse::getClients).map(Client::getClientId).collectList() .flatMap(clientIds -> this.uaaClient.clients() .batchDelete(BatchDeleteClientsRequest.builder().clientIds(clientIds).build())) .thenMany(requestListClients(this.uaaClient)) .filter(client -> clientId1.equals(client.getClientId()) || clientId2.equals(client.getClientId())) .as(StepVerifier::create).expectComplete().verify(Duration.ofMinutes(5)); } @Test public void batchUpdate() { String clientId1 = this.nameFactory.getClientId(); String clientId2 = this.nameFactory.getClientId(); String clientSecret = this.nameFactory.getClientSecret(); requestCreateClient(this.uaaClient, clientId1, clientSecret) .then(requestCreateClient(this.uaaClient, clientId2, clientSecret)) .then(this.uaaClient.clients().batchUpdate(BatchUpdateClientsRequest.builder() .clients(UpdateClient.builder().authorizedGrantTypes(CLIENT_CREDENTIALS, IMPLICIT) .clientId(clientId1).name("test-name").scopes("client.read", "client.write") .redirectUriPattern("https://test.com/*").tokenSalt("test-token-salt").build(), UpdateClient.builder().authorizedGrantType(PASSWORD).clientId(clientId2) .name("filtered-test-name").scope("client.write") .tokenSalt("filtered-test-token-salt").build()) .build())) .flatMapIterable(BatchUpdateClientsResponse::getClients) .filter(client -> clientId1.equals(client.getClientId())).as(StepVerifier::create) .consumeNextWith(response -> { assertThat(response.getAuthorizedGrantTypes()).containsExactly(IMPLICIT, CLIENT_CREDENTIALS); assertThat(response.getClientId()).isEqualTo(clientId1); assertThat(response.getName()).isEqualTo("test-name"); assertThat(response.getScopes()).containsExactly("client.read", "client.write"); assertThat(response.getTokenSalt()).isEqualTo("test-token-salt"); }).expectComplete().verify(Duration.ofMinutes(5)); } @Test public void changeSecret() { String clientId = this.nameFactory.getClientId(); String newClientSecret = this.nameFactory.getClientSecret(); String oldClientSecret = this.nameFactory.getClientSecret(); requestCreateClient(this.uaaClient, clientId, oldClientSecret) .then(this.uaaClient.clients() .changeSecret(ChangeSecretRequest.builder().clientId(clientId).oldSecret(oldClientSecret) .secret(newClientSecret).build())) .as(StepVerifier::create) // TODO: Update test based on https://www.pivotaltracker.com/n/projects/997278/stories/130645469 to use the following // .expectThat(response -> { // assertEquals("secret updated", response.getMessage()); // assertEquals("ok", response.getStatus()); // })); .consumeErrorWith(t -> assertThat(t).isInstanceOf(UaaException.class) .hasMessage("invalid_client: Only a client can change client secret")) .verify(Duration.ofMinutes(5)); } @Test public void create() { String clientId = this.nameFactory.getClientId(); String clientSecret = this.nameFactory.getClientSecret(); this.uaaClient.clients() .create(CreateClientRequest.builder().approvalsDeleted(true).authorizedGrantType(PASSWORD) .clientId(clientId).clientSecret(clientSecret).scopes("client.read", "client.write") .tokenSalt("test-token-salt").build()) .as(StepVerifier::create).consumeNextWith(response -> { assertThat(response.getAuthorizedGrantTypes()).containsExactly(PASSWORD, REFRESH_TOKEN); assertThat(response.getClientId()).isEqualTo(clientId); assertThat(response.getScopes()).containsExactly("client.read", "client.write"); assertThat(response.getTokenSalt()).isEqualTo("test-token-salt"); }).expectComplete().verify(Duration.ofMinutes(5)); } @Test public void delete() { String clientId = this.nameFactory.getClientId(); String clientSecret = this.nameFactory.getClientSecret(); requestCreateClient(this.uaaClient, clientId, clientSecret) .then(this.uaaClient.clients().delete(DeleteClientRequest.builder().clientId(clientId).build())) .thenMany(requestListClients(this.uaaClient)) .filter(client -> clientId.equals(client.getClientId())).as(StepVerifier::create).expectComplete() .verify(Duration.ofMinutes(5)); } @Test public void get() { String clientId = this.nameFactory.getClientId(); String clientSecret = this.nameFactory.getClientSecret(); requestCreateClient(this.uaaClient, clientId, clientSecret) .then(this.uaaClient.clients().get(GetClientRequest.builder().clientId(clientId).build())) .as(StepVerifier::create).consumeNextWith(response -> { assertThat(response.getAuthorizedGrantTypes()).containsExactly(PASSWORD, REFRESH_TOKEN); assertThat(response.getClientId()).isEqualTo(clientId); }).expectComplete().verify(Duration.ofMinutes(5)); } @Test public void getMetadata() { requestUpdateMetadata(this.uaaClient, this.clientId, "http://test.get.url") .then(this.uaaClient.clients() .getMetadata(GetMetadataRequest.builder().clientId(this.clientId).build())) .as(StepVerifier::create).consumeNextWith(metadata -> { assertThat(metadata.getAppLaunchUrl()).isEqualTo("http://test.get.url"); assertThat(metadata.getClientId()).isEqualTo(this.clientId); }).expectComplete().verify(Duration.ofMinutes(5)); } @Test public void list() { String clientId = this.nameFactory.getClientId(); String clientSecret = this.nameFactory.getClientSecret(); requestCreateClient(this.uaaClient, clientId, clientSecret) .thenMany(PaginationUtils.requestUaaResources(startIndex -> this.uaaClient.clients() .list(ListClientsRequest.builder().startIndex(startIndex).build()))) .filter(client -> clientId.equals(client.getClientId())).as(StepVerifier::create).expectNextCount(1) .expectComplete().verify(Duration.ofMinutes(5)); } @Test public void listMetadatas() { requestUpdateMetadata(this.uaaClient, this.clientId, "http://test.list.url") .then(this.uaaClient.clients().listMetadatas(ListMetadatasRequest.builder().build())) .flatMapIterable(ListMetadatasResponse::getMetadatas) .filter(metadata -> this.clientId.equals(metadata.getClientId())).single().as(StepVerifier::create) .consumeNextWith(metadata -> { assertThat(metadata.getAppLaunchUrl()).isEqualTo("http://test.list.url"); assertThat(metadata.getClientId()).isEqualTo(this.clientId); }).expectComplete().verify(Duration.ofMinutes(5)); } @Test public void mixedActions() { String clientId1 = this.nameFactory.getClientId(); String clientId2 = this.nameFactory.getClientId(); String clientSecret = this.nameFactory.getClientSecret(); String newClientSecret = this.nameFactory.getClientSecret(); this.uaaClient.clients() .mixedActions(MixedActionsRequest.builder() .action(CreateClientAction.builder().authorizedGrantType(PASSWORD).clientId(clientId1) .clientSecret(clientSecret).name("test-name-old").build()) .action(CreateClientAction.builder().authorizedGrantType(PASSWORD).clientId(clientId2) .clientSecret(clientSecret).build()) .action(UpdateClientAction.builder().authorizedGrantType(PASSWORD).clientId(clientId1) .name("test-name-temporary").build()) .action(UpdateSecretAction.builder().clientId(clientId2).secret(newClientSecret).build()) .action(DeleteClientAction.builder().clientId(clientId2).build()) .action(UpdateSecretClientAction.builder().authorizedGrantType(PASSWORD) .name("test-name-new").clientId(clientId1).secret(newClientSecret).build()) .build()) .thenMany(requestListClients(this.uaaClient)) .filter(client -> clientId1.equals(client.getClientId())).as(StepVerifier::create) .consumeNextWith(client -> assertThat(client.getName()).isEqualTo("test-name-new")).expectComplete() .verify(Duration.ofMinutes(5)); } @Test public void update() { String clientId = this.nameFactory.getClientId(); String clientSecret = this.nameFactory.getClientSecret(); requestCreateClient(this.uaaClient, clientId, clientSecret) .then(this.uaaClient.clients() .update(UpdateClientRequest.builder().authorizedGrantType(CLIENT_CREDENTIALS) .clientId(clientId).name("test-name").build())) .thenMany(requestListClients(this.uaaClient)) .filter(client -> clientId.equals(client.getClientId())).as(StepVerifier::create) .consumeNextWith(response -> { assertThat(response.getAuthorizedGrantTypes()).containsExactly(CLIENT_CREDENTIALS); assertThat(response.getClientId()).isEqualTo(clientId); assertThat(response.getName()).isEqualTo("test-name"); }).expectComplete().verify(Duration.ofMinutes(5)); } @Test public void updateMetadata() { String appIcon = Base64.getEncoder().encodeToString(new AsciiString("test-image").toByteArray()); this.uaaClient.clients() .updateMetadata( UpdateMetadataRequest.builder().appIcon(appIcon).appLaunchUrl("http://test.app.launch.url") .clientId(this.clientId).showOnHomePage(true).clientName("test-name").build()) .then(requestGetMetadata(this.uaaClient, this.clientId)).as(StepVerifier::create) .consumeNextWith(metadata -> { assertThat(metadata.getAppIcon()).isEqualTo(appIcon); assertThat(metadata.getAppLaunchUrl()).isEqualTo("http://test.app.launch.url"); assertThat(metadata.getClientId()).isEqualTo(this.clientId); assertThat(metadata.getClientName()).isEqualTo("test-name"); assertThat(metadata.getShowOnHomePage()).isTrue(); }).expectComplete().verify(Duration.ofMinutes(5)); } private static Mono<BatchCreateClientsResponse> batchCreateClients(UaaClient uaaClient, String clientId1, String clientId2, String clientSecret) { return uaaClient.clients().batchCreate(BatchCreateClientsRequest.builder() .client(CreateClient.builder().approvalsDeleted(true).authorizedGrantType(PASSWORD) .clientId(clientId1).clientSecret(clientSecret).scopes("client.read", "client.write") .tokenSalt("test-token-salt").build()) .client(CreateClient.builder().approvalsDeleted(true).authorizedGrantTypes(PASSWORD, REFRESH_TOKEN) .clientId(clientId2).clientSecret(clientSecret).scope("client.write") .tokenSalt("alternate-test-token-salt").build()) .build()); } private static Mono<CreateClientResponse> requestCreateClient(UaaClient uaaClient, String clientId, String clientSecret) { return uaaClient.clients().create(CreateClientRequest.builder().authorizedGrantType(PASSWORD) .clientId(clientId).clientSecret(clientSecret).build()); } private static Mono<GetMetadataResponse> requestGetMetadata(UaaClient uaaClient, String clientId) { return uaaClient.clients().getMetadata(GetMetadataRequest.builder().clientId(clientId).build()); } private static Flux<Client> requestListClients(UaaClient uaaClient) { return PaginationUtils.requestUaaResources(startIndex -> uaaClient.clients() .list(ListClientsRequest.builder().startIndex(startIndex).build())); } private static Mono<UpdateMetadataResponse> requestUpdateMetadata(UaaClient uaaClient, String clientId, String appLaunchUrl) { return uaaClient.clients().updateMetadata( UpdateMetadataRequest.builder().appLaunchUrl(appLaunchUrl).clientId(clientId).build()); } }