diff --git a/sdk/identity/Azure.Identity/src/AuthorizationCodeCredential.cs b/sdk/identity/Azure.Identity/src/AuthorizationCodeCredential.cs index 1872ceec3b31..33a1daf15f49 100644 --- a/sdk/identity/Azure.Identity/src/AuthorizationCodeCredential.cs +++ b/sdk/identity/Azure.Identity/src/AuthorizationCodeCredential.cs @@ -117,15 +117,9 @@ private async ValueTask GetTokenImplAsync(bool async, TokenRequestC return scope.Succeeded(token); } - catch (OperationCanceledException e) - { - scope.Failed(e); - - throw; - } catch (Exception e) { - throw scope.FailAndWrap(e); + throw scope.FailWrapAndThrow(e); } } } diff --git a/sdk/identity/Azure.Identity/src/AzureCliCredential.cs b/sdk/identity/Azure.Identity/src/AzureCliCredential.cs index 3ac9a5cc7f06..d3b4b66711dd 100644 --- a/sdk/identity/Azure.Identity/src/AzureCliCredential.cs +++ b/sdk/identity/Azure.Identity/src/AzureCliCredential.cs @@ -89,14 +89,9 @@ private async ValueTask GetTokenImplAsync(bool async, TokenRequestC AccessToken token = await RequestCliAccessTokenAsync(async, requestContext.Scopes, cancellationToken).ConfigureAwait(false); return scope.Succeeded(token); } - catch (OperationCanceledException e) - { - scope.Failed(e); - throw; - } catch (Exception e) { - throw scope.FailAndWrap(e); + throw scope.FailWrapAndThrow(e); } } diff --git a/sdk/identity/Azure.Identity/src/ClientCertificateCredential.cs b/sdk/identity/Azure.Identity/src/ClientCertificateCredential.cs index 44f19a7b73e6..8092713f9079 100644 --- a/sdk/identity/Azure.Identity/src/ClientCertificateCredential.cs +++ b/sdk/identity/Azure.Identity/src/ClientCertificateCredential.cs @@ -145,15 +145,9 @@ public override AccessToken GetToken(TokenRequestContext requestContext, Cancell X509Certificate2 cert = ClientCertificateProvider.GetCertificateAsync(false, cancellationToken).EnsureCompleted(); return scope.Succeeded(_client.Authenticate(TenantId, ClientId, cert, requestContext.Scopes, cancellationToken)); } - catch (OperationCanceledException e) - { - scope.Failed(e); - - throw; - } catch (Exception e) { - throw scope.FailAndWrap(e); + throw scope.FailWrapAndThrow(e); } } @@ -172,15 +166,9 @@ public override async ValueTask GetTokenAsync(TokenRequestContext r X509Certificate2 cert = await ClientCertificateProvider.GetCertificateAsync(true, cancellationToken).ConfigureAwait(false); return scope.Succeeded(await _client.AuthenticateAsync(TenantId, ClientId, cert, requestContext.Scopes, cancellationToken).ConfigureAwait(false)); } - catch (OperationCanceledException e) - { - scope.Failed(e); - - throw; - } catch (Exception e) { - throw scope.FailAndWrap(e); + throw scope.FailWrapAndThrow(e); } } diff --git a/sdk/identity/Azure.Identity/src/ClientSecretCredential.cs b/sdk/identity/Azure.Identity/src/ClientSecretCredential.cs index 566f338f4dad..cfe72be7ce67 100644 --- a/sdk/identity/Azure.Identity/src/ClientSecretCredential.cs +++ b/sdk/identity/Azure.Identity/src/ClientSecretCredential.cs @@ -95,15 +95,9 @@ public override async ValueTask GetTokenAsync(TokenRequestContext r { return scope.Succeeded(await _client.AuthenticateAsync(TenantId, ClientId, ClientSecret, requestContext.Scopes, cancellationToken).ConfigureAwait(false)); } - catch (OperationCanceledException e) - { - scope.Failed(e); - - throw; - } catch (Exception e) { - throw scope.FailAndWrap(e); + throw scope.FailWrapAndThrow(e); } } @@ -121,15 +115,9 @@ public override AccessToken GetToken(TokenRequestContext requestContext, Cancell { return scope.Succeeded(_client.Authenticate(TenantId, ClientId, ClientSecret, requestContext.Scopes, cancellationToken)); } - catch (OperationCanceledException e) - { - scope.Failed(e); - - throw; - } catch (Exception e) { - throw scope.FailAndWrap(e); + throw scope.FailWrapAndThrow(e); } } } diff --git a/sdk/identity/Azure.Identity/src/CredentialDiagnosticScope.cs b/sdk/identity/Azure.Identity/src/CredentialDiagnosticScope.cs index 15d8f91a0e2f..801547020440 100644 --- a/sdk/identity/Azure.Identity/src/CredentialDiagnosticScope.cs +++ b/sdk/identity/Azure.Identity/src/CredentialDiagnosticScope.cs @@ -2,8 +2,10 @@ // Licensed under the MIT License. using System; +using System.Runtime.ExceptionServices; using Azure.Core; using Azure.Core.Pipeline; +using Microsoft.Identity.Client; namespace Azure.Identity { @@ -34,27 +36,26 @@ public AccessToken Succeeded(AccessToken token) return token; } - public AuthenticationFailedException FailAndWrap(Exception ex) + public Exception FailWrapAndThrow(Exception ex) { - if (!(ex is AuthenticationFailedException)) + if (ex is OperationCanceledException || ex is AuthenticationFailedException) { - ex = new AuthenticationFailedException($"{_name.Substring(0, _name.IndexOf('.'))} authentication failed.", ex); + var info = ExceptionDispatchInfo.Capture(ex); + RegisterFailed(ex); + info.Throw(); } - return (AuthenticationFailedException)Failed(ex); + ex = new AuthenticationFailedException($"{_name.Substring(0, _name.IndexOf('.'))} authentication failed.", ex); + RegisterFailed(ex); + throw ex; } - - public Exception Failed(Exception ex) + private void RegisterFailed(Exception ex) { AzureIdentityEventSource.Singleton.GetTokenFailed(_name, _context, ex); - _scope.Failed(ex); - - return ex; } - public void Dispose() { _scope.Dispose(); diff --git a/sdk/identity/Azure.Identity/src/DefaultAzureCredential.cs b/sdk/identity/Azure.Identity/src/DefaultAzureCredential.cs index 60162cb232f0..b2199f182f56 100644 --- a/sdk/identity/Azure.Identity/src/DefaultAzureCredential.cs +++ b/sdk/identity/Azure.Identity/src/DefaultAzureCredential.cs @@ -112,20 +112,14 @@ private async ValueTask GetTokenImplAsync(bool async, TokenRequestC return scope.Succeeded(token); } - catch (OperationCanceledException e) - { - scope.Failed(e); - throw; - } catch (Exception e) when (!(e is CredentialUnavailableException)) { - throw scope.FailAndWrap(new AuthenticationFailedException(UnhandledExceptionMessage, e)); + throw scope.FailWrapAndThrow(new AuthenticationFailedException(UnhandledExceptionMessage, e)); } } private async ValueTask GetTokenFromSourcesAsync(bool async, TokenRequestContext requestContext, CancellationToken cancellationToken) { - int i; List exceptions = new List(); diff --git a/sdk/identity/Azure.Identity/src/DeviceCodeCredential.cs b/sdk/identity/Azure.Identity/src/DeviceCodeCredential.cs index 0fd2cb9eb755..a122bbb6c7b4 100644 --- a/sdk/identity/Azure.Identity/src/DeviceCodeCredential.cs +++ b/sdk/identity/Azure.Identity/src/DeviceCodeCredential.cs @@ -167,15 +167,9 @@ private async Task AuthenticateImplAsync(bool async, Token return _record; } - catch (OperationCanceledException e) - { - scope.Failed(e); - - throw; - } catch (Exception e) { - throw scope.FailAndWrap(e); + throw scope.FailWrapAndThrow(e); } } @@ -208,15 +202,9 @@ private async ValueTask GetTokenImplAsync(bool async, TokenRequestC return scope.Succeeded(await GetTokenViaDeviceCodeAsync(requestContext.Scopes, async, cancellationToken).ConfigureAwait(false)); } - catch (OperationCanceledException e) - { - scope.Failed(e); - - throw; - } catch (Exception e) { - throw scope.FailAndWrap(e); + throw scope.FailWrapAndThrow(e); } } diff --git a/sdk/identity/Azure.Identity/src/EnvironmentCredential.cs b/sdk/identity/Azure.Identity/src/EnvironmentCredential.cs index 6bb22a3b8ad8..0ec87b105d9b 100644 --- a/sdk/identity/Azure.Identity/src/EnvironmentCredential.cs +++ b/sdk/identity/Azure.Identity/src/EnvironmentCredential.cs @@ -125,7 +125,7 @@ private async ValueTask GetTokenImplAsync(bool async, TokenRequestC if (_credential is null) { - throw scope.Failed(new CredentialUnavailableException(UnavailbleErrorMessage)); + throw scope.FailWrapAndThrow(new CredentialUnavailableException(UnavailbleErrorMessage)); } try @@ -136,15 +136,9 @@ private async ValueTask GetTokenImplAsync(bool async, TokenRequestC return scope.Succeeded(token); } - catch (OperationCanceledException e) - { - scope.Failed(e); - - throw; - } catch (Exception e) { - throw scope.FailAndWrap(e); + throw scope.FailWrapAndThrow(e); } } } diff --git a/sdk/identity/Azure.Identity/src/InteractiveBrowserCredential.cs b/sdk/identity/Azure.Identity/src/InteractiveBrowserCredential.cs index 2eadab0c38cb..3d2d1032d058 100644 --- a/sdk/identity/Azure.Identity/src/InteractiveBrowserCredential.cs +++ b/sdk/identity/Azure.Identity/src/InteractiveBrowserCredential.cs @@ -161,15 +161,9 @@ private async Task AuthenticateImplAsync(bool async, Token return _record; } - catch (OperationCanceledException e) - { - scope.Failed(e); - - throw; - } catch (Exception e) { - throw scope.FailAndWrap(e); + throw scope.FailWrapAndThrow(e); } } @@ -202,15 +196,9 @@ private async ValueTask GetTokenImplAsync(bool async, TokenRequestC return scope.Succeeded(await GetTokenViaBrowserLoginAsync(requestContext.Scopes, async, cancellationToken).ConfigureAwait(false)); } - catch (OperationCanceledException e) - { - scope.Failed(e); - - throw; - } catch (Exception e) { - throw scope.FailAndWrap(e); + throw scope.FailWrapAndThrow(e); } } diff --git a/sdk/identity/Azure.Identity/src/ManagedIdentityCredential.cs b/sdk/identity/Azure.Identity/src/ManagedIdentityCredential.cs index c2cd3731266d..f65f06217d4e 100644 --- a/sdk/identity/Azure.Identity/src/ManagedIdentityCredential.cs +++ b/sdk/identity/Azure.Identity/src/ManagedIdentityCredential.cs @@ -91,15 +91,9 @@ private async ValueTask GetTokenImplAsync(bool async, TokenRequestC return scope.Succeeded(result); } - catch (OperationCanceledException e) - { - scope.Failed(e); - - throw; - } catch (Exception e) { - throw scope.FailAndWrap(e); + throw scope.FailWrapAndThrow(e); } } } diff --git a/sdk/identity/Azure.Identity/src/SharedTokenCacheCredential.cs b/sdk/identity/Azure.Identity/src/SharedTokenCacheCredential.cs index a88eb1c37f85..294b1efcf634 100644 --- a/sdk/identity/Azure.Identity/src/SharedTokenCacheCredential.cs +++ b/sdk/identity/Azure.Identity/src/SharedTokenCacheCredential.cs @@ -116,16 +116,11 @@ private async ValueTask GetTokenImplAsync(bool async, TokenRequestC } catch (MsalUiRequiredException) { - throw scope.Failed(new CredentialUnavailableException($"{nameof(SharedTokenCacheCredential)} authentication unavailable. Token acquisition failed for user {_username}. Ensure that you have authenticated with a developer tool that supports Azure single sign on.")); - } - catch (OperationCanceledException e) - { - scope.Failed(e); - throw; + throw scope.FailWrapAndThrow(new CredentialUnavailableException($"{nameof(SharedTokenCacheCredential)} authentication unavailable. Token acquisition failed for user {_username}. Ensure that you have authenticated with a developer tool that supports Azure single sign on.")); } catch (Exception e) { - throw scope.FailAndWrap(e); + throw scope.FailWrapAndThrow(e); } } diff --git a/sdk/identity/Azure.Identity/src/UsernamePasswordCredential.cs b/sdk/identity/Azure.Identity/src/UsernamePasswordCredential.cs index 75783d66036f..0daeef15f02e 100644 --- a/sdk/identity/Azure.Identity/src/UsernamePasswordCredential.cs +++ b/sdk/identity/Azure.Identity/src/UsernamePasswordCredential.cs @@ -114,7 +114,7 @@ private async Task GetTokenImplAsync(bool async, TokenRequestContex } catch (Exception e) { - throw scope.FailAndWrap(e); + throw scope.FailWrapAndThrow(e); } } } diff --git a/sdk/identity/Azure.Identity/src/VisualStudioCodeCredential.cs b/sdk/identity/Azure.Identity/src/VisualStudioCodeCredential.cs index 568897d2048d..f51832729f82 100644 --- a/sdk/identity/Azure.Identity/src/VisualStudioCodeCredential.cs +++ b/sdk/identity/Azure.Identity/src/VisualStudioCodeCredential.cs @@ -36,7 +36,7 @@ protected VisualStudioCodeCredential() : this(default, default) {} public VisualStudioCodeCredential(string tenantId, TokenCredentialOptions options) : this(tenantId, CredentialPipeline.GetInstance(options), default, default) {} internal VisualStudioCodeCredential(string tenantId, CredentialPipeline pipeline, IFileSystemService fileSystem, IVisualStudioCodeAdapter vscAdapter) - : this(tenantId, pipeline, pipeline.CreateMsalPublicClient(ClientId), fileSystem, vscAdapter) + : this(tenantId, pipeline, default, fileSystem, vscAdapter) { } @@ -44,7 +44,7 @@ internal VisualStudioCodeCredential(string tenantId, CredentialPipeline pipeline { _tenantId = tenantId ?? "common"; _pipeline = pipeline; - _client = client; + _client = client ?? pipeline.CreateMsalPublicClient(ClientId); _fileSystem = fileSystem ?? FileSystemService.Default; _vscAdapter = vscAdapter ?? GetVscAdapter(); } @@ -76,14 +76,13 @@ private async ValueTask GetTokenImplAsync(TokenRequestContext reque var result = await _client.AcquireTokenByRefreshToken(requestContext.Scopes, storedCredentials, cloudInstance, tenant, async, cancellationToken).ConfigureAwait(false); return scope.Succeeded(new AccessToken(result.AccessToken, result.ExpiresOn)); } - catch (OperationCanceledException e) + catch (MsalUiRequiredException e) { - scope.Failed(e); - throw; + throw scope.FailWrapAndThrow(new CredentialUnavailableException($"{nameof(VisualStudioCodeCredential)} authentication unavailable. Token acquisition failed. Ensure that you have authenticated in VSCode Azure Account.", e)); } catch (Exception e) { - throw scope.FailAndWrap(e); + throw scope.FailWrapAndThrow(e); } } diff --git a/sdk/identity/Azure.Identity/src/VisualStudioCredential.cs b/sdk/identity/Azure.Identity/src/VisualStudioCredential.cs index 0a72a9d257c5..40f551af10d0 100644 --- a/sdk/identity/Azure.Identity/src/VisualStudioCredential.cs +++ b/sdk/identity/Azure.Identity/src/VisualStudioCredential.cs @@ -75,14 +75,9 @@ private async ValueTask GetTokenImplAsync(TokenRequestContext reque var accessToken = await RunProcessesAsync(processStartInfos, async, cancellationToken).ConfigureAwait(false); return scope.Succeeded(accessToken); } - catch (OperationCanceledException e) - { - scope.Failed(e); - throw; - } catch (Exception e) { - throw scope.FailAndWrap(e); + throw scope.FailWrapAndThrow(e); } } @@ -120,7 +115,7 @@ private async Task RunProcessesAsync(List process } catch (JsonException exception) { - exceptions.Add(new CredentialUnavailableException($"Process \"{processStartInfo.FileName}\" has invalid output: {output}.", exception)); + exceptions.Add(new CredentialUnavailableException($"Process \"{processStartInfo.FileName}\" has non-json output: {output}.", exception)); } catch (Exception exception) { diff --git a/sdk/identity/Azure.Identity/tests/DefaultAzureCredentialTests.cs b/sdk/identity/Azure.Identity/tests/DefaultAzureCredentialTests.cs index cf0f0863eb37..ce693fcb71c6 100644 --- a/sdk/identity/Azure.Identity/tests/DefaultAzureCredentialTests.cs +++ b/sdk/identity/Azure.Identity/tests/DefaultAzureCredentialTests.cs @@ -570,27 +570,5 @@ public async Task ValidateSelectedCredentialCaching([Values(typeof(EnvironmentCr Assert.AreEqual(calledCredentials[0], availableCredential); } - - internal class PartialMockDefaultAzureCredentialFactory : DefaultAzureCredentialFactory - { - private EnvironmentCredential _environmentCredential; - private ManagedIdentityCredential _managedIdentityCredential; - - public PartialMockDefaultAzureCredentialFactory(CredentialPipeline pipeline=null, EnvironmentCredential environmentCredential = null, ManagedIdentityCredential managedIdentityCredential = null) : base(pipeline ?? CredentialPipeline.GetInstance(null)) - { - _environmentCredential = environmentCredential; - _managedIdentityCredential = managedIdentityCredential; - } - - public override TokenCredential CreateEnvironmentCredential() - { - return _environmentCredential ?? base.CreateEnvironmentCredential(); - } - - public override TokenCredential CreateManagedIdentityCredential(string clientId) - { - return _managedIdentityCredential ?? base.CreateManagedIdentityCredential(clientId); - } - } } } diff --git a/sdk/identity/Azure.Identity/tests/Mock/MockDefaultAzureCredentialFactory.cs b/sdk/identity/Azure.Identity/tests/Mock/MockDefaultAzureCredentialFactory.cs index 8d1cdadad825..b0f8448e6461 100644 --- a/sdk/identity/Azure.Identity/tests/Mock/MockDefaultAzureCredentialFactory.cs +++ b/sdk/identity/Azure.Identity/tests/Mock/MockDefaultAzureCredentialFactory.cs @@ -8,9 +8,7 @@ namespace Azure.Identity.Tests.Mock { internal class MockDefaultAzureCredentialFactory : DefaultAzureCredentialFactory { - public MockDefaultAzureCredentialFactory(CredentialPipeline pipeline) : base(pipeline) - { - } + public MockDefaultAzureCredentialFactory(CredentialPipeline pipeline) : base(pipeline) {} public Action OnCreateEnvironmentCredential { get; set; } public Action OnCreateAzureCliCredential { get; set; } diff --git a/sdk/identity/Azure.Identity/tests/VisualStudioCodeCredentialLiveTests.cs b/sdk/identity/Azure.Identity/tests/VisualStudioCodeCredentialLiveTests.cs index edcb1223ad72..e414b2a1b2a7 100644 --- a/sdk/identity/Azure.Identity/tests/VisualStudioCodeCredentialLiveTests.cs +++ b/sdk/identity/Azure.Identity/tests/VisualStudioCodeCredentialLiveTests.cs @@ -144,7 +144,7 @@ public void AuthenticateWithVscCredential_InvalidRefreshToken() TokenCredentialOptions options = Recording.InstrumentClientOptions(new TokenCredentialOptions()); VisualStudioCodeCredential credential = InstrumentClient(new VisualStudioCodeCredential(tenantId, CredentialPipeline.GetInstance(options), fileSystemService, vscAdapter)); - Assert.ThrowsAsync(async () => await credential.GetTokenAsync(new TokenRequestContext(new[] {".default"}), CancellationToken.None)); + Assert.ThrowsAsync(async () => await credential.GetTokenAsync(new TokenRequestContext(new[] {".default"}), CancellationToken.None)); } private static TestFileSystemService CreateTestFileSystemService(string tenant = default, string cloudName = default)