Skip to content

Commit 07a74e4

Browse files
authored
[Communication] - Identity - Added managed identity tests and updated README (Azure#18183)
* Added managed identity tests and updated README * Addressed comments * Addressed README comments
1 parent 6b2e9c6 commit 07a74e4

File tree

12 files changed

+672
-6
lines changed

12 files changed

+672
-6
lines changed

sdk/communication/azure-communication-administration/README.md

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,39 @@ Acquired phone numbers can come with many capabilities, depending on the country
2828

2929
## Key concepts
3030

31-
To use the Admnistration SDK, a resource access key is required for authentication.
31+
There are two forms of authentication to use the Administration SDK:
3232

33-
Administration uses HMAC authentication with the resource access key.
34-
The access key must be provided to the CommunicationIdentityClientBuilder
35-
or the PhoneNumberClientBuilder via the accessKey() function. Endpoint and httpClient must also be set
33+
### Azure Active Directory Token Authentication
34+
Currently, Azure Active Directory (AAD) authentication is only possible for CommunicationIdentityClient.
35+
The `DefaultAzureCredential` object must be passed to the `CommunicationIdentityClientBuilder` via
36+
the credential() funtion. Endpoint and httpClient must also be set
3637
via the endpoint() and httpClient() functions respectively.
3738

38-
### Initializing Identity Client
39+
`CLIENT_SECRET`, `CLIENT_ID` and `TENANT_ID` environment variables
40+
are needed to create a DefaultAzureCredential object.
41+
42+
<!-- embedme ./src/samples/java/com/azure/communication/administration/ReadmeSamples.java#L377-L389 -->
43+
```java
44+
String endpoint = "https://<RESOURCE_NAME>.communication.azure.com";
45+
46+
// Create an HttpClient builder of your choice and customize it
47+
HttpClient httpClient = new NettyAsyncHttpClientBuilder().build();
48+
49+
CommunicationIdentityClient communicationIdentityClient = new CommunicationIdentityClientBuilder()
50+
.endpoint(endpoint)
51+
.credential(new DefaultAzureCredentialBuilder().build())
52+
.httpClient(httpClient)
53+
.buildClient();
54+
55+
return communicationIdentityClient;
56+
}
57+
```
58+
59+
### Access Key Authentication
60+
Administration uses HMAC authentication with the resource access key.
61+
The access key must be provided to the `CommunicationIdentityClientBuilder`
62+
or the `PhoneNumberClientBuilder` via the accessKey() function. Endpoint and httpClient must also be set
63+
via the endpoint() and httpClient() functions respectively.
3964

4065
<!-- embedme ./src/samples/java/com/azure/communication/administration/ReadmeSamples.java#L37-L48 -->
4166
```java

sdk/communication/azure-communication-administration/src/samples/java/com/azure/communication/administration/ReadmeSamples.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import com.azure.core.http.netty.NettyAsyncHttpClientBuilder;
2626
import com.azure.core.http.rest.PagedIterable;
2727
import com.azure.core.util.polling.SyncPoller;
28-
28+
import com.azure.identity.DefaultAzureCredentialBuilder;
2929

3030
public class ReadmeSamples {
3131
/**
@@ -366,4 +366,25 @@ public void beginReleasePhoneNumbers() {
366366
PhoneNumberRelease result = res.getFinalResult();
367367
System.out.println("Phone number release status: " + result.getStatus());
368368
}
369+
370+
/**
371+
* Sample code for creating a sync Communication Identity Client using AAD authentication.
372+
*
373+
* @return the Communication Identity Client.
374+
*/
375+
public CommunicationIdentityClient createCommunicationIdentityClientWithAAD() {
376+
// You can find your endpoint and access key from your resource in the Azure Portal
377+
String endpoint = "https://<RESOURCE_NAME>.communication.azure.com";
378+
379+
// Create an HttpClient builder of your choice and customize it
380+
HttpClient httpClient = new NettyAsyncHttpClientBuilder().build();
381+
382+
CommunicationIdentityClient communicationIdentityClient = new CommunicationIdentityClientBuilder()
383+
.endpoint(endpoint)
384+
.credential(new DefaultAzureCredentialBuilder().build())
385+
.httpClient(httpClient)
386+
.buildClient();
387+
388+
return communicationIdentityClient;
389+
}
369390
}

sdk/communication/azure-communication-administration/src/test/java/com/azure/communication/administration/CommunicationIdentityAsyncTests.java

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,4 +319,158 @@ public void issueTokenWithResponseWithNullUser(HttpClient httpClient) {
319319
asyncClient.issueTokenWithResponse(null, scopes))
320320
.verifyError(NullPointerException.class);
321321
}
322+
323+
@ParameterizedTest
324+
@MethodSource("com.azure.core.test.TestBase#getHttpClients")
325+
public void createUserWithResponseUsingManagedIdentity(HttpClient httpClient) {
326+
// Arrange
327+
asyncClient = getCommunicationIdentityClientBuilderUsingManagedIdentity(httpClient).buildAsyncClient();
328+
329+
// Action & Assert
330+
Mono<Response<CommunicationUserIdentifier>> response = asyncClient.createUserWithResponse();
331+
StepVerifier.create(response)
332+
.assertNext(item -> {
333+
assertNotNull(item.getValue().getId());
334+
assertFalse(item.getValue().getId().isEmpty());
335+
assertEquals(200, item.getStatusCode(), "Expect status code to be 200");
336+
})
337+
.verifyComplete();
338+
}
339+
340+
@ParameterizedTest
341+
@MethodSource("com.azure.core.test.TestBase#getHttpClients")
342+
public void createUserWithContextUsingManagedIdentity(HttpClient httpClient) {
343+
// Arrange
344+
asyncClient = getCommunicationIdentityClientBuilderUsingManagedIdentity(httpClient).buildAsyncClient();
345+
346+
// Action & Assert
347+
Mono<Response<CommunicationUserIdentifier>> response = asyncClient.createUser(Context.NONE);
348+
StepVerifier.create(response)
349+
.assertNext(item -> {
350+
assertNotNull(item.getValue().getId());
351+
assertFalse(item.getValue().getId().isEmpty());
352+
assertEquals(200, item.getStatusCode(), "Expect status code to be 200");
353+
})
354+
.verifyComplete();
355+
}
356+
357+
@ParameterizedTest
358+
@MethodSource("com.azure.core.test.TestBase#getHttpClients")
359+
public void deleteUserUsingManagedIdentity(HttpClient httpClient) {
360+
// Arrange
361+
asyncClient = getCommunicationIdentityClientBuilderUsingManagedIdentity(httpClient).buildAsyncClient();
362+
363+
// Action & Assert
364+
StepVerifier.create(
365+
asyncClient.createUser()
366+
.flatMap(communicationUser -> {
367+
return asyncClient.deleteUser(communicationUser);
368+
}))
369+
.verifyComplete();
370+
}
371+
372+
@ParameterizedTest
373+
@MethodSource("com.azure.core.test.TestBase#getHttpClients")
374+
public void deleteUserWithResponseUsingManagedIdentity(HttpClient httpClient) {
375+
// Arrange
376+
asyncClient = getCommunicationIdentityClientBuilderUsingManagedIdentity(httpClient).buildAsyncClient();
377+
378+
// Action & Assert
379+
StepVerifier.create(
380+
asyncClient.createUser()
381+
.flatMap(communicationUser -> {
382+
return asyncClient.deleteUserWithResponse(communicationUser);
383+
}))
384+
.assertNext(item -> {
385+
assertEquals(204, item.getStatusCode(), "Expect status code to be 204");
386+
})
387+
.verifyComplete();
388+
}
389+
390+
@ParameterizedTest
391+
@MethodSource("com.azure.core.test.TestBase#getHttpClients")
392+
public void revokeTokenUsingManagedIdentity(HttpClient httpClient) {
393+
// Arrange
394+
asyncClient = getCommunicationIdentityClientBuilderUsingManagedIdentity(httpClient).buildAsyncClient();
395+
396+
// Action & Assert
397+
StepVerifier.create(
398+
asyncClient.createUser()
399+
.flatMap(communicationUser -> {
400+
List<String> scopes = new ArrayList<>(Arrays.asList("chat"));
401+
return asyncClient.issueToken(communicationUser, scopes)
402+
.flatMap(communicationUserToken -> {
403+
return asyncClient.revokeTokens(communicationUserToken.getUser(), null);
404+
});
405+
}))
406+
.verifyComplete();
407+
}
408+
409+
@ParameterizedTest
410+
@MethodSource("com.azure.core.test.TestBase#getHttpClients")
411+
public void revokeTokenWithResponseUsingManagedIdentity(HttpClient httpClient) {
412+
// Arrange
413+
asyncClient = getCommunicationIdentityClientBuilderUsingManagedIdentity(httpClient).buildAsyncClient();
414+
415+
// Action & Assert
416+
StepVerifier.create(
417+
asyncClient.createUser()
418+
.flatMap(communicationUser -> {
419+
List<String> scopes = new ArrayList<>(Arrays.asList("chat"));
420+
return asyncClient.issueToken(communicationUser, scopes)
421+
.flatMap(communicationUserToken -> {
422+
return asyncClient.revokeTokensWithResponse(communicationUserToken.getUser(), null);
423+
});
424+
}))
425+
.assertNext(item -> {
426+
assertEquals(204, item.getStatusCode(), "Expect status code to be 204");
427+
})
428+
.verifyComplete();
429+
}
430+
431+
@ParameterizedTest
432+
@MethodSource("com.azure.core.test.TestBase#getHttpClients")
433+
public void issueTokenUsingManagedIdentity(HttpClient httpClient) {
434+
// Arrange
435+
asyncClient = getCommunicationIdentityClientBuilderUsingManagedIdentity(httpClient).buildAsyncClient();
436+
437+
// Action & Assert
438+
StepVerifier.create(
439+
asyncClient.createUser()
440+
.flatMap(communicationUser -> {
441+
List<String> scopes = new ArrayList<>(Arrays.asList("chat"));
442+
return asyncClient.issueToken(communicationUser, scopes);
443+
}))
444+
.assertNext(issuedToken -> {
445+
assertNotNull(issuedToken.getToken());
446+
assertFalse(issuedToken.getToken().isEmpty());
447+
assertNotNull(issuedToken.getExpiresOn());
448+
assertFalse(issuedToken.getExpiresOn().toString().isEmpty());
449+
assertNotNull(issuedToken.getUser());
450+
})
451+
.verifyComplete();
452+
}
453+
454+
@ParameterizedTest
455+
@MethodSource("com.azure.core.test.TestBase#getHttpClients")
456+
public void issueTokenWithResponseUsingManagedIdentity(HttpClient httpClient) {
457+
// Arrange
458+
asyncClient = getCommunicationIdentityClientBuilderUsingManagedIdentity(httpClient).buildAsyncClient();
459+
460+
// Action & Assert
461+
StepVerifier.create(
462+
asyncClient.createUser()
463+
.flatMap(communicationUser -> {
464+
List<String> scopes = new ArrayList<>(Arrays.asList("chat"));
465+
return asyncClient.issueTokenWithResponse(communicationUser, scopes);
466+
}))
467+
.assertNext(issuedToken -> {
468+
assertNotNull(issuedToken.getValue().getToken());
469+
assertFalse(issuedToken.getValue().getToken().isEmpty());
470+
assertNotNull(issuedToken.getValue().getExpiresOn());
471+
assertFalse(issuedToken.getValue().getExpiresOn().toString().isEmpty());
472+
assertNotNull(issuedToken.getValue().getUser());
473+
})
474+
.verifyComplete();
475+
}
322476
}

sdk/communication/azure-communication-administration/src/test/java/com/azure/communication/administration/CommunicationIdentityTests.java

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,4 +168,108 @@ public void issueTokenWithResponse(HttpClient httpClient) {
168168
assertFalse(issuedToken.getExpiresOn().toString().isEmpty());
169169
assertNotNull(issuedToken.getUser());
170170
}
171+
172+
@ParameterizedTest
173+
@MethodSource("com.azure.core.test.TestBase#getHttpClients")
174+
public void createUserWithResponseUsingManagedIdentity(HttpClient httpClient) {
175+
// Arrange
176+
client = getCommunicationIdentityClientBuilderUsingManagedIdentity(httpClient).buildClient();
177+
178+
// Action & Assert
179+
Response<CommunicationUserIdentifier> response = client.createUserWithResponse(Context.NONE);
180+
assertNotNull(response.getValue().getId());
181+
assertFalse(response.getValue().getId().isEmpty());
182+
assertEquals(200, response.getStatusCode(), "Expect status code to be 200");
183+
}
184+
185+
@ParameterizedTest
186+
@MethodSource("com.azure.core.test.TestBase#getHttpClients")
187+
public void deleteUserUsingManagedIdentity(HttpClient httpClient) {
188+
// Arrange
189+
client = getCommunicationIdentityClientBuilderUsingManagedIdentity(httpClient).buildClient();
190+
191+
// Action & Assert
192+
CommunicationUserIdentifier communicationUser = client.createUser();
193+
assertNotNull(communicationUser.getId());
194+
client.deleteUser(communicationUser);
195+
}
196+
197+
@ParameterizedTest
198+
@MethodSource("com.azure.core.test.TestBase#getHttpClients")
199+
public void deleteUserWithResponseUsingManagedIdentity(HttpClient httpClient) {
200+
// Arrange
201+
client = getCommunicationIdentityClientBuilderUsingManagedIdentity(httpClient).buildClient();
202+
203+
// Action & Assert
204+
CommunicationUserIdentifier communicationUser = client.createUser();
205+
Response<Void> response = client.deleteUserWithResponse(communicationUser, Context.NONE);
206+
assertEquals(204, response.getStatusCode(), "Expect status code to be 204");
207+
}
208+
209+
@ParameterizedTest
210+
@MethodSource("com.azure.core.test.TestBase#getHttpClients")
211+
public void revokeTokenUsingManagedIdentity(HttpClient httpClient) {
212+
// Arrange
213+
client = getCommunicationIdentityClientBuilderUsingManagedIdentity(httpClient).buildClient();
214+
215+
// Action & Assert
216+
CommunicationUserIdentifier communicationUser = client.createUser();
217+
assertNotNull(communicationUser.getId());
218+
List<String> scopes = new ArrayList<>(Arrays.asList("chat"));
219+
CommunicationUserToken token = client.issueToken(communicationUser, scopes);
220+
client.revokeTokens(token.getUser(), null);
221+
}
222+
223+
@ParameterizedTest
224+
@MethodSource("com.azure.core.test.TestBase#getHttpClients")
225+
public void revokeTokenWithResponseUsingManagedIdentity(HttpClient httpClient) {
226+
// Arrange
227+
client = getCommunicationIdentityClientBuilderUsingManagedIdentity(httpClient).buildClient();
228+
229+
// Action & Assert
230+
CommunicationUserIdentifier communicationUser = client.createUser();
231+
assertNotNull(communicationUser.getId());
232+
List<String> scopes = new ArrayList<>(Arrays.asList("chat"));
233+
CommunicationUserToken token = client.issueToken(communicationUser, scopes);
234+
Response<Void> response = client.revokeTokensWithResponse(token.getUser(), null, Context.NONE);
235+
assertEquals(204, response.getStatusCode(), "Expect status code to be 204");
236+
}
237+
238+
@ParameterizedTest
239+
@MethodSource("com.azure.core.test.TestBase#getHttpClients")
240+
public void issueTokenUsingManagedIdentity(HttpClient httpClient) {
241+
// Arrange
242+
client = getCommunicationIdentityClientBuilderUsingManagedIdentity(httpClient).buildClient();
243+
244+
// Action & Assert
245+
CommunicationUserIdentifier communicationUser = client.createUser();
246+
assertNotNull(communicationUser.getId());
247+
List<String> scopes = new ArrayList<>(Arrays.asList("chat"));
248+
CommunicationUserToken issuedToken = client.issueToken(communicationUser, scopes);
249+
assertNotNull(issuedToken.getToken());
250+
assertFalse(issuedToken.getToken().isEmpty());
251+
assertNotNull(issuedToken.getExpiresOn());
252+
assertFalse(issuedToken.getExpiresOn().toString().isEmpty());
253+
assertNotNull(issuedToken.getUser());
254+
}
255+
256+
@ParameterizedTest
257+
@MethodSource("com.azure.core.test.TestBase#getHttpClients")
258+
public void issueTokenWithResponseUsingManagedIdentity(HttpClient httpClient) {
259+
// Arrange
260+
client = getCommunicationIdentityClientBuilderUsingManagedIdentity(httpClient).buildClient();
261+
262+
// Action & Assert
263+
CommunicationUserIdentifier communicationUser = client.createUser();
264+
assertNotNull(communicationUser.getId());
265+
List<String> scopes = new ArrayList<>(Arrays.asList("chat"));
266+
Response<CommunicationUserToken> issuedTokenResponse = client.issueTokenWithResponse(communicationUser, scopes, Context.NONE);
267+
CommunicationUserToken issuedToken = issuedTokenResponse.getValue();
268+
assertEquals(200, issuedTokenResponse.getStatusCode(), "Expect status code to be 200");
269+
assertNotNull(issuedToken.getToken());
270+
assertFalse(issuedToken.getToken().isEmpty());
271+
assertNotNull(issuedToken.getExpiresOn());
272+
assertFalse(issuedToken.getExpiresOn().toString().isEmpty());
273+
assertNotNull(issuedToken.getUser());
274+
}
171275
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"networkCallRecords" : [ {
3+
"Method" : "POST",
4+
"Uri" : "https://REDACTED.communication.azure.com/identities?api-version=2020-07-20-preview2",
5+
"Headers" : {
6+
"User-Agent" : "azsdk-java-azure-communication-administration/1.0.0-beta.4 (11.0.8; Windows 10; 10.0)"
7+
},
8+
"Response" : {
9+
"Transfer-Encoding" : "chunked",
10+
"Strict-Transport-Security" : "max-age=2592000",
11+
"api-supported-versions" : "2020-01-15-preview3, 2020-07-20-preview1, 2020-07-20-preview2",
12+
"X-Processing-Time" : "18ms",
13+
"MS-CV" : "sRzpzpovhkiJnp4Uqn6qvw.0",
14+
"retry-after" : "0",
15+
"X-Azure-Ref" : "0Q07aXwAAAABEbSTTVZVZSqvifv/5Hbv+TEFYRURHRTEyMDYAOWZjN2I1MTktYThjYy00Zjg5LTkzNWUtYzkxNDhhZTA5ZTgx",
16+
"StatusCode" : "200",
17+
"Body" : "{\"id\":\"REDACTED\"}",
18+
"Date" : "Wed, 16 Dec 2020 18:13:22 GMT",
19+
"x-ms-client-request-id" : "64b2feaf-19b0-4cde-9550-7107c0194fc2",
20+
"Content-Type" : "application/json; charset=utf-8"
21+
},
22+
"Exception" : null
23+
} ],
24+
"variables" : [ ]
25+
}

0 commit comments

Comments
 (0)