From 772e2ed006fa9f67cab4a48483986cfcdb197622 Mon Sep 17 00:00:00 2001 From: Jianghao Lu Date: Tue, 19 Nov 2019 15:12:58 -0800 Subject: [PATCH 01/15] Add HttpPipeline adapter for MSAL IHttpClient --- sdk/identity/azure-identity/pom.xml | 10 ++++ .../azure/identity/CredentialBuilderBase.java | 7 +++ .../implementation/HttpPipelineAdapter.java | 52 +++++++++++++++++++ .../implementation/IdentityClient.java | 13 +++-- .../implementation/IdentityClientOptions.java | 25 +++++++++ .../IdentityClientIntegrationTests.java | 11 ++-- .../implementation/IdentityClientTests.java | 16 +++--- .../msalextensions/CrossProgramVSTest.java | 2 +- .../MultithreadedTokenCacheTest.java | 4 +- .../PersistentTokenCacheAccessAspectTest.java | 4 +- .../com/azure/identity/util/TestUtils.java | 18 ++++++- 11 files changed, 139 insertions(+), 23 deletions(-) create mode 100644 sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/HttpPipelineAdapter.java diff --git a/sdk/identity/azure-identity/pom.xml b/sdk/identity/azure-identity/pom.xml index 7261bd618fb0..f995a02ed7c5 100644 --- a/sdk/identity/azure-identity/pom.xml +++ b/sdk/identity/azure-identity/pom.xml @@ -25,9 +25,15 @@ azure-core 1.1.0-beta.1 + + com.azure + azure-core-http-netty + 1.1.0-beta.1 + com.microsoft.azure msal4j + 1.0.0 com.nimbusds @@ -67,5 +73,9 @@ reactor-test test + + org.slf4j + slf4j-simple + diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/CredentialBuilderBase.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/CredentialBuilderBase.java index 11ec1cb80671..73981044407b 100644 --- a/sdk/identity/azure-identity/src/main/java/com/azure/identity/CredentialBuilderBase.java +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/CredentialBuilderBase.java @@ -3,6 +3,7 @@ package com.azure.identity; +import com.azure.core.http.HttpPipeline; import com.azure.core.http.ProxyOptions; import com.azure.identity.implementation.IdentityClientOptions; @@ -55,4 +56,10 @@ public T proxyOptions(ProxyOptions proxyOptions) { this.identityClientOptions.setProxyOptions(proxyOptions); return (T) this; } + + @SuppressWarnings("unchecked") + public T httpPipeline(HttpPipeline httpPipeline) { + this.identityClientOptions.setHttpPipeline(httpPipeline); + return (T) this; + } } diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/HttpPipelineAdapter.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/HttpPipelineAdapter.java new file mode 100644 index 000000000000..ca3c9cb41119 --- /dev/null +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/HttpPipelineAdapter.java @@ -0,0 +1,52 @@ +package com.azure.identity.implementation; + +import com.azure.core.http.HttpHeader; +import com.azure.core.http.HttpHeaders; +import com.azure.core.http.HttpMethod; +import com.azure.core.http.HttpPipeline; +import com.microsoft.aad.msal4j.HttpRequest; +import com.microsoft.aad.msal4j.IHttpClient; +import com.microsoft.aad.msal4j.IHttpResponse; +import reactor.core.publisher.Mono; + +import java.util.Collections; +import java.util.stream.Collectors; + +public class HttpPipelineAdapter implements IHttpClient { + private final HttpPipeline httpPipeline; + + public HttpPipelineAdapter(HttpPipeline httpPipeline) { + this.httpPipeline = httpPipeline; + } + + @Override + public IHttpResponse send(HttpRequest httpRequest) throws Exception { + // convert request + com.azure.core.http.HttpRequest request = new com.azure.core.http.HttpRequest( + HttpMethod.valueOf(httpRequest.httpMethod().name()), + httpRequest.url()); + if (httpRequest.headers() != null) { + request.setHeaders(new HttpHeaders(httpRequest.headers())); + } + if (httpRequest.body() != null) { + request.setBody(httpRequest.body()); + } + + return httpPipeline.send(request) + .flatMap(response -> response.getBodyAsString() + .map(body -> { + com.microsoft.aad.msal4j.HttpResponse httpResponse = new com.microsoft.aad.msal4j.HttpResponse() + .body(body) + .statusCode(response.getStatusCode()); + httpResponse.headers(response.getHeaders().stream().collect(Collectors.toMap(HttpHeader::getName,h -> Collections.singletonList(h.getValue())))); + return httpResponse; + }) + .switchIfEmpty(Mono.defer(() -> { + com.microsoft.aad.msal4j.HttpResponse httpResponse = new com.microsoft.aad.msal4j.HttpResponse() + .statusCode(response.getStatusCode()); + httpResponse.headers(response.getHeaders().stream().collect(Collectors.toMap(HttpHeader::getName,h -> Collections.singletonList(h.getValue())))); + return Mono.just(httpResponse); + }))) + .block(); + } +} diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClient.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClient.java index 33cad876b36b..6dfc8bc1724f 100644 --- a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClient.java +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClient.java @@ -87,6 +87,7 @@ public class IdentityClient { } else { String authorityUrl = options.getAuthorityHost().replaceAll("/+$", "") + "/organizations/" + tenantId; PublicClientApplication.Builder publicClientApplicationBuilder = PublicClientApplication.builder(clientId); + publicClientApplicationBuilder = publicClientApplicationBuilder.httpClient(new HttpPipelineAdapter(options.getHttpPipeline())); try { publicClientApplicationBuilder = publicClientApplicationBuilder.authority(authorityUrl); } catch (MalformedURLException e) { @@ -110,7 +111,8 @@ public Mono authenticateWithClientSecret(String clientSecret, Token String authorityUrl = options.getAuthorityHost().replaceAll("/+$", "") + "/" + tenantId; try { ConfidentialClientApplication.Builder applicationBuilder = - ConfidentialClientApplication.builder(clientId, ClientCredentialFactory.create(clientSecret)) + ConfidentialClientApplication.builder(clientId, ClientCredentialFactory.createFromSecret(clientSecret)) + .httpClient(new HttpPipelineAdapter(options.getHttpPipeline())) .authority(authorityUrl); if (options.getProxyOptions() != null) { applicationBuilder.proxy(proxyOptionsToJavaNetProxy(options.getProxyOptions())); @@ -140,7 +142,8 @@ public Mono authenticateWithPfxCertificate(String pfxCertificatePat try { ConfidentialClientApplication.Builder applicationBuilder = ConfidentialClientApplication.builder(clientId, - ClientCredentialFactory.create(new FileInputStream(pfxCertificatePath), pfxCertificatePassword)) + ClientCredentialFactory.createFromCertificate(new FileInputStream(pfxCertificatePath), pfxCertificatePassword)) + .httpClient(new HttpPipelineAdapter(options.getHttpPipeline())) .authority(authorityUrl); if (options.getProxyOptions() != null) { applicationBuilder.proxy(proxyOptionsToJavaNetProxy(options.getProxyOptions())); @@ -174,8 +177,10 @@ public Mono authenticateWithPemCertificate(String pemCertificatePat byte[] pemCertificateBytes = Files.readAllBytes(Paths.get(pemCertificatePath)); ConfidentialClientApplication.Builder applicationBuilder = ConfidentialClientApplication.builder(clientId, - ClientCredentialFactory.create(CertificateUtil.privateKeyFromPem(pemCertificateBytes), - CertificateUtil.publicKeyFromPem(pemCertificateBytes))).authority(authorityUrl); + ClientCredentialFactory.createFromCertificate(CertificateUtil.privateKeyFromPem(pemCertificateBytes), + CertificateUtil.publicKeyFromPem(pemCertificateBytes))) + .httpClient(new HttpPipelineAdapter(options.getHttpPipeline())) + .authority(authorityUrl); if (options.getProxyOptions() != null) { applicationBuilder.proxy(proxyOptionsToJavaNetProxy(options.getProxyOptions())); } diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClientOptions.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClientOptions.java index 4fb5c1372ab1..917267050f1c 100644 --- a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClientOptions.java +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClientOptions.java @@ -3,8 +3,18 @@ package com.azure.identity.implementation; +import com.azure.core.http.HttpPipeline; +import com.azure.core.http.HttpPipelineBuilder; import com.azure.core.http.ProxyOptions; +import com.azure.core.http.netty.NettyAsyncHttpClientBuilder; +import com.azure.core.http.policy.CookiePolicy; +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.http.policy.HttpLogOptions; +import com.azure.core.http.policy.HttpLoggingPolicy; +import com.azure.core.http.policy.RetryPolicy; +import com.azure.core.http.policy.UserAgentPolicy; +import java.net.InetSocketAddress; import java.time.Duration; import java.util.function.Function; @@ -19,6 +29,7 @@ public final class IdentityClientOptions { private int maxRetry; private Function retryTimeout; private ProxyOptions proxyOptions; + private HttpPipeline httpPipeline; /** * Creates an instance of IdentityClientOptions with default settings. @@ -27,6 +38,12 @@ public IdentityClientOptions() { authorityHost = DEFAULT_AUTHORITY_HOST; maxRetry = MAX_RETRY_DEFAULT_LIMIT; retryTimeout = i -> Duration.ofSeconds((long) Math.pow(2, i.getSeconds() - 1)); + httpPipeline = new HttpPipelineBuilder() + .httpClient(new NettyAsyncHttpClientBuilder().proxy(new ProxyOptions(ProxyOptions.Type.HTTP, new InetSocketAddress("10.127.70.25", 8888))).build()) + .policies( + new UserAgentPolicy(), + new RetryPolicy(), + new CookiePolicy(), new HttpLoggingPolicy(new HttpLogOptions().setLogLevel(HttpLogDetailLevel.BODY_AND_HEADERS))).build(); } /** @@ -96,4 +113,12 @@ public IdentityClientOptions setProxyOptions(ProxyOptions proxyOptions) { this.proxyOptions = proxyOptions; return this; } + + public HttpPipeline getHttpPipeline() { + return httpPipeline; + } + + public void setHttpPipeline(HttpPipeline httpPipeline) { + this.httpPipeline = httpPipeline; + } } diff --git a/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/IdentityClientIntegrationTests.java b/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/IdentityClientIntegrationTests.java index 47d208bd6d23..156ce358e9b2 100644 --- a/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/IdentityClientIntegrationTests.java +++ b/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/IdentityClientIntegrationTests.java @@ -8,6 +8,7 @@ import com.azure.core.http.ProxyOptions.Type; import org.junit.Assert; import org.junit.Ignore; +import org.junit.Test; import reactor.test.StepVerifier; import java.net.InetSocketAddress; @@ -21,9 +22,9 @@ public class IdentityClientIntegrationTests { private static final String AZURE_CLIENT_CERTIFICATE = "AZURE_CLIENT_CERTIFICATE"; private final TokenRequestContext request = new TokenRequestContext().addScopes("https://management.azure.com/.default"); - @Ignore("Integration test") + @Test public void clientSecretCanGetToken() { - IdentityClient client = new IdentityClient(System.getenv(AZURE_TENANT_ID), System.getenv(AZURE_CLIENT_ID), new IdentityClientOptions().setProxyOptions(new ProxyOptions(Type.HTTP, new InetSocketAddress("localhost", 8888)))); + IdentityClient client = new IdentityClient(System.getenv(AZURE_TENANT_ID), System.getenv(AZURE_CLIENT_ID), new IdentityClientOptions()); StepVerifier.create(client.authenticateWithClientSecret(System.getenv(AZURE_CLIENT_SECRET), request)) .expectNextMatches(token -> token.getToken() != null && token.getExpiresAt() != null @@ -36,7 +37,7 @@ public void clientSecretCanGetToken() { .verifyComplete(); } - @Ignore("Integration tests") + @Test public void deviceCodeCanGetToken() { IdentityClient client = new IdentityClient("common", System.getenv(AZURE_CLIENT_ID), new IdentityClientOptions().setProxyOptions(new ProxyOptions(Type.HTTP, new InetSocketAddress("localhost", 8888)))); MsalToken token = client.authenticateWithDeviceCode(request, deviceCode -> { @@ -58,9 +59,9 @@ public void deviceCodeCanGetToken() { Assert.assertFalse(token.isExpired()); } - @Ignore("Integration tests") + @Test public void browserCanGetToken() { - IdentityClient client = new IdentityClient("common", System.getenv(AZURE_CLIENT_ID), new IdentityClientOptions().setProxyOptions(new ProxyOptions(Type.HTTP, new InetSocketAddress("localhost", 8888)))); + IdentityClient client = new IdentityClient("common", System.getenv(AZURE_CLIENT_ID), new IdentityClientOptions()); MsalToken token = client.authenticateWithBrowserInteraction(request, 8765).block(); Assert.assertNotNull(token); Assert.assertNotNull(token.getToken()); diff --git a/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/IdentityClientTests.java b/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/IdentityClientTests.java index 9544bef34c8c..a3d22e4545ca 100644 --- a/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/IdentityClientTests.java +++ b/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/IdentityClientTests.java @@ -6,11 +6,10 @@ import com.azure.core.credential.AccessToken; import com.azure.core.credential.TokenRequestContext; import com.azure.identity.util.TestUtils; -import com.microsoft.aad.msal4j.AsymmetricKeyCredential; import com.microsoft.aad.msal4j.ClientCredentialParameters; -import com.microsoft.aad.msal4j.ClientSecret; import com.microsoft.aad.msal4j.ConfidentialClientApplication; import com.microsoft.aad.msal4j.DeviceCodeFlowParameters; +import com.microsoft.aad.msal4j.IClientSecret; import com.microsoft.aad.msal4j.MsalServiceException; import com.microsoft.aad.msal4j.PublicClientApplication; import org.junit.Assert; @@ -154,9 +153,10 @@ private void mockForClientSecret(String secret, TokenRequestContext request, Str ConfidentialClientApplication.Builder builder = PowerMockito.mock(ConfidentialClientApplication.Builder.class); when(builder.build()).thenReturn(application); when(builder.authority(any())).thenReturn(builder); + when(builder.httpClient(any())).thenReturn(builder); whenNew(ConfidentialClientApplication.Builder.class).withAnyArguments().thenAnswer(invocation -> { String cid = (String) invocation.getArguments()[0]; - ClientSecret clientSecret = (ClientSecret) invocation.getArguments()[1]; + IClientSecret clientSecret = (IClientSecret) invocation.getArguments()[1]; if (!clientId.equals(cid)) { throw new MsalServiceException("Invalid clientId", "InvalidClientId"); } @@ -182,15 +182,16 @@ private void mockForClientCertificate(TokenRequestContext request, String access ConfidentialClientApplication.Builder builder = PowerMockito.mock(ConfidentialClientApplication.Builder.class); when(builder.build()).thenReturn(application); when(builder.authority(any())).thenReturn(builder); + when(builder.httpClient(any())).thenReturn(builder); whenNew(ConfidentialClientApplication.Builder.class).withAnyArguments().thenAnswer(invocation -> { String cid = (String) invocation.getArguments()[0]; - AsymmetricKeyCredential keyCredential = (AsymmetricKeyCredential) invocation.getArguments()[1]; +// AsymmetricKeyCredential keyCredential = (AsymmetricKeyCredential) invocation.getArguments()[1]; if (!clientId.equals(cid)) { throw new MsalServiceException("Invalid clientId", "InvalidClientId"); } - if (keyCredential == null || keyCredential.key() == null) { - throw new MsalServiceException("Invalid clientCertificate", "InvalidClientCertificate"); - } +// if (keyCredential == null || keyCredential.key() == null) { +// throw new MsalServiceException("Invalid clientCertificate", "InvalidClientCertificate"); +// } return builder; }); } @@ -216,6 +217,7 @@ private void mockForDeviceCodeFlow(TokenRequestContext request, String accessTok PublicClientApplication.Builder builder = PowerMockito.mock(PublicClientApplication.Builder.class); when(builder.build()).thenReturn(application); when(builder.authority(any())).thenReturn(builder); + when(builder.httpClient(any())).thenReturn(builder); whenNew(PublicClientApplication.Builder.class).withArguments(clientId).thenReturn(builder); } } diff --git a/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/msalextensions/CrossProgramVSTest.java b/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/msalextensions/CrossProgramVSTest.java index 2af976acc872..5ff72cc81908 100644 --- a/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/msalextensions/CrossProgramVSTest.java +++ b/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/msalextensions/CrossProgramVSTest.java @@ -44,7 +44,7 @@ public void setup() throws Exception { accessAspect = new PersistentTokenCacheAccessAspect(); confApp = ConfidentialClientApplication.builder(TestConfiguration.CONFIDENTIAL_CLIENT_ID, - ClientCredentialFactory.create(TestConfiguration.CONFIDENTIAL_CLIENT_SECRET)) + ClientCredentialFactory.createFromSecret(TestConfiguration.CONFIDENTIAL_CLIENT_SECRET)) .authority(TestConfiguration.TENANT_SPECIFIC_AUTHORITY) .setTokenCacheAccessAspect(accessAspect) .build(); diff --git a/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/msalextensions/MultithreadedTokenCacheTest.java b/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/msalextensions/MultithreadedTokenCacheTest.java index 9d347ae8edaf..667b295314ed 100644 --- a/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/msalextensions/MultithreadedTokenCacheTest.java +++ b/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/msalextensions/MultithreadedTokenCacheTest.java @@ -38,13 +38,13 @@ public void setup() throws Exception { accessAspect = new PersistentTokenCacheAccessAspect(cachePersister); confApp = ConfidentialClientApplication.builder(TestConfiguration.CONFIDENTIAL_CLIENT_ID, - ClientCredentialFactory.create(TestConfiguration.CONFIDENTIAL_CLIENT_SECRET)) + ClientCredentialFactory.createFromSecret(TestConfiguration.CONFIDENTIAL_CLIENT_SECRET)) .authority(TestConfiguration.TENANT_SPECIFIC_AUTHORITY) .setTokenCacheAccessAspect(accessAspect) .build(); confApp2 = ConfidentialClientApplication.builder(TestConfiguration.CONFIDENTIAL_CLIENT_ID_2, - ClientCredentialFactory.create(TestConfiguration.CONFIDENTIAL_CLIENT_SECRET_2)) + ClientCredentialFactory.createFromSecret(TestConfiguration.CONFIDENTIAL_CLIENT_SECRET_2)) .authority(TestConfiguration.TENANT_SPECIFIC_AUTHORITY) .setTokenCacheAccessAspect(accessAspect) .build(); diff --git a/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/msalextensions/PersistentTokenCacheAccessAspectTest.java b/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/msalextensions/PersistentTokenCacheAccessAspectTest.java index 2b78b6daae7b..b9afcbaaed4f 100644 --- a/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/msalextensions/PersistentTokenCacheAccessAspectTest.java +++ b/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/msalextensions/PersistentTokenCacheAccessAspectTest.java @@ -42,13 +42,13 @@ public void setup() throws Exception { }; confApp = ConfidentialClientApplication.builder(TestConfiguration.CONFIDENTIAL_CLIENT_ID, - ClientCredentialFactory.create(TestConfiguration.CONFIDENTIAL_CLIENT_SECRET)) + ClientCredentialFactory.createFromSecret(TestConfiguration.CONFIDENTIAL_CLIENT_SECRET)) .authority(TestConfiguration.TENANT_SPECIFIC_AUTHORITY) .setTokenCacheAccessAspect(accessAspect) .build(); confApp2 = ConfidentialClientApplication.builder(TestConfiguration.CONFIDENTIAL_CLIENT_ID_2, - ClientCredentialFactory.create(TestConfiguration.CONFIDENTIAL_CLIENT_SECRET_2)) + ClientCredentialFactory.createFromSecret(TestConfiguration.CONFIDENTIAL_CLIENT_SECRET_2)) .authority(TestConfiguration.TENANT_SPECIFIC_AUTHORITY) .setTokenCacheAccessAspect(accessAspect) .build(); diff --git a/sdk/identity/azure-identity/src/test/java/com/azure/identity/util/TestUtils.java b/sdk/identity/azure-identity/src/test/java/com/azure/identity/util/TestUtils.java index fdd42968b9a7..78545f83ab39 100644 --- a/sdk/identity/azure-identity/src/test/java/com/azure/identity/util/TestUtils.java +++ b/sdk/identity/azure-identity/src/test/java/com/azure/identity/util/TestUtils.java @@ -5,7 +5,6 @@ import com.azure.core.credential.AccessToken; import com.azure.identity.implementation.MsalToken; -import com.microsoft.aad.msal4j.Account; import com.microsoft.aad.msal4j.IAccount; import com.microsoft.aad.msal4j.IAuthenticationResult; import reactor.core.publisher.Mono; @@ -39,7 +38,22 @@ public String idToken() { @Override public IAccount account() { - return new Account(UUID.randomUUID().toString(), "http://login.microsoftonline.com", "testuser"); + return new IAccount() { + @Override + public String homeAccountId() { + return UUID.randomUUID().toString(); + } + + @Override + public String environment() { + return "http://login.microsoftonline.com"; + } + + @Override + public String username() { + return "testuser"; + } + }; } @Override From 63c16f706438cf75c18b30f5e1268afff056609d Mon Sep 17 00:00:00 2001 From: Jianghao Lu Date: Fri, 3 Jan 2020 11:51:43 -0800 Subject: [PATCH 02/15] Build backward compatible identity client options --- .../implementation/HttpPipelineAdapter.java | 1 + .../implementation/IdentityClientOptions.java | 29 ++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/HttpPipelineAdapter.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/HttpPipelineAdapter.java index ca3c9cb41119..8a2a0517f4b9 100644 --- a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/HttpPipelineAdapter.java +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/HttpPipelineAdapter.java @@ -41,6 +41,7 @@ public IHttpResponse send(HttpRequest httpRequest) throws Exception { httpResponse.headers(response.getHeaders().stream().collect(Collectors.toMap(HttpHeader::getName,h -> Collections.singletonList(h.getValue())))); return httpResponse; }) + // if no body .switchIfEmpty(Mono.defer(() -> { com.microsoft.aad.msal4j.HttpResponse httpResponse = new com.microsoft.aad.msal4j.HttpResponse() .statusCode(response.getStatusCode()); diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClientOptions.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClientOptions.java index 917267050f1c..26776952f7d6 100644 --- a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClientOptions.java +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClientOptions.java @@ -11,11 +11,15 @@ import com.azure.core.http.policy.HttpLogDetailLevel; import com.azure.core.http.policy.HttpLogOptions; import com.azure.core.http.policy.HttpLoggingPolicy; +import com.azure.core.http.policy.HttpPipelinePolicy; import com.azure.core.http.policy.RetryPolicy; +import com.azure.core.http.policy.RetryStrategy; import com.azure.core.http.policy.UserAgentPolicy; import java.net.InetSocketAddress; import java.time.Duration; +import java.util.ArrayList; +import java.util.List; import java.util.function.Function; /** @@ -115,7 +119,30 @@ public IdentityClientOptions setProxyOptions(ProxyOptions proxyOptions) { } public HttpPipeline getHttpPipeline() { - return httpPipeline; + if (httpPipeline != null) { + return httpPipeline; + } else { + NettyAsyncHttpClientBuilder httpClientBuilder = new NettyAsyncHttpClientBuilder(); + if (proxyOptions != null) { + httpClientBuilder = httpClientBuilder.proxy(proxyOptions); + } + HttpPipelineBuilder pipelineBuilder = new HttpPipelineBuilder() + .httpClient(httpClientBuilder.build()); + List policies = new ArrayList<>(); + policies.add(new UserAgentPolicy()); + policies.add(new RetryPolicy(new RetryStrategy() { + @Override + public int getMaxRetries() { + return maxRetry; + } + + @Override + public Duration calculateRetryDelay(int i) { + return retryTimeout.apply(Duration.ofSeconds(i)); + } + })); + return pipelineBuilder.policies(policies.toArray(new HttpPipelinePolicy[0])).build(); + } } public void setHttpPipeline(HttpPipeline httpPipeline) { From 9c01dbad21231ed7df11313b4b189d95cd023f23 Mon Sep 17 00:00:00 2001 From: Jianghao Lu Date: Fri, 3 Jan 2020 17:17:34 -0800 Subject: [PATCH 03/15] Fix code styles --- .../implementation/HttpPipelineAdapter.java | 7 ++- .../implementation/IdentityClient.java | 47 +++++++------------ 2 files changed, 22 insertions(+), 32 deletions(-) diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/HttpPipelineAdapter.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/HttpPipelineAdapter.java index 8a2a0517f4b9..523ac3e7adab 100644 --- a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/HttpPipelineAdapter.java +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/HttpPipelineAdapter.java @@ -12,10 +12,13 @@ import java.util.Collections; import java.util.stream.Collectors; -public class HttpPipelineAdapter implements IHttpClient { +/** + * Adapts an HttpPipeline to an instance of IHttpClient in the MSAL4j pipeline. + */ +class HttpPipelineAdapter implements IHttpClient { private final HttpPipeline httpPipeline; - public HttpPipelineAdapter(HttpPipeline httpPipeline) { + HttpPipelineAdapter(HttpPipeline httpPipeline) { this.httpPipeline = httpPipeline; } diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClient.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClient.java index 6dfc8bc1724f..2dae639442d8 100644 --- a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClient.java +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClient.java @@ -6,10 +6,10 @@ import com.azure.core.credential.AccessToken; import com.azure.core.credential.TokenRequestContext; import com.azure.core.http.ProxyOptions; +import com.azure.core.util.logging.ClientLogger; +import com.azure.core.util.serializer.JacksonAdapter; import com.azure.core.util.serializer.SerializerAdapter; import com.azure.core.util.serializer.SerializerEncoding; -import com.azure.core.util.serializer.JacksonAdapter; -import com.azure.core.util.logging.ClientLogger; import com.azure.identity.DeviceCodeInfo; import com.azure.identity.implementation.util.CertificateUtil; import com.microsoft.aad.msal4j.AuthorizationCodeParameters; @@ -37,11 +37,6 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.UnrecoverableKeyException; -import java.security.cert.CertificateException; import java.time.Duration; import java.time.OffsetDateTime; import java.time.ZoneOffset; @@ -87,7 +82,8 @@ public class IdentityClient { } else { String authorityUrl = options.getAuthorityHost().replaceAll("/+$", "") + "/organizations/" + tenantId; PublicClientApplication.Builder publicClientApplicationBuilder = PublicClientApplication.builder(clientId); - publicClientApplicationBuilder = publicClientApplicationBuilder.httpClient(new HttpPipelineAdapter(options.getHttpPipeline())); + publicClientApplicationBuilder = publicClientApplicationBuilder + .httpClient(new HttpPipelineAdapter(options.getHttpPipeline())); try { publicClientApplicationBuilder = publicClientApplicationBuilder.authority(authorityUrl); } catch (MalformedURLException e) { @@ -139,29 +135,20 @@ public Mono authenticateWithClientSecret(String clientSecret, Token public Mono authenticateWithPfxCertificate(String pfxCertificatePath, String pfxCertificatePassword, TokenRequestContext request) { String authorityUrl = options.getAuthorityHost().replaceAll("/+$", "") + "/" + tenantId; - try { + return Mono.fromCallable(() -> { ConfidentialClientApplication.Builder applicationBuilder = - ConfidentialClientApplication.builder(clientId, - ClientCredentialFactory.createFromCertificate(new FileInputStream(pfxCertificatePath), pfxCertificatePassword)) - .httpClient(new HttpPipelineAdapter(options.getHttpPipeline())) - .authority(authorityUrl); + ConfidentialClientApplication.builder(clientId, ClientCredentialFactory.createFromCertificate( + new FileInputStream(pfxCertificatePath), pfxCertificatePassword)) + .httpClient(new HttpPipelineAdapter(options.getHttpPipeline())) + .authority(authorityUrl); if (options.getProxyOptions() != null) { applicationBuilder.proxy(proxyOptionsToJavaNetProxy(options.getProxyOptions())); } - ConfidentialClientApplication application = applicationBuilder.build(); - return Mono.fromFuture(application.acquireToken( - ClientCredentialParameters.builder(new HashSet<>(request.getScopes())) - .build())) - .map(ar -> new AccessToken(ar.accessToken(), OffsetDateTime.ofInstant(ar.expiresOnDate().toInstant(), - ZoneOffset.UTC))); - } catch (CertificateException - | UnrecoverableKeyException - | NoSuchAlgorithmException - | KeyStoreException - | NoSuchProviderException - | IOException e) { - return Mono.error(e); - } + return applicationBuilder.build(); + }).flatMap(application -> Mono.fromFuture(application.acquireToken( + ClientCredentialParameters.builder(new HashSet<>(request.getScopes())).build()))) + .map(ar -> new AccessToken(ar.accessToken(), OffsetDateTime.ofInstant(ar.expiresOnDate().toInstant(), + ZoneOffset.UTC))); } /** @@ -176,9 +163,9 @@ public Mono authenticateWithPemCertificate(String pemCertificatePat try { byte[] pemCertificateBytes = Files.readAllBytes(Paths.get(pemCertificatePath)); ConfidentialClientApplication.Builder applicationBuilder = - ConfidentialClientApplication.builder(clientId, - ClientCredentialFactory.createFromCertificate(CertificateUtil.privateKeyFromPem(pemCertificateBytes), - CertificateUtil.publicKeyFromPem(pemCertificateBytes))) + ConfidentialClientApplication.builder(clientId, ClientCredentialFactory.createFromCertificate( + CertificateUtil.privateKeyFromPem(pemCertificateBytes), + CertificateUtil.publicKeyFromPem(pemCertificateBytes))) .httpClient(new HttpPipelineAdapter(options.getHttpPipeline())) .authority(authorityUrl); if (options.getProxyOptions() != null) { From 1cd4675b1774570b73364a34cc6ff31054f2ca9a Mon Sep 17 00:00:00 2001 From: Jianghao Lu Date: Fri, 3 Jan 2020 17:21:17 -0800 Subject: [PATCH 04/15] Clean up pom --- sdk/identity/azure-identity/pom.xml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sdk/identity/azure-identity/pom.xml b/sdk/identity/azure-identity/pom.xml index 3b3b9b2a02e5..aedb8074a80b 100644 --- a/sdk/identity/azure-identity/pom.xml +++ b/sdk/identity/azure-identity/pom.xml @@ -38,7 +38,7 @@ com.microsoft.azure msal4j - 1.1.0 + 1.1.0 com.nimbusds @@ -86,9 +86,5 @@ 3.3.0.RELEASE test - - org.slf4j - slf4j-simple - From 06c5f5631070bba8090a37fb052ff45ebddeb37d Mon Sep 17 00:00:00 2001 From: Jianghao Lu Date: Fri, 3 Jan 2020 17:38:34 -0800 Subject: [PATCH 05/15] Fix netty module version --- sdk/identity/azure-identity/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/identity/azure-identity/pom.xml b/sdk/identity/azure-identity/pom.xml index aedb8074a80b..2ce8961dd385 100644 --- a/sdk/identity/azure-identity/pom.xml +++ b/sdk/identity/azure-identity/pom.xml @@ -33,7 +33,7 @@ com.azure azure-core-http-netty - 1.1.0-beta.1 + 1.1.0 com.microsoft.azure From 0bc580fd051b37ea129d108003f2114b8d07fae9 Mon Sep 17 00:00:00 2001 From: Jianghao Lu Date: Fri, 3 Jan 2020 18:32:00 -0800 Subject: [PATCH 06/15] Use default when HttpPipeline is not specified --- sdk/identity/azure-identity/pom.xml | 11 ++-- .../implementation/IdentityClient.java | 16 ++++- .../implementation/IdentityClientOptions.java | 59 ++++--------------- .../IdentityClientIntegrationTests.java | 8 +-- 4 files changed, 36 insertions(+), 58 deletions(-) diff --git a/sdk/identity/azure-identity/pom.xml b/sdk/identity/azure-identity/pom.xml index 2ce8961dd385..a6bb9ae9ed43 100644 --- a/sdk/identity/azure-identity/pom.xml +++ b/sdk/identity/azure-identity/pom.xml @@ -30,11 +30,6 @@ slf4j-api 1.7.28 - - com.azure - azure-core-http-netty - 1.1.0 - com.microsoft.azure msal4j @@ -86,5 +81,11 @@ 3.3.0.RELEASE test + + com.azure + azure-core-http-netty + 1.1.0 + test + diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClient.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClient.java index 2dae639442d8..cbb9c20fa20c 100644 --- a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClient.java +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClient.java @@ -82,8 +82,10 @@ public class IdentityClient { } else { String authorityUrl = options.getAuthorityHost().replaceAll("/+$", "") + "/organizations/" + tenantId; PublicClientApplication.Builder publicClientApplicationBuilder = PublicClientApplication.builder(clientId); - publicClientApplicationBuilder = publicClientApplicationBuilder - .httpClient(new HttpPipelineAdapter(options.getHttpPipeline())); + if (options.getHttpPipeline() != null) { + publicClientApplicationBuilder = publicClientApplicationBuilder + .httpClient(new HttpPipelineAdapter(options.getHttpPipeline())); + } try { publicClientApplicationBuilder = publicClientApplicationBuilder.authority(authorityUrl); } catch (MalformedURLException e) { @@ -108,11 +110,13 @@ public Mono authenticateWithClientSecret(String clientSecret, Token try { ConfidentialClientApplication.Builder applicationBuilder = ConfidentialClientApplication.builder(clientId, ClientCredentialFactory.createFromSecret(clientSecret)) - .httpClient(new HttpPipelineAdapter(options.getHttpPipeline())) .authority(authorityUrl); if (options.getProxyOptions() != null) { applicationBuilder.proxy(proxyOptionsToJavaNetProxy(options.getProxyOptions())); } + if (options.getHttpPipeline() != null) { + applicationBuilder.httpClient(new HttpPipelineAdapter(options.getHttpPipeline())); + } ConfidentialClientApplication application = applicationBuilder.build(); return Mono.fromFuture(application.acquireToken( ClientCredentialParameters.builder(new HashSet<>(request.getScopes())) @@ -144,6 +148,9 @@ public Mono authenticateWithPfxCertificate(String pfxCertificatePat if (options.getProxyOptions() != null) { applicationBuilder.proxy(proxyOptionsToJavaNetProxy(options.getProxyOptions())); } + if (options.getHttpPipeline() != null) { + applicationBuilder.httpClient(new HttpPipelineAdapter(options.getHttpPipeline())); + } return applicationBuilder.build(); }).flatMap(application -> Mono.fromFuture(application.acquireToken( ClientCredentialParameters.builder(new HashSet<>(request.getScopes())).build()))) @@ -171,6 +178,9 @@ public Mono authenticateWithPemCertificate(String pemCertificatePat if (options.getProxyOptions() != null) { applicationBuilder.proxy(proxyOptionsToJavaNetProxy(options.getProxyOptions())); } + if (options.getHttpPipeline() != null) { + applicationBuilder.httpClient(new HttpPipelineAdapter(options.getHttpPipeline())); + } ConfidentialClientApplication application = applicationBuilder.build(); return Mono.fromFuture(application.acquireToken( ClientCredentialParameters.builder(new HashSet<>(request.getScopes())) diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClientOptions.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClientOptions.java index 26776952f7d6..fb8db6f635eb 100644 --- a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClientOptions.java +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClientOptions.java @@ -4,22 +4,9 @@ package com.azure.identity.implementation; import com.azure.core.http.HttpPipeline; -import com.azure.core.http.HttpPipelineBuilder; import com.azure.core.http.ProxyOptions; -import com.azure.core.http.netty.NettyAsyncHttpClientBuilder; -import com.azure.core.http.policy.CookiePolicy; -import com.azure.core.http.policy.HttpLogDetailLevel; -import com.azure.core.http.policy.HttpLogOptions; -import com.azure.core.http.policy.HttpLoggingPolicy; -import com.azure.core.http.policy.HttpPipelinePolicy; -import com.azure.core.http.policy.RetryPolicy; -import com.azure.core.http.policy.RetryStrategy; -import com.azure.core.http.policy.UserAgentPolicy; - -import java.net.InetSocketAddress; + import java.time.Duration; -import java.util.ArrayList; -import java.util.List; import java.util.function.Function; /** @@ -42,12 +29,6 @@ public IdentityClientOptions() { authorityHost = DEFAULT_AUTHORITY_HOST; maxRetry = MAX_RETRY_DEFAULT_LIMIT; retryTimeout = i -> Duration.ofSeconds((long) Math.pow(2, i.getSeconds() - 1)); - httpPipeline = new HttpPipelineBuilder() - .httpClient(new NettyAsyncHttpClientBuilder().proxy(new ProxyOptions(ProxyOptions.Type.HTTP, new InetSocketAddress("10.127.70.25", 8888))).build()) - .policies( - new UserAgentPolicy(), - new RetryPolicy(), - new CookiePolicy(), new HttpLoggingPolicy(new HttpLogOptions().setLogLevel(HttpLogDetailLevel.BODY_AND_HEADERS))).build(); } /** @@ -109,7 +90,7 @@ public ProxyOptions getProxyOptions() { } /** - * Specifies he options for proxy configuration. + * Specifies the options for proxy configuration. * @param proxyOptions the options for proxy configuration * @return IdentityClientOptions */ @@ -118,34 +99,20 @@ public IdentityClientOptions setProxyOptions(ProxyOptions proxyOptions) { return this; } + /** + * @return the HttpPipeline to send all requests + */ public HttpPipeline getHttpPipeline() { - if (httpPipeline != null) { - return httpPipeline; - } else { - NettyAsyncHttpClientBuilder httpClientBuilder = new NettyAsyncHttpClientBuilder(); - if (proxyOptions != null) { - httpClientBuilder = httpClientBuilder.proxy(proxyOptions); - } - HttpPipelineBuilder pipelineBuilder = new HttpPipelineBuilder() - .httpClient(httpClientBuilder.build()); - List policies = new ArrayList<>(); - policies.add(new UserAgentPolicy()); - policies.add(new RetryPolicy(new RetryStrategy() { - @Override - public int getMaxRetries() { - return maxRetry; - } - - @Override - public Duration calculateRetryDelay(int i) { - return retryTimeout.apply(Duration.ofSeconds(i)); - } - })); - return pipelineBuilder.policies(policies.toArray(new HttpPipelinePolicy[0])).build(); - } + return httpPipeline; } - public void setHttpPipeline(HttpPipeline httpPipeline) { + /** + * Specifies the HttpPipeline to send all requests. This setting overrides the others. + * @param httpPipeline the HttpPipeline to send all requests + * @return IdentityClientOptions + */ + public IdentityClientOptions setHttpPipeline(HttpPipeline httpPipeline) { this.httpPipeline = httpPipeline; + return this; } } diff --git a/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/IdentityClientIntegrationTests.java b/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/IdentityClientIntegrationTests.java index 156ce358e9b2..9b46f0756070 100644 --- a/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/IdentityClientIntegrationTests.java +++ b/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/IdentityClientIntegrationTests.java @@ -22,7 +22,7 @@ public class IdentityClientIntegrationTests { private static final String AZURE_CLIENT_CERTIFICATE = "AZURE_CLIENT_CERTIFICATE"; private final TokenRequestContext request = new TokenRequestContext().addScopes("https://management.azure.com/.default"); - @Test + @Ignore("Integration tests") public void clientSecretCanGetToken() { IdentityClient client = new IdentityClient(System.getenv(AZURE_TENANT_ID), System.getenv(AZURE_CLIENT_ID), new IdentityClientOptions()); StepVerifier.create(client.authenticateWithClientSecret(System.getenv(AZURE_CLIENT_SECRET), request)) @@ -37,7 +37,7 @@ public void clientSecretCanGetToken() { .verifyComplete(); } - @Test + @Ignore("Integration tests") public void deviceCodeCanGetToken() { IdentityClient client = new IdentityClient("common", System.getenv(AZURE_CLIENT_ID), new IdentityClientOptions().setProxyOptions(new ProxyOptions(Type.HTTP, new InetSocketAddress("localhost", 8888)))); MsalToken token = client.authenticateWithDeviceCode(request, deviceCode -> { @@ -59,9 +59,9 @@ public void deviceCodeCanGetToken() { Assert.assertFalse(token.isExpired()); } - @Test + @Ignore("Integration tests") public void browserCanGetToken() { - IdentityClient client = new IdentityClient("common", System.getenv(AZURE_CLIENT_ID), new IdentityClientOptions()); + IdentityClient client = new IdentityClient("common", System.getenv(AZURE_CLIENT_ID), new IdentityClientOptions().setProxyOptions(new ProxyOptions(Type.HTTP, new InetSocketAddress("localhost", 8888)))); MsalToken token = client.authenticateWithBrowserInteraction(request, 8765).block(); Assert.assertNotNull(token); Assert.assertNotNull(token.getToken()); From c372959e85335dae1f00fbc7d7a3dff30fd3a492 Mon Sep 17 00:00:00 2001 From: Jianghao Lu Date: Fri, 3 Jan 2020 23:28:08 -0800 Subject: [PATCH 07/15] Update msal4j in eventhubs --- eng/versioning/external_dependencies.txt | 2 +- sdk/eventhubs/microsoft-azure-eventhubs/pom.xml | 2 +- .../java/com/microsoft/azure/eventhubs/sendrecv/MsalTest.java | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/eng/versioning/external_dependencies.txt b/eng/versioning/external_dependencies.txt index 8e1d850960dd..2b16ef0beeb1 100644 --- a/eng/versioning/external_dependencies.txt +++ b/eng/versioning/external_dependencies.txt @@ -62,7 +62,7 @@ com.microsoft.azure:azure-mgmt-keyvault;1.11.1 com.microsoft.azure:azure-mgmt-resources;1.3.0 com.microsoft.azure:azure-mgmt-storage;1.3.0 com.microsoft.azure:azure-storage;8.0.0 -com.microsoft.azure:msal4j;0.5.0-preview +com.microsoft.azure:msal4j;1.1.0 io.opentelemetry:opentelemetry-api;0.2.0 io.opentelemetry:opentelemetry-sdk;0.2.0 io.projectreactor:reactor-test;3.3.0.RELEASE diff --git a/sdk/eventhubs/microsoft-azure-eventhubs/pom.xml b/sdk/eventhubs/microsoft-azure-eventhubs/pom.xml index 8b6a0b515286..9edcd7390500 100644 --- a/sdk/eventhubs/microsoft-azure-eventhubs/pom.xml +++ b/sdk/eventhubs/microsoft-azure-eventhubs/pom.xml @@ -76,7 +76,7 @@ com.microsoft.azure msal4j - 0.5.0-preview + 1.1.0 test diff --git a/sdk/eventhubs/microsoft-azure-eventhubs/src/test/java/com/microsoft/azure/eventhubs/sendrecv/MsalTest.java b/sdk/eventhubs/microsoft-azure-eventhubs/src/test/java/com/microsoft/azure/eventhubs/sendrecv/MsalTest.java index c91ca4b6bd43..e8a1d38b0828 100644 --- a/sdk/eventhubs/microsoft-azure-eventhubs/src/test/java/com/microsoft/azure/eventhubs/sendrecv/MsalTest.java +++ b/sdk/eventhubs/microsoft-azure-eventhubs/src/test/java/com/microsoft/azure/eventhubs/sendrecv/MsalTest.java @@ -3,8 +3,8 @@ package com.microsoft.azure.eventhubs.sendrecv; +import com.microsoft.aad.msal4j.ClientCredentialFactory; import com.microsoft.aad.msal4j.ClientCredentialParameters; -import com.microsoft.aad.msal4j.ClientSecret; import com.microsoft.aad.msal4j.ConfidentialClientApplication; import com.microsoft.aad.msal4j.IAuthenticationResult; import com.microsoft.azure.eventhubs.AzureActiveDirectoryTokenProvider; @@ -61,7 +61,7 @@ public void runSendReceiveWithCustomTokenProvider() throws Exception { @Override String tokenGet(final String authority, final String clientId, final String clientSecret, final String audience, final String extra) throws MalformedURLException, InterruptedException, ExecutionException { - ConfidentialClientApplication app = ConfidentialClientApplication.builder(clientId, new ClientSecret(clientSecret)) + ConfidentialClientApplication app = ConfidentialClientApplication.builder(clientId, ClientCredentialFactory.createFromSecret(clientSecret)) .authority(authority) .build(); From 27c34c09c4ba4486b94e37db8021b6e6352f71b8 Mon Sep 17 00:00:00 2001 From: Jianghao Lu Date: Sat, 4 Jan 2020 00:00:39 -0800 Subject: [PATCH 08/15] Checkstyle --- .../java/com/azure/identity/CredentialBuilderBase.java | 6 ++++++ .../identity/implementation/HttpPipelineAdapter.java | 9 +++++++-- .../implementation/IdentityClientIntegrationTests.java | 1 - 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/CredentialBuilderBase.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/CredentialBuilderBase.java index 73981044407b..73da65dea943 100644 --- a/sdk/identity/azure-identity/src/main/java/com/azure/identity/CredentialBuilderBase.java +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/CredentialBuilderBase.java @@ -57,6 +57,12 @@ public T proxyOptions(ProxyOptions proxyOptions) { return (T) this; } + /** + * Specifies the HttpPipeline to send all requests. This setting overrides the others. + * + * @param httpPipeline the HttpPipeline to send all requests + * @return itself + */ @SuppressWarnings("unchecked") public T httpPipeline(HttpPipeline httpPipeline) { this.identityClientOptions.setHttpPipeline(httpPipeline); diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/HttpPipelineAdapter.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/HttpPipelineAdapter.java index 523ac3e7adab..7ff4f654a486 100644 --- a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/HttpPipelineAdapter.java +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/HttpPipelineAdapter.java @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + package com.azure.identity.implementation; import com.azure.core.http.HttpHeader; @@ -41,14 +44,16 @@ public IHttpResponse send(HttpRequest httpRequest) throws Exception { com.microsoft.aad.msal4j.HttpResponse httpResponse = new com.microsoft.aad.msal4j.HttpResponse() .body(body) .statusCode(response.getStatusCode()); - httpResponse.headers(response.getHeaders().stream().collect(Collectors.toMap(HttpHeader::getName,h -> Collections.singletonList(h.getValue())))); + httpResponse.headers(response.getHeaders().stream().collect(Collectors.toMap(HttpHeader::getName, + h -> Collections.singletonList(h.getValue())))); return httpResponse; }) // if no body .switchIfEmpty(Mono.defer(() -> { com.microsoft.aad.msal4j.HttpResponse httpResponse = new com.microsoft.aad.msal4j.HttpResponse() .statusCode(response.getStatusCode()); - httpResponse.headers(response.getHeaders().stream().collect(Collectors.toMap(HttpHeader::getName,h -> Collections.singletonList(h.getValue())))); + httpResponse.headers(response.getHeaders().stream().collect(Collectors.toMap(HttpHeader::getName, + h -> Collections.singletonList(h.getValue())))); return Mono.just(httpResponse); }))) .block(); diff --git a/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/IdentityClientIntegrationTests.java b/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/IdentityClientIntegrationTests.java index 9b46f0756070..aa7fd71b7aef 100644 --- a/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/IdentityClientIntegrationTests.java +++ b/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/IdentityClientIntegrationTests.java @@ -8,7 +8,6 @@ import com.azure.core.http.ProxyOptions.Type; import org.junit.Assert; import org.junit.Ignore; -import org.junit.Test; import reactor.test.StepVerifier; import java.net.InetSocketAddress; From f9ecc2e3b8fe6573dbd0f5c3a4246a5cdb6b4613 Mon Sep 17 00:00:00 2001 From: Jianghao Lu Date: Sat, 4 Jan 2020 00:54:30 -0800 Subject: [PATCH 09/15] Checkstyle --- .../azure/identity/implementation/HttpPipelineAdapter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/HttpPipelineAdapter.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/HttpPipelineAdapter.java index 7ff4f654a486..5621bc018299 100644 --- a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/HttpPipelineAdapter.java +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/HttpPipelineAdapter.java @@ -45,7 +45,7 @@ public IHttpResponse send(HttpRequest httpRequest) throws Exception { .body(body) .statusCode(response.getStatusCode()); httpResponse.headers(response.getHeaders().stream().collect(Collectors.toMap(HttpHeader::getName, - h -> Collections.singletonList(h.getValue())))); + h -> Collections.singletonList(h.getValue())))); return httpResponse; }) // if no body @@ -53,7 +53,7 @@ public IHttpResponse send(HttpRequest httpRequest) throws Exception { com.microsoft.aad.msal4j.HttpResponse httpResponse = new com.microsoft.aad.msal4j.HttpResponse() .statusCode(response.getStatusCode()); httpResponse.headers(response.getHeaders().stream().collect(Collectors.toMap(HttpHeader::getName, - h -> Collections.singletonList(h.getValue())))); + h -> Collections.singletonList(h.getValue())))); return Mono.just(httpResponse); }))) .block(); From cace69f9c70083730179190cc0988efcb2abe5cc Mon Sep 17 00:00:00 2001 From: Jianghao Lu Date: Mon, 6 Jan 2020 10:39:44 -0800 Subject: [PATCH 10/15] Add azure-core-http-netty to identity pom.service.xml --- sdk/identity/pom.service.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sdk/identity/pom.service.xml b/sdk/identity/pom.service.xml index a295059f7c7b..f8c9b74b99e4 100644 --- a/sdk/identity/pom.service.xml +++ b/sdk/identity/pom.service.xml @@ -11,7 +11,8 @@ - ../core/azure-core + ../core/azure-core + ../core/azure-core-http-netty azure-identity From ed2ac04850708f89145442d7cb0e453c7e15d578 Mon Sep 17 00:00:00 2001 From: Jianghao Lu Date: Mon, 6 Jan 2020 11:04:49 -0800 Subject: [PATCH 11/15] Add azure-core-test to identity pom.service.xml --- sdk/identity/pom.service.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/identity/pom.service.xml b/sdk/identity/pom.service.xml index f8c9b74b99e4..c37d14e46a05 100644 --- a/sdk/identity/pom.service.xml +++ b/sdk/identity/pom.service.xml @@ -13,6 +13,7 @@ --> ../core/azure-core ../core/azure-core-http-netty + ../core/azure-core-test azure-identity From c1c4478e9c25014072a6f7c1c58d1d1836be0d32 Mon Sep 17 00:00:00 2001 From: Jianghao Lu Date: Sun, 12 Jan 2020 19:00:19 -0800 Subject: [PATCH 12/15] Update MSAL to 1.3.0 --- eng/versioning/external_dependencies.txt | 2 +- sdk/eventhubs/microsoft-azure-eventhubs/pom.xml | 2 +- sdk/identity/azure-identity/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/versioning/external_dependencies.txt b/eng/versioning/external_dependencies.txt index 2b16ef0beeb1..a6f90349641c 100644 --- a/eng/versioning/external_dependencies.txt +++ b/eng/versioning/external_dependencies.txt @@ -62,7 +62,7 @@ com.microsoft.azure:azure-mgmt-keyvault;1.11.1 com.microsoft.azure:azure-mgmt-resources;1.3.0 com.microsoft.azure:azure-mgmt-storage;1.3.0 com.microsoft.azure:azure-storage;8.0.0 -com.microsoft.azure:msal4j;1.1.0 +com.microsoft.azure:msal4j;1.3.0 io.opentelemetry:opentelemetry-api;0.2.0 io.opentelemetry:opentelemetry-sdk;0.2.0 io.projectreactor:reactor-test;3.3.0.RELEASE diff --git a/sdk/eventhubs/microsoft-azure-eventhubs/pom.xml b/sdk/eventhubs/microsoft-azure-eventhubs/pom.xml index 9edcd7390500..478167350d18 100644 --- a/sdk/eventhubs/microsoft-azure-eventhubs/pom.xml +++ b/sdk/eventhubs/microsoft-azure-eventhubs/pom.xml @@ -76,7 +76,7 @@ com.microsoft.azure msal4j - 1.1.0 + 1.3.0 test diff --git a/sdk/identity/azure-identity/pom.xml b/sdk/identity/azure-identity/pom.xml index a6bb9ae9ed43..7a24db6d5854 100644 --- a/sdk/identity/azure-identity/pom.xml +++ b/sdk/identity/azure-identity/pom.xml @@ -33,7 +33,7 @@ com.microsoft.azure msal4j - 1.1.0 + 1.3.0 com.nimbusds From f91989e0e3c5bec0ece4c972859efdee51daec93 Mon Sep 17 00:00:00 2001 From: Jianghao Lu Date: Tue, 14 Jan 2020 00:21:43 -0800 Subject: [PATCH 13/15] Some cr feedback --- sdk/identity/azure-identity/pom.xml | 2 +- .../java/com/azure/identity/implementation/IdentityClient.java | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/sdk/identity/azure-identity/pom.xml b/sdk/identity/azure-identity/pom.xml index 6541e1f8a79e..1f2c5ba3ee3d 100644 --- a/sdk/identity/azure-identity/pom.xml +++ b/sdk/identity/azure-identity/pom.xml @@ -84,7 +84,7 @@ com.azure azure-core-http-netty - 1.1.0 + 1.2.0 test diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClient.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClient.java index cbb9c20fa20c..89c2ed1009f5 100644 --- a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClient.java +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClient.java @@ -143,7 +143,6 @@ public Mono authenticateWithPfxCertificate(String pfxCertificatePat ConfidentialClientApplication.Builder applicationBuilder = ConfidentialClientApplication.builder(clientId, ClientCredentialFactory.createFromCertificate( new FileInputStream(pfxCertificatePath), pfxCertificatePassword)) - .httpClient(new HttpPipelineAdapter(options.getHttpPipeline())) .authority(authorityUrl); if (options.getProxyOptions() != null) { applicationBuilder.proxy(proxyOptionsToJavaNetProxy(options.getProxyOptions())); @@ -173,7 +172,6 @@ public Mono authenticateWithPemCertificate(String pemCertificatePat ConfidentialClientApplication.builder(clientId, ClientCredentialFactory.createFromCertificate( CertificateUtil.privateKeyFromPem(pemCertificateBytes), CertificateUtil.publicKeyFromPem(pemCertificateBytes))) - .httpClient(new HttpPipelineAdapter(options.getHttpPipeline())) .authority(authorityUrl); if (options.getProxyOptions() != null) { applicationBuilder.proxy(proxyOptionsToJavaNetProxy(options.getProxyOptions())); From 3a9509074425212a4674cb5289bc4a2cdbc61b7e Mon Sep 17 00:00:00 2001 From: Jianghao Lu Date: Tue, 14 Jan 2020 11:47:38 -0800 Subject: [PATCH 14/15] Add GSON test dependency to identity --- sdk/identity/azure-identity/pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sdk/identity/azure-identity/pom.xml b/sdk/identity/azure-identity/pom.xml index 1f2c5ba3ee3d..2d8ec149b981 100644 --- a/sdk/identity/azure-identity/pom.xml +++ b/sdk/identity/azure-identity/pom.xml @@ -87,5 +87,12 @@ 1.2.0 test + + + com.google.code.gson + gson + 2.8.5 + test + From 1617b80ff125af1037c90ac3999e6b0e32b56116 Mon Sep 17 00:00:00 2001 From: Jianghao Lu Date: Tue, 14 Jan 2020 12:07:05 -0800 Subject: [PATCH 15/15] Add back test verification of client certificate --- .../identity/implementation/IdentityClientTests.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/IdentityClientTests.java b/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/IdentityClientTests.java index a3d22e4545ca..ef04b0502069 100644 --- a/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/IdentityClientTests.java +++ b/sdk/identity/azure-identity/src/test/java/com/azure/identity/implementation/IdentityClientTests.java @@ -9,6 +9,7 @@ import com.microsoft.aad.msal4j.ClientCredentialParameters; import com.microsoft.aad.msal4j.ConfidentialClientApplication; import com.microsoft.aad.msal4j.DeviceCodeFlowParameters; +import com.microsoft.aad.msal4j.IClientCredential; import com.microsoft.aad.msal4j.IClientSecret; import com.microsoft.aad.msal4j.MsalServiceException; import com.microsoft.aad.msal4j.PublicClientApplication; @@ -185,13 +186,13 @@ private void mockForClientCertificate(TokenRequestContext request, String access when(builder.httpClient(any())).thenReturn(builder); whenNew(ConfidentialClientApplication.Builder.class).withAnyArguments().thenAnswer(invocation -> { String cid = (String) invocation.getArguments()[0]; -// AsymmetricKeyCredential keyCredential = (AsymmetricKeyCredential) invocation.getArguments()[1]; + IClientCredential keyCredential = (IClientCredential) invocation.getArguments()[1]; if (!clientId.equals(cid)) { throw new MsalServiceException("Invalid clientId", "InvalidClientId"); } -// if (keyCredential == null || keyCredential.key() == null) { -// throw new MsalServiceException("Invalid clientCertificate", "InvalidClientCertificate"); -// } + if (keyCredential == null) { + throw new MsalServiceException("Invalid clientCertificate", "InvalidClientCertificate"); + } return builder; }); }