diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/AzureCliCredential.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/AzureCliCredential.java index c7068bc9b9f56..0ee540096db13 100644 --- a/sdk/identity/azure-identity/src/main/java/com/azure/identity/AzureCliCredential.java +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/AzureCliCredential.java @@ -83,7 +83,14 @@ public Mono getToken(TokenRequestContext request) { return identityClient.authenticateWithAzureCli(request) .doOnNext(token -> LoggingUtil.logTokenSuccess(LOGGER, request)) .doOnError(error -> LoggingUtil.logTokenError(LOGGER, identityClient.getIdentityClientOptions(), request, - error)); + error)) + .onErrorMap(error -> { + if (identityClient.getIdentityClientOptions().isChained()) { + return new CredentialUnavailableException(error.getMessage(), error); + } else { + return error; + } + }); } @Override @@ -94,7 +101,11 @@ public AccessToken getTokenSync(TokenRequestContext request) { return accessToken; } catch (Exception e) { LoggingUtil.logTokenError(LOGGER, identityClient.getIdentityClientOptions(), request, e); - throw e; + if (identityClient.getIdentityClientOptions().isChained()) { + throw new CredentialUnavailableException(e.getMessage(), e); + } else { + throw e; + } } } } diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/AzureDeveloperCliCredential.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/AzureDeveloperCliCredential.java index e8871cf98e0c1..c43f5d2ae307d 100644 --- a/sdk/identity/azure-identity/src/main/java/com/azure/identity/AzureDeveloperCliCredential.java +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/AzureDeveloperCliCredential.java @@ -83,7 +83,14 @@ public Mono getToken(TokenRequestContext request) { return identityClient.authenticateWithAzureDeveloperCli(request) .doOnNext(token -> LoggingUtil.logTokenSuccess(LOGGER, request)) .doOnError(error -> LoggingUtil.logTokenError(LOGGER, identityClient.getIdentityClientOptions(), request, - error)); + error)) + .onErrorMap(error -> { + if (identityClient.getIdentityClientOptions().isChained()) { + return new CredentialUnavailableException(error.getMessage(), error); + } else { + return error; + } + }); } @Override @@ -94,7 +101,11 @@ public AccessToken getTokenSync(TokenRequestContext request) { return accessToken; } catch (Exception e) { LoggingUtil.logTokenError(LOGGER, identityClient.getIdentityClientOptions(), request, e); - throw e; + if (identityClient.getIdentityClientOptions().isChained()) { + throw new CredentialUnavailableException(e.getMessage(), e); + } else { + throw e; + } } } } diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/AzurePowerShellCredential.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/AzurePowerShellCredential.java index 1714e0cb55898..44c1d0f89a1b0 100644 --- a/sdk/identity/azure-identity/src/main/java/com/azure/identity/AzurePowerShellCredential.java +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/AzurePowerShellCredential.java @@ -75,6 +75,13 @@ public Mono getToken(TokenRequestContext request) { return identityClient.authenticateWithAzurePowerShell(request) .doOnNext(token -> LoggingUtil.logTokenSuccess(LOGGER, request)) .doOnError(error -> LoggingUtil.logTokenError(LOGGER, identityClient.getIdentityClientOptions(), request, - error)); + error)) + .onErrorMap(error -> { + if (identityClient.getIdentityClientOptions().isChained()) { + return new CredentialUnavailableException(error.getMessage(), error); + } else { + return error; + } + }); } } diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/DefaultAzureCredentialBuilder.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/DefaultAzureCredentialBuilder.java index ad64181775eb0..91b1ea94cc15c 100644 --- a/sdk/identity/azure-identity/src/main/java/com/azure/identity/DefaultAzureCredentialBuilder.java +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/DefaultAzureCredentialBuilder.java @@ -76,6 +76,7 @@ public class DefaultAzureCredentialBuilder extends CredentialBuilderBase getToken(TokenRequestContext request) { }) .doOnNext(token -> LoggingUtil.logTokenSuccess(LOGGER, request)) .doOnError(error -> LoggingUtil.logTokenError(LOGGER, identityClient.getIdentityClientOptions(), - request, error)); + request, error)) + .onErrorMap(error -> { + if (identityClient.getIdentityClientOptions().isChained()) { + return new CredentialUnavailableException(error.getMessage(), error); + } else { + return error; + } + }); } } diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/SharedTokenCacheCredential.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/SharedTokenCacheCredential.java index 51810f6d389db..bb3b31a95003a 100644 --- a/sdk/identity/azure-identity/src/main/java/com/azure/identity/SharedTokenCacheCredential.java +++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/SharedTokenCacheCredential.java @@ -101,7 +101,14 @@ public Mono getToken(TokenRequestContext request) { .map(this::updateCache) .doOnNext(token -> LoggingUtil.logTokenSuccess(LOGGER, request)) .doOnError(error -> LoggingUtil.logTokenError(LOGGER, identityClient.getIdentityClientOptions(), - request, error)); + request, error)) + .onErrorMap(error -> { + if (identityClient.getIdentityClientOptions().isChained()) { + return new CredentialUnavailableException(error.getMessage(), error); + } else { + return error; + } + }); } private AccessToken updateCache(MsalToken msalToken) { 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 c3519ecc31886..df97ec95d4d46 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 @@ -15,6 +15,7 @@ import com.azure.core.util.logging.ClientLogger; import com.azure.identity.AzureAuthorityHosts; import com.azure.identity.AuthenticationRecord; +import com.azure.identity.ChainedTokenCredential; import com.azure.identity.TokenCachePersistenceOptions; import com.azure.identity.implementation.util.IdentityConstants; import com.azure.identity.implementation.util.ValidationUtil; @@ -72,6 +73,8 @@ public final class IdentityClientOptions implements Cloneable { private Duration credentialProcessTimeout = Duration.ofSeconds(10); + private boolean isChained; + /** * Creates an instance of IdentityClientOptions with default settings. */ @@ -708,6 +711,24 @@ public void setCredentialProcessTimeout(Duration credentialProcessTimeout) { this.credentialProcessTimeout = credentialProcessTimeout; } + /** + * Indicates whether this options instance is part of a {@link ChainedTokenCredential}. + * @return true if this options instance is part of a {@link ChainedTokenCredential}, false otherwise. + */ + public boolean isChained() { + return this.isChained; + } + + /** + * Sets whether this options instance is part of a {@link ChainedTokenCredential}. + * @param isChained + * @return the updated client options + */ + public IdentityClientOptions setChained(boolean isChained) { + this.isChained = isChained; + return this; + } + public IdentityClientOptions clone() { IdentityClientOptions clone = new IdentityClientOptions() .setAdditionallyAllowedTenants(this.additionallyAllowedTenants)