diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/ClientAssertionCredential.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/ClientAssertionCredential.java new file mode 100644 index 000000000000..7189ed7b4c51 --- /dev/null +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/ClientAssertionCredential.java @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.identity; + +import com.azure.core.credential.AccessToken; +import com.azure.core.credential.TokenRequestContext; +import com.azure.identity.implementation.IdentityClient; + +import reactor.core.publisher.Mono; + +/** + * Authenticates a service principal with AAD using a client assertion. + */ +class ClientAssertionCredential extends ManagedIdentityServiceCredential { + + /** + * Creates an instance of ClientAssertionCredential. + * + * @param clientId the client id of user assigned or system assigned identity. + * @param identityClient the identity client to acquire a token with. + */ + ClientAssertionCredential(String clientId, IdentityClient identityClient) { + super(clientId, identityClient, "AZURE AKS TOKEN EXCHANGE"); + } + + @Override + public Mono authenticate(TokenRequestContext request) { + return identityClient.authenticatewithExchangeToken(request); + } +} diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/ManagedIdentityCredential.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/ManagedIdentityCredential.java index d5129fb369c2..cd4789c7fd01 100644 --- a/sdk/identity/azure-identity/src/main/java/com/azure/identity/ManagedIdentityCredential.java +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/ManagedIdentityCredential.java @@ -9,7 +9,6 @@ import com.azure.core.credential.TokenRequestContext; import com.azure.core.util.Configuration; import com.azure.core.util.logging.ClientLogger; -import com.azure.identity.implementation.IdentityClient; import com.azure.identity.implementation.IdentityClientBuilder; import com.azure.identity.implementation.IdentityClientOptions; import com.azure.identity.implementation.util.LoggingUtil; @@ -25,6 +24,7 @@ public final class ManagedIdentityCredential implements TokenCredential { static final String PROPERTY_IMDS_ENDPOINT = "IMDS_ENDPOINT"; static final String PROPERTY_IDENTITY_SERVER_THUMBPRINT = "IDENTITY_SERVER_THUMBPRINT"; + static final String TOKEN_FILE_PATH = "TOKEN_FILE_PATH"; /** @@ -33,28 +33,35 @@ public final class ManagedIdentityCredential implements TokenCredential { * @param identityClientOptions the options for configuring the identity client. */ ManagedIdentityCredential(String clientId, IdentityClientOptions identityClientOptions) { - IdentityClient identityClient = new IdentityClientBuilder() + IdentityClientBuilder clientBuilder = new IdentityClientBuilder() .clientId(clientId) - .identityClientOptions(identityClientOptions) - .build(); + .identityClientOptions(identityClientOptions); + Configuration configuration = Configuration.getGlobalConfiguration().clone(); if (configuration.contains(Configuration.PROPERTY_MSI_ENDPOINT)) { - managedIdentityServiceCredential = new AppServiceMsiCredential(clientId, identityClient); + managedIdentityServiceCredential = new AppServiceMsiCredential(clientId, clientBuilder.build()); } else if (configuration.contains(Configuration.PROPERTY_IDENTITY_ENDPOINT)) { if (configuration.contains(Configuration.PROPERTY_IDENTITY_HEADER)) { if (configuration.get(PROPERTY_IDENTITY_SERVER_THUMBPRINT) != null) { - managedIdentityServiceCredential = new ServiceFabricMsiCredential(clientId, identityClient); + managedIdentityServiceCredential = new ServiceFabricMsiCredential(clientId, clientBuilder.build()); } else { - managedIdentityServiceCredential = new VirtualMachineMsiCredential(clientId, identityClient); + managedIdentityServiceCredential = new VirtualMachineMsiCredential(clientId, clientBuilder.build()); } } else if (configuration.get(PROPERTY_IMDS_ENDPOINT) != null) { - managedIdentityServiceCredential = new ArcIdentityCredential(clientId, identityClient); + managedIdentityServiceCredential = new ArcIdentityCredential(clientId, clientBuilder.build()); } else { - managedIdentityServiceCredential = new VirtualMachineMsiCredential(clientId, identityClient); + managedIdentityServiceCredential = new VirtualMachineMsiCredential(clientId, clientBuilder.build()); } + } else if (configuration.contains(Configuration.PROPERTY_AZURE_CLIENT_ID) + && configuration.contains(Configuration.PROPERTY_AZURE_TENANT_ID) + && configuration.get(TOKEN_FILE_PATH) != null) { + clientBuilder.tenantId(configuration.get(Configuration.PROPERTY_AZURE_TENANT_ID)); + clientBuilder.clientAssertionPath(configuration.get(TOKEN_FILE_PATH)); + managedIdentityServiceCredential = new ClientAssertionCredential(clientId, clientBuilder.build()); + } else { - managedIdentityServiceCredential = new VirtualMachineMsiCredential(clientId, identityClient); + managedIdentityServiceCredential = new VirtualMachineMsiCredential(clientId, clientBuilder.build()); } LoggingUtil.logAvailableEnvironmentVariables(logger, configuration); } diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/OnBehalfOfCredential.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/OnBehalfOfCredential.java new file mode 100644 index 000000000000..4ea37b537077 --- /dev/null +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/OnBehalfOfCredential.java @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.identity; + +import com.azure.core.credential.AccessToken; +import com.azure.core.credential.TokenCredential; +import com.azure.core.credential.TokenRequestContext; +import com.azure.core.util.logging.ClientLogger; +import com.azure.identity.implementation.IdentityClient; +import com.azure.identity.implementation.IdentityClientBuilder; +import com.azure.identity.implementation.IdentityClientOptions; +import com.azure.identity.implementation.util.LoggingUtil; +import reactor.core.publisher.Mono; + +import java.time.Duration; + +/** + * An AAD credential that acquires a token with a client secret and user assertion for an AAD application + * on behalf of a user principal. + */ +public class OnBehalfOfCredential implements TokenCredential { + private final IdentityClient identityClient; + private final ClientLogger logger = new ClientLogger(OnBehalfOfCredential.class); + + + /** + * Creates OnBehalfOfCredential with the specified AAD application details and client options. + * + * @param tenantId the tenant ID of the application + * @param clientId the client ID of the application + * @param clientSecret the secret value of the AAD application. + * @param certificatePath the PEM file or PFX file containing the certificate + * @param certificatePassword the password protecting the PFX file + * @param identityClientOptions the options for configuring the identity client + */ + public OnBehalfOfCredential(String clientId, String tenantId, String clientSecret, String certificatePath, + String certificatePassword, IdentityClientOptions identityClientOptions) { + this.identityClient = new IdentityClientBuilder() + .tenantId(tenantId) + .clientId(clientId) + .clientSecret(clientSecret) + .certificatePath(certificatePath) + .certificatePassword(certificatePassword) + .identityClientOptions(identityClientOptions) + .confidentialClientCacheTimeout(Duration.ofMinutes(5)) + .build(); + } + + @Override + public Mono getToken(TokenRequestContext request) { + return Mono.deferContextual(ctx -> identityClient.authenticateWithConfidentialClientCache(request) + .onErrorResume(t -> Mono.empty()) + .switchIfEmpty(Mono.defer(() -> identityClient.authenticateWithOBO(request))) + .doOnNext(token -> LoggingUtil.logTokenSuccess(logger, request)) + .doOnError(error -> LoggingUtil.logTokenError(logger, request, error))); + } +} diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/OnBehalfOfCredentialBuilder.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/OnBehalfOfCredentialBuilder.java new file mode 100644 index 000000000000..c988f1b88628 --- /dev/null +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/OnBehalfOfCredentialBuilder.java @@ -0,0 +1,127 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.identity; + +import com.azure.core.util.logging.ClientLogger; +import com.azure.identity.implementation.util.ValidationUtil; + +import java.util.HashMap; + +/** + * Fluent credential builder for instantiating a {@link OnBehalfOfCredential}. + * + * @see OnBehalfOfCredential + */ +public class OnBehalfOfCredentialBuilder extends AadCredentialBuilderBase { + private String clientSecret; + private String clientCertificatePath; + private String clientCertificatePassword; + private final ClientLogger logger = new ClientLogger(OnBehalfOfCredentialBuilder.class); + + /** + * Sets the client secret for the authentication. + * @param clientSecret the secret value of the AAD application. + * @return An updated instance of this builder. + */ + public OnBehalfOfCredentialBuilder clientSecret(String clientSecret) { + this.clientSecret = clientSecret; + return this; + } + + /** + * Configures the persistent shared token cache options and enables the persistent token cache which is disabled + * by default. If configured, the credential will store tokens in a cache persisted to the machine, protected to + * the current user, which can be shared by other credentials and processes. + * + * @param tokenCachePersistenceOptions the token cache configuration options + * @return An updated instance of this builder with the token cache options configured. + */ + public OnBehalfOfCredentialBuilder tokenCachePersistenceOptions(TokenCachePersistenceOptions + tokenCachePersistenceOptions) { + this.identityClientOptions.setTokenCacheOptions(tokenCachePersistenceOptions); + return this; + } + + /** + * Sets the path and password of the PFX certificate for authenticating to AAD. + * + * @param certificatePath the password protected PFX file containing the certificate + * @param clientCertificatePassword the password protecting the PFX file + * @return An updated instance of this builder. + */ + public OnBehalfOfCredentialBuilder pfxCertificate(String certificatePath, + String clientCertificatePassword) { + this.clientCertificatePath = certificatePath; + this.clientCertificatePassword = clientCertificatePassword; + return this; + } + + /** + * Specifies if the x5c claim (public key of the certificate) should be sent as part of the authentication request + * and enable subject name / issuer based authentication. The default value is false. + * + * @param sendCertificateChain the flag to indicate if certificate chain should be sent as part of authentication + * request. + * @return An updated instance of this builder. + */ + public OnBehalfOfCredentialBuilder sendCertificateChain(boolean sendCertificateChain) { + this.identityClientOptions.setIncludeX5c(sendCertificateChain); + return this; + } + + /** + * Specifies either the specific regional authority, or use {@link RegionalAuthority#AUTO_DISCOVER_REGION} to + * attempt to auto-detect the region. If unset, a non-regional authority will be used. This argument should be used + * only by applications deployed to Azure VMs. + * + * @param regionalAuthority the regional authority + * @return An updated instance of this builder with the regional authority configured. + */ + public OnBehalfOfCredentialBuilder regionalAuthority(RegionalAuthority regionalAuthority) { + this.identityClientOptions.setRegionalAuthority(regionalAuthority); + return this; + } + + /** + * Configure the User Assertion Scope to be used for OnBehalfOf Authentication request. + * + * @param userAssertion the user assertion access token to be used for On behalf Of authentication flow + * @return An updated instance of this builder with the user assertion scope configured. + */ + public OnBehalfOfCredentialBuilder userAssertion(String userAssertion) { + this.identityClientOptions.userAssertion(userAssertion); + return this; + } + + /** + * Creates a new {@link OnBehalfOfCredential} with the current configurations. + * + * @return a {@link OnBehalfOfCredential} with the current configurations. + * @throws IllegalArgumentException if eiter both the client secret and certificate are configured or none of them + * are configured. + */ + public OnBehalfOfCredential build() { + ValidationUtil.validate(getClass().getSimpleName(), new HashMap() { + { + put("clientId", clientId); + put("tenantId", tenantId); + } + }); + + if (clientSecret == null && clientCertificatePath == null) { + throw logger.logExceptionAsWarning(new IllegalArgumentException("Atleast client secret or certificate " + + "path should provided in OnBhealfOfCredentialBuilder. Only one of them should " + + "be provided.")); + } + + if (clientCertificatePath != null && clientSecret != null) { + throw logger.logExceptionAsWarning(new IllegalArgumentException("Both client secret and certificate " + + "path are provided in OnBhealfCredentialBuilder. Only one of them should " + + "be provided.")); + } + + return new OnBehalfOfCredential(clientId, tenantId, clientSecret, clientCertificatePath, + clientCertificatePassword, identityClientOptions); + } +} 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 0f02ac01ee92..bb87cef1a3f4 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 @@ -42,6 +42,7 @@ import com.microsoft.aad.msal4j.IClientCredential; import com.microsoft.aad.msal4j.InteractiveRequestParameters; import com.microsoft.aad.msal4j.MsalInteractionRequiredException; +import com.microsoft.aad.msal4j.OnBehalfOfParameters; import com.microsoft.aad.msal4j.Prompt; import com.microsoft.aad.msal4j.PublicClientApplication; import com.microsoft.aad.msal4j.RefreshTokenParameters; @@ -122,6 +123,7 @@ public class IdentityClient { private final String tenantId; private final String clientId; private final String clientSecret; + private final String clientAssertionFilePath; private final InputStream certificate; private final String certificatePath; private final String certificatePassword; @@ -140,10 +142,12 @@ public class IdentityClient { * @param certificatePassword the password protecting the PFX certificate. * @param isSharedTokenCacheCredential Indicate whether the credential is * {@link com.azure.identity.SharedTokenCacheCredential} or not. + * @param confidentialClientCacheTimeout the cache time out to use for confidential client. * @param options the options configuring the client. */ IdentityClient(String tenantId, String clientId, String clientSecret, String certificatePath, - InputStream certificate, String certificatePassword, boolean isSharedTokenCacheCredential, + String clientAssertionFilePath, InputStream certificate, String certificatePassword, + boolean isSharedTokenCacheCredential, Duration confidentialClientCacheTimeout, IdentityClientOptions options) { if (tenantId == null) { tenantId = "organizations"; @@ -154,16 +158,18 @@ public class IdentityClient { this.tenantId = tenantId; this.clientId = clientId; this.clientSecret = clientSecret; + this.clientAssertionFilePath = clientAssertionFilePath; this.certificatePath = certificatePath; this.certificate = certificate; this.certificatePassword = certificatePassword; this.options = options; - this.publicClientApplicationAccessor = new SynchronizedAccessor(() -> + this.publicClientApplicationAccessor = new SynchronizedAccessor<>(() -> getPublicClientApplication(isSharedTokenCacheCredential)); - this.confidentialClientApplicationAccessor = new SynchronizedAccessor(() -> - getConfidentialClientApplication()); + this.confidentialClientApplicationAccessor = confidentialClientCacheTimeout == null + ? new SynchronizedAccessor<>(() -> getConfidentialClientApplication()) + : new SynchronizedAccessor<>(() -> getConfidentialClientApplication(), confidentialClientCacheTimeout); } private Mono getConfidentialClientApplication() { @@ -205,6 +211,15 @@ private Mono getConfidentialClientApplication() { return Mono.error(logger.logExceptionAsError(new RuntimeException( "Failed to parse the certificate for the credential: " + e.getMessage(), e))); } + } else if (clientAssertionFilePath != null) { + try { + credential = ClientCredentialFactory + .createFromClientAssertion(parseClientAssertion(clientAssertionFilePath)); + } catch (IOException e) { + return Mono.error(logger.logExceptionAsError(new RuntimeException( + "Failed to parse the client assertion from the provided file: " + clientAssertionFilePath + + ". " + e.getMessage(), e))); + } } else { return Mono.error(logger.logExceptionAsError( new IllegalArgumentException("Must provide client secret or client certificate path"))); @@ -256,6 +271,11 @@ private Mono getConfidentialClientApplication() { }); } + private String parseClientAssertion(String clientAssertionFilePath) throws IOException { + byte[] encoded = Files.readAllBytes(Paths.get(clientAssertionFilePath)); + return new String(encoded, StandardCharsets.UTF_8); + } + private Mono getPublicClientApplication(boolean sharedTokenCacheCredential) { return Mono.defer(() -> { if (clientId == null) { @@ -526,6 +546,23 @@ public Mono authenticateWithAzurePowerShell(TokenRequestContext req })); } + + /** + * Asynchronously acquire a token from Active Directory with Azure Power Shell. + * + * @param request the details of the token request + * @return a Publisher that emits an AccessToken + */ + public Mono authenticateWithOBO(TokenRequestContext request) { + + return confidentialClientApplicationAccessor.getValue() + .flatMap(confidentialClient -> Mono.fromFuture(() -> confidentialClient.acquireToken(OnBehalfOfParameters + .builder(new HashSet<>(request.getScopes()), options.getUserAssertion()) + .build())) + .map(MsalToken::new)); + } + + private Mono getAccessTokenFromPowerShell(TokenRequestContext request, PowershellManager powershellManager) { return powershellManager.initSession() @@ -994,6 +1031,16 @@ public Mono authenticateToArcManagedIdentityEndpoint(String identit }); } + /** + * Asynchronously acquire a token from the Azure Arc Managed Service Identity endpoint. + * + * @param request the details of the token request + * @return a Publisher that emits an AccessToken + */ + public Mono authenticatewithExchangeToken(TokenRequestContext request) { + return authenticateWithConfidentialClient(request); + } + /** * Asynchronously acquire a token from the Azure Service Fabric Managed Service Identity endpoint. * diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClientBuilder.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClientBuilder.java index c7c25071d66c..51192fe87f78 100644 --- a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClientBuilder.java +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClientBuilder.java @@ -6,6 +6,7 @@ import com.azure.identity.SharedTokenCacheCredential; import java.io.InputStream; +import java.time.Duration; /** * Fluent client builder for instantiating an {@link IdentityClient}. @@ -17,10 +18,12 @@ public final class IdentityClientBuilder { private String tenantId; private String clientId; private String clientSecret; + private String clientAssertionPath; private String certificatePath; private InputStream certificate; private String certificatePassword; private boolean sharedTokenCacheCred; + private Duration confidentialClientCacheTimeout; /** * Sets the tenant ID for the client. @@ -63,6 +66,17 @@ public IdentityClientBuilder certificatePath(String certificatePath) { return this; } + /** + * Sets the client certificate for the client. + * + * @param clientAssertionPath the path to the file containing client assertion. + * @return the IdentityClientBuilder itself + */ + public IdentityClientBuilder clientAssertionPath(String clientAssertionPath) { + this.clientAssertionPath = clientAssertionPath; + return this; + } + /** * Sets the client certificate for the client. * @@ -106,11 +120,22 @@ public IdentityClientBuilder sharedTokenCacheCredential(boolean isSharedTokenCac return this; } + /** + * Configure the time out to use re-use confidential client for. Post time out, a new instance of client is created. + * + * @param confidentialClientCacheTimeout the time out to use for confidential client cache. + * @return the updated IdentityClientBuilder. + */ + public IdentityClientBuilder confidentialClientCacheTimeout(Duration confidentialClientCacheTimeout) { + this.confidentialClientCacheTimeout = confidentialClientCacheTimeout; + return this; + } + /** * @return a {@link IdentityClient} with the current configurations. */ public IdentityClient build() { - return new IdentityClient(tenantId, clientId, clientSecret, certificatePath, certificate, - certificatePassword, sharedTokenCacheCred, identityClientOptions); + return new IdentityClient(tenantId, clientId, clientSecret, certificatePath, clientAssertionPath, certificate, + certificatePassword, sharedTokenCacheCred, confidentialClientCacheTimeout, identityClientOptions); } } 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 f2b913644491..235b5c2da6cd 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 @@ -7,11 +7,12 @@ import com.azure.core.http.HttpPipeline; import com.azure.core.http.ProxyOptions; import com.azure.core.util.Configuration; -import com.azure.identity.AuthenticationRecord; import com.azure.identity.AzureAuthorityHosts; +import com.azure.identity.AuthenticationRecord; import com.azure.identity.RegionalAuthority; import com.azure.identity.TokenCachePersistenceOptions; import com.azure.identity.implementation.util.ValidationUtil; +import com.microsoft.aad.msal4j.UserAssertion; import java.time.Duration; import java.util.concurrent.ExecutorService; @@ -41,6 +42,7 @@ public final class IdentityClientOptions { private TokenCachePersistenceOptions tokenCachePersistenceOptions; private boolean cp1Disabled; private RegionalAuthority regionalAuthority; + private UserAssertion userAssertion; private boolean identityLegacyTenantSelection; private Configuration configuration; @@ -355,6 +357,26 @@ public RegionalAuthority getRegionalAuthority() { } + /** + * Configure the User Assertion Scope to be used for OnBehalfOf Authentication request. + * + * @param userAssertion the user assertion access token to be used for On behalf Of authentication flow + * @return the updated identity client options + */ + public IdentityClientOptions userAssertion(String userAssertion) { + this.userAssertion = new UserAssertion(userAssertion); + return this; + } + + /** + * Get the configured {@link UserAssertion} + * + * @return the configured user assertion scope + */ + public UserAssertion getUserAssertion() { + return this.userAssertion; + } + /** * Gets the regional authority, or null if regional authority should not be used. * @return the regional authority value if specified @@ -363,7 +385,6 @@ public boolean isLegacyTenantSelectionEnabled() { return identityLegacyTenantSelection; } - /** * Sets the specified configuration store. * diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/SynchronizedAccessor.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/SynchronizedAccessor.java index c63bdf444ca3..5754a857ec6e 100644 --- a/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/SynchronizedAccessor.java +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/SynchronizedAccessor.java @@ -5,6 +5,7 @@ import reactor.core.publisher.Mono; +import java.time.Duration; import java.util.function.Supplier; /** @@ -19,6 +20,10 @@ public SynchronizedAccessor(Supplier> supplier) { monoCache = supplier.get().cache(); } + public SynchronizedAccessor(Supplier> supplier, Duration cacheTimeout) { + monoCache = supplier.get().cache(cacheTimeout); + } + /** * Get the value from the configured supplier. * diff --git a/sdk/identity/azure-identity/src/test/java/com/azure/identity/AzureApplicationCredentialTest.java b/sdk/identity/azure-identity/src/test/java/com/azure/identity/AzureApplicationCredentialTest.java index 56c0031507ae..73b391f9c394 100644 --- a/sdk/identity/azure-identity/src/test/java/com/azure/identity/AzureApplicationCredentialTest.java +++ b/sdk/identity/azure-identity/src/test/java/com/azure/identity/AzureApplicationCredentialTest.java @@ -50,7 +50,7 @@ public void testUseEnvironmentCredential() throws Exception { IdentityClient identityClient = PowerMockito.mock(IdentityClient.class); when(identityClient.authenticateWithConfidentialClientCache(any())).thenReturn(Mono.empty()); when(identityClient.authenticateWithConfidentialClient(request1)).thenReturn(TestUtils.getMockAccessToken(token1, expiresOn)); - PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), eq(secret), isNull(), isNull(), isNull(), eq(false), any()).thenReturn(identityClient); + PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), eq(secret), isNull(), isNull(), isNull(), isNull(), eq(false), isNull(), any()).thenReturn(identityClient); // test AzureApplicationCredential credential = new AzureApplicationCredentialBuilder().build(); diff --git a/sdk/identity/azure-identity/src/test/java/com/azure/identity/ClientCertificateCredentialTest.java b/sdk/identity/azure-identity/src/test/java/com/azure/identity/ClientCertificateCredentialTest.java index 67fe612e58a0..4b181c11677c 100644 --- a/sdk/identity/azure-identity/src/test/java/com/azure/identity/ClientCertificateCredentialTest.java +++ b/sdk/identity/azure-identity/src/test/java/com/azure/identity/ClientCertificateCredentialTest.java @@ -57,8 +57,8 @@ public void testValidCertificatePaths() throws Exception { when(pfxIdentityClient.authenticateWithConfidentialClientCache(any())).thenReturn(Mono.empty()); when(pemIdentityClient.authenticateWithConfidentialClient(request1)).thenReturn(TestUtils.getMockAccessToken(token1, expiresAt)); when(pfxIdentityClient.authenticateWithConfidentialClient(request2)).thenReturn(TestUtils.getMockAccessToken(token2, expiresAt)); - PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), isNull(), eq(pemPath), isNull(), isNull(), eq(false), any()).thenReturn(pemIdentityClient); - PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), isNull(), eq(pfxPath), isNull(), eq(pfxPassword), eq(false), any()).thenReturn(pfxIdentityClient); + PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), isNull(), eq(pemPath), isNull(), isNull(), isNull(), eq(false), isNull(), any()).thenReturn(pemIdentityClient); + PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), isNull(), eq(pfxPath), isNull(), isNull(), eq(pfxPassword), eq(false), isNull(), any()).thenReturn(pfxIdentityClient); // test ClientCertificateCredential credential = @@ -95,8 +95,8 @@ public void testValidCertificates() throws Exception { when(pfxIdentityClient.authenticateWithConfidentialClientCache(any())).thenReturn(Mono.empty()); when(pemIdentityClient.authenticateWithConfidentialClient(request1)).thenReturn(TestUtils.getMockAccessToken(token1, expiresAt)); when(pfxIdentityClient.authenticateWithConfidentialClient(request2)).thenReturn(TestUtils.getMockAccessToken(token2, expiresAt)); - PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), isNull(), isNull(), eq(pemCert), isNull(), eq(false), any()).thenReturn(pemIdentityClient); - PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), isNull(), isNull(), eq(pfxCert), eq(pfxPassword), eq(false), any()).thenReturn(pfxIdentityClient); + PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), isNull(), isNull(), isNull(), eq(pemCert), isNull(), eq(false), isNull(), any()).thenReturn(pemIdentityClient); + PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), isNull(), isNull(), isNull(), eq(pfxCert), eq(pfxPassword), eq(false), isNull(), any()).thenReturn(pfxIdentityClient); // test ClientCertificateCredential credential = @@ -129,8 +129,8 @@ public void testInvalidCertificatePaths() throws Exception { when(pfxIdentityClient.authenticateWithConfidentialClientCache(any())).thenReturn(Mono.empty()); when(pemIdentityClient.authenticateWithConfidentialClient(request1)).thenReturn(Mono.error(new MsalServiceException("bad pem", "BadPem"))); when(pfxIdentityClient.authenticateWithConfidentialClient(request2)).thenReturn(Mono.error(new MsalServiceException("bad pfx", "BadPfx"))); - PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), isNull(), eq(pemPath), isNull(), isNull(), eq(false), any()).thenReturn(pemIdentityClient); - PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), isNull(), eq(pfxPath), isNull(), eq(pfxPassword), eq(false), any()).thenReturn(pfxIdentityClient); + PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), isNull(), eq(pemPath), isNull(), isNull(), isNull(), eq(false), isNull(), any()).thenReturn(pemIdentityClient); + PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), isNull(), eq(pfxPath), isNull(), isNull(), eq(pfxPassword), eq(false), isNull(), any()).thenReturn(pfxIdentityClient); // test ClientCertificateCredential credential = @@ -162,8 +162,8 @@ public void testInvalidCertificates() throws Exception { when(pfxIdentityClient.authenticateWithConfidentialClientCache(any())).thenReturn(Mono.empty()); when(pemIdentityClient.authenticateWithConfidentialClient(request1)).thenReturn(Mono.error(new MsalServiceException("bad pem", "BadPem"))); when(pfxIdentityClient.authenticateWithConfidentialClient(request2)).thenReturn(Mono.error(new MsalServiceException("bad pfx", "BadPfx"))); - PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), isNull(), isNull(), eq(pemCert), isNull(), eq(false), any()).thenReturn(pemIdentityClient); - PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), isNull(), isNull(), eq(pfxCert), eq(pfxPassword), eq(false), any()).thenReturn(pfxIdentityClient); + PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), isNull(), isNull(), isNull(), eq(pemCert), isNull(), eq(false), isNull(), any()).thenReturn(pemIdentityClient); + PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), isNull(), isNull(), isNull(), eq(pfxCert), eq(pfxPassword), eq(false), isNull(), any()).thenReturn(pfxIdentityClient); // test ClientCertificateCredential credential = @@ -191,7 +191,7 @@ public void testInvalidParameters() throws Exception { IdentityClient identityClient = PowerMockito.mock(IdentityClient.class); when(identityClient.authenticateWithConfidentialClientCache(any())).thenReturn(Mono.empty()); when(identityClient.authenticateWithConfidentialClient(request)).thenReturn(TestUtils.getMockAccessToken(token1, expiresOn)); - PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), isNull(), eq(pemPath), isNull(), isNull(), eq(false), any()).thenReturn(identityClient); + PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), isNull(), eq(pemPath), isNull(), isNull(), isNull(), eq(false), isNull(), any()).thenReturn(identityClient); // test try { diff --git a/sdk/identity/azure-identity/src/test/java/com/azure/identity/ClientSecretCredentialTest.java b/sdk/identity/azure-identity/src/test/java/com/azure/identity/ClientSecretCredentialTest.java index b4de4b76d9ee..256b54ee1eef 100644 --- a/sdk/identity/azure-identity/src/test/java/com/azure/identity/ClientSecretCredentialTest.java +++ b/sdk/identity/azure-identity/src/test/java/com/azure/identity/ClientSecretCredentialTest.java @@ -82,8 +82,8 @@ public void testInvalidSecrets() throws Exception { when(badIdentityClient.authenticateWithConfidentialClientCache(any())).thenReturn(Mono.empty()); when(identityClient.authenticateWithConfidentialClient(request)).thenReturn(TestUtils.getMockAccessToken(token1, expiresOn)); when(badIdentityClient.authenticateWithConfidentialClient(request)).thenReturn(Mono.error(new MsalServiceException("bad secret", "BadSecret"))); - PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), eq(secret), isNull(), isNull(), isNull(), eq(false), any()).thenReturn(identityClient); - PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), eq(badSecret), isNull(), isNull(), isNull(), eq(false), any()).thenReturn(badIdentityClient); + PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), eq(secret), isNull(), isNull(), isNull(), isNull(), eq(false), isNull(), any()).thenReturn(identityClient); + PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), eq(badSecret), isNull(), isNull(), isNull(), isNull(), eq(false), isNull(), any()).thenReturn(badIdentityClient); // test ClientSecretCredential credential = diff --git a/sdk/identity/azure-identity/src/test/java/com/azure/identity/DefaultAzureCredentialTest.java b/sdk/identity/azure-identity/src/test/java/com/azure/identity/DefaultAzureCredentialTest.java index 27da40c3023c..edea9c5cfcd7 100644 --- a/sdk/identity/azure-identity/src/test/java/com/azure/identity/DefaultAzureCredentialTest.java +++ b/sdk/identity/azure-identity/src/test/java/com/azure/identity/DefaultAzureCredentialTest.java @@ -52,7 +52,7 @@ public void testUseEnvironmentCredential() throws Exception { IdentityClient identityClient = PowerMockito.mock(IdentityClient.class); when(identityClient.authenticateWithConfidentialClientCache(any())).thenReturn(Mono.empty()); when(identityClient.authenticateWithConfidentialClient(request1)).thenReturn(TestUtils.getMockAccessToken(token1, expiresOn)); - PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), eq(secret), isNull(), isNull(), isNull(), eq(false), any()).thenReturn(identityClient); + PowerMockito.whenNew(IdentityClient.class).withArguments(eq(TENANT_ID), eq(CLIENT_ID), eq(secret), isNull(), isNull(), isNull(), isNull(), eq(false), isNull(), any()).thenReturn(identityClient); IntelliJCredential intelliJCredential = PowerMockito.mock(IntelliJCredential.class); when(intelliJCredential.getToken(request1)) 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 4d6ea9b4ede7..02aebbd052f0 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 @@ -23,7 +23,7 @@ public class IdentityClientIntegrationTests { @Ignore("Integration tests") public void clientSecretCanGetToken() { - IdentityClient client = new IdentityClient(System.getenv(AZURE_TENANT_ID), System.getenv(AZURE_CLIENT_ID), System.getenv(AZURE_CLIENT_SECRET), null, null, null, false, new IdentityClientOptions()); + IdentityClient client = new IdentityClient(System.getenv(AZURE_TENANT_ID), System.getenv(AZURE_CLIENT_ID), System.getenv(AZURE_CLIENT_SECRET), null, null, null, null, false, null, new IdentityClientOptions()); StepVerifier.create(client.authenticateWithConfidentialClient(request)) .expectNextMatches(token -> token.getToken() != null && token.getExpiresAt() != null @@ -38,7 +38,7 @@ public void clientSecretCanGetToken() { @Ignore("Integration tests") public void deviceCodeCanGetToken() { - IdentityClient client = new IdentityClient("common", System.getenv(AZURE_CLIENT_ID), null, null, null, null, false, new IdentityClientOptions().setProxyOptions(new ProxyOptions(Type.HTTP, new InetSocketAddress("localhost", 8888)))); + IdentityClient client = new IdentityClient("common", System.getenv(AZURE_CLIENT_ID), null, null, null, null, null, false, null, new IdentityClientOptions().setProxyOptions(new ProxyOptions(Type.HTTP, new InetSocketAddress("localhost", 8888)))); MsalToken token = client.authenticateWithDeviceCode(request, deviceCode -> { System.out.println(deviceCode.getMessage()); try { @@ -60,7 +60,7 @@ public void deviceCodeCanGetToken() { @Ignore("Integration tests") public void browserCanGetToken() { - IdentityClient client = new IdentityClient("common", System.getenv(AZURE_CLIENT_ID), null, null, null, null, false, new IdentityClientOptions().setProxyOptions(new ProxyOptions(Type.HTTP, new InetSocketAddress("localhost", 8888)))); + IdentityClient client = new IdentityClient("common", System.getenv(AZURE_CLIENT_ID), null, null, null, null, null, false, null, new IdentityClientOptions().setProxyOptions(new ProxyOptions(Type.HTTP, new InetSocketAddress("localhost", 8888)))); MsalToken token = client.authenticateWithBrowserInteraction(request, 8765, null, null).block(); Assert.assertNotNull(token); Assert.assertNotNull(token.getToken()); @@ -75,7 +75,7 @@ public void browserCanGetToken() { @Ignore("Integration tests") public void usernamePasswordCanGetToken() { - IdentityClient client = new IdentityClient("common", System.getenv(AZURE_CLIENT_ID), null, null, null, null, false, new IdentityClientOptions().setProxyOptions(new ProxyOptions(Type.HTTP, new InetSocketAddress("localhost", 8888)))); + IdentityClient client = new IdentityClient("common", System.getenv(AZURE_CLIENT_ID), null, null, null, null, null, false, null, new IdentityClientOptions().setProxyOptions(new ProxyOptions(Type.HTTP, new InetSocketAddress("localhost", 8888)))); MsalToken token = client.authenticateWithUsernamePassword(request, System.getenv("username"), System.getenv("password")).block(); Assert.assertNotNull(token); Assert.assertNotNull(token.getToken()); @@ -90,7 +90,7 @@ public void usernamePasswordCanGetToken() { @Ignore("Integration tests") public void authCodeCanGetToken() throws Exception { - IdentityClient client = new IdentityClient("common", System.getenv(AZURE_CLIENT_ID), null, null, null, null, false, new IdentityClientOptions()); + IdentityClient client = new IdentityClient("common", System.getenv(AZURE_CLIENT_ID), null, null, null, null, null, false, null, new IdentityClientOptions()); MsalToken token = client.authenticateWithAuthorizationCode(request, System.getenv("AZURE_AUTH_CODE"), new URI("http://localhost:8000")).block(); Assert.assertNotNull(token); Assert.assertNotNull(token.getToken());