Exemple #1
0
        private async ValueTask <AccessToken> GetTokenImplAsync(TokenRequestContext requestContext, bool async, CancellationToken cancellationToken)
        {
            using CredentialDiagnosticScope scope = _pipeline.StartGetTokenScope("VisualStudioCodeCredential.GetToken", requestContext);

            try
            {
                GetUserSettings(out var tenant, out var environmentName);
                var tenantId = TenantIdResolver.Resolve(tenant, requestContext);

                if (string.Equals(tenantId, Constants.AdfsTenantId, StringComparison.Ordinal))
                {
                    throw new CredentialUnavailableException("VisualStudioCodeCredential authentication unavailable. ADFS tenant / authorities are not supported.");
                }

                var    cloudInstance     = GetAzureCloudInstance(environmentName);
                string storedCredentials = GetStoredCredentials(environmentName);

                var result = await Client
                             .AcquireTokenByRefreshTokenAsync(requestContext.Scopes, requestContext.Claims, storedCredentials, cloudInstance, tenantId, async, cancellationToken)
                             .ConfigureAwait(false);

                return(scope.Succeeded(new AccessToken(result.AccessToken, result.ExpiresOn)));
            }
            catch (MsalUiRequiredException e)
            {
                throw scope.FailWrapAndThrow(
                          new CredentialUnavailableException(
                              $"{nameof(VisualStudioCodeCredential)} authentication unavailable. Token acquisition failed. Ensure that you have authenticated in VSCode Azure Account. " + Troubleshooting,
                              e));
            }
            catch (Exception e)
            {
                throw scope.FailWrapAndThrow(e, Troubleshooting);
            }
        }
Exemple #2
0
        private async ValueTask <AccessToken> GetTokenImplAsync(bool async, TokenRequestContext requestContext, CancellationToken cancellationToken = default)
        {
            using CredentialDiagnosticScope scope = _pipeline.StartGetTokenScope($"{nameof(AuthorizationCodeCredential)}.{nameof(GetToken)}", requestContext);

            try
            {
                AccessToken token;
                var         tenantId = TenantIdResolver.Resolve(_tenantId, requestContext);

                if (_record is null)
                {
                    AuthenticationResult result = await _client
                                                  .AcquireTokenByAuthorizationCodeAsync(requestContext.Scopes, _authCode, tenantId, _redirectUri, async, cancellationToken)
                                                  .ConfigureAwait(false);

                    _record = new AuthenticationRecord(result, _clientId);

                    token = new AccessToken(result.AccessToken, result.ExpiresOn);
                }
                else
                {
                    AuthenticationResult result = await _client
                                                  .AcquireTokenSilentAsync(requestContext.Scopes, (AuthenticationAccount)_record, tenantId, _redirectUri, async, cancellationToken)
                                                  .ConfigureAwait(false);

                    token = new AccessToken(result.AccessToken, result.ExpiresOn);
                }

                return(scope.Succeeded(token));
            }
            catch (Exception e)
            {
                throw scope.FailWrapAndThrow(e);
            }
        }
Exemple #3
0
        private async ValueTask <AccessToken> GetTokenImplAsync(bool async, TokenRequestContext requestContext, CancellationToken cancellationToken)
        {
            using CredentialDiagnosticScope scope = _pipeline.StartGetTokenScope("SharedTokenCacheCredential.GetToken", requestContext);

            try
            {
                var      tenantId = TenantIdResolver.Resolve(_tenantId, requestContext);
                IAccount account  = await GetAccountAsync(tenantId, async, cancellationToken).ConfigureAwait(false);

                AuthenticationResult result = await Client.AcquireTokenSilentAsync(requestContext.Scopes, requestContext.Claims, account, tenantId, async, cancellationToken).ConfigureAwait(false);

                return(scope.Succeeded(new AccessToken(result.AccessToken, result.ExpiresOn)));
            }
            catch (MsalUiRequiredException ex)
            {
                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.",
                              ex));
            }
            catch (Exception e)
            {
                throw scope.FailWrapAndThrow(e);
            }
        }
Exemple #4
0
        private async Task <AccessToken> GetTokenImplAsync(bool async, TokenRequestContext requestContext, CancellationToken cancellationToken)
        {
            using CredentialDiagnosticScope scope = _pipeline.StartGetTokenScope("UsernamePasswordCredential.GetToken", requestContext);
            try
            {
                AuthenticationResult result;
                if (_record != null)
                {
                    var tenantId = TenantIdResolver.Resolve(_tenantId, requestContext);
                    try
                    {
                        result = await Client.AcquireTokenSilentAsync(requestContext.Scopes, requestContext.Claims, _record, tenantId, async, cancellationToken)
                                 .ConfigureAwait(false);

                        return(scope.Succeeded(new AccessToken(result.AccessToken, result.ExpiresOn)));
                    }
                    catch (MsalUiRequiredException msalEx)
                    {
                        AzureIdentityEventSource.Singleton.UsernamePasswordCredentialAcquireTokenSilentFailed(msalEx);
                        // fall through so that AuthenticateImplAsync is called.
                    }
                }
                result = await AuthenticateImplAsync(async, requestContext, cancellationToken).ConfigureAwait(false);

                return(scope.Succeeded(new AccessToken(result.AccessToken, result.ExpiresOn)));
            }
            catch (Exception e)
            {
                throw scope.FailWrapAndThrow(e, Troubleshooting);
            }
        }
Exemple #5
0
        private async ValueTask <AccessToken> RequestCliAccessTokenAsync(bool async, TokenRequestContext context, CancellationToken cancellationToken)
        {
            string resource = ScopeUtilities.ScopesToResource(context.Scopes);
            string tenantId = TenantIdResolver.Resolve(_tenantId, context, _allowMultiTenantAuthentication);

            ScopeUtilities.ValidateScope(resource);

            GetFileNameAndArguments(resource, tenantId, out string fileName, out string argument);
            ProcessStartInfo processStartInfo = GetAzureCliProcessStartInfo(fileName, argument);

            using var processRunner = new ProcessRunner(_processService.Create(processStartInfo), TimeSpan.FromMilliseconds(CliProcessTimeoutMs), cancellationToken);

            string output;

            try
            {
                output = async ? await processRunner.RunAsync().ConfigureAwait(false) : processRunner.Run();
            }
            catch (OperationCanceledException) when(!cancellationToken.IsCancellationRequested)
            {
                throw new AuthenticationFailedException(AzureCliTimeoutError);
            }
            catch (InvalidOperationException exception)
            {
                bool isWinError = exception.Message.StartsWith(WinAzureCLIError, StringComparison.CurrentCultureIgnoreCase);

                bool isOtherOsError = AzNotFoundPattern.IsMatch(exception.Message);

                if (isWinError || isOtherOsError)
                {
                    throw new CredentialUnavailableException(AzureCLINotInstalled);
                }

                bool isLoginError = exception.Message.IndexOf("az login", StringComparison.OrdinalIgnoreCase) != -1 ||
                                    exception.Message.IndexOf("az account set", StringComparison.OrdinalIgnoreCase) != -1;

                if (isLoginError)
                {
                    throw new CredentialUnavailableException(AzNotLogIn);
                }

                bool isRefreshTokenFailedError = exception.Message.IndexOf(AzureCliFailedError, StringComparison.OrdinalIgnoreCase) != -1 &&
                                                 exception.Message.IndexOf(RefreshTokeExpired, StringComparison.OrdinalIgnoreCase) != -1 ||
                                                 exception.Message.IndexOf("CLIInternalError", StringComparison.OrdinalIgnoreCase) != -1;

                if (isRefreshTokenFailedError)
                {
                    throw new CredentialUnavailableException(InteractiveLoginRequired);
                }

                throw new AuthenticationFailedException($"{AzureCliFailedError} {exception.Message}");
            }

            return(DeserializeOutput(output));
        }
Exemple #6
0
        private async ValueTask <AccessToken> RequestAzurePowerShellAccessTokenAsync(bool async, TokenRequestContext context, CancellationToken cancellationToken)
        {
            string resource = ScopeUtilities.ScopesToResource(context.Scopes);

            ScopeUtilities.ValidateScope(resource);
            var tenantId = TenantIdResolver.Resolve(_tenantId, context, _allowMultiTenantAuthentication);

            GetFileNameAndArguments(resource, tenantId, out string fileName, out string argument);
            ProcessStartInfo processStartInfo = GetAzurePowerShellProcessStartInfo(fileName, argument);

            using var processRunner = new ProcessRunner(
                      _processService.Create(processStartInfo),
                      TimeSpan.FromMilliseconds(PowerShellProcessTimeoutMs),
                      _logPII,
                      cancellationToken);

            string output;

            try
            {
                output = async ? await processRunner.RunAsync().ConfigureAwait(false) : processRunner.Run();

                CheckForErrors(output);
            }
            catch (OperationCanceledException) when(!cancellationToken.IsCancellationRequested)
            {
                throw new AuthenticationFailedException(AzurePowerShellTimeoutError);
            }
            catch (InvalidOperationException exception)
            {
                bool noPowerShell = exception.Message.IndexOf("not found", StringComparison.OrdinalIgnoreCase) != -1 ||
                                    exception.Message.IndexOf("is not recognized", StringComparison.OrdinalIgnoreCase) != -1;

                if (noPowerShell)
                {
                    throw new CredentialUnavailableException(PowerShellNotInstalledError);
                }

                bool noLogin = exception.Message.IndexOf("Run Connect-AzAccount to login", StringComparison.OrdinalIgnoreCase) != -1;

                if (noLogin)
                {
                    throw new CredentialUnavailableException(AzurePowerShellNotLogInError);
                }

                throw new AuthenticationFailedException($"{AzurePowerShellFailedError} {exception.Message}");
            }
            return(DeserializeOutput(output));
        }
Exemple #7
0
        /// <summary>
        /// Obtains a token from the Azure Active Directory service, using the specified client secret to authenticate. This method is called automatically by Azure SDK client libraries. You may call this method directly, but you must also handle token caching and token refreshing.
        /// </summary>
        /// <param name="requestContext">The details of the authentication request.</param>
        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
        /// <returns>An <see cref="AccessToken"/> which can be used to authenticate service client calls.</returns>
        public override AccessToken GetToken(TokenRequestContext requestContext, CancellationToken cancellationToken = default)
        {
            using CredentialDiagnosticScope scope = _pipeline.StartGetTokenScope("ClientSecretCredential.GetToken", requestContext);

            try
            {
                var tenantId = TenantIdResolver.Resolve(TenantId, requestContext, _allowMultiTenantAuthentication);
                AuthenticationResult result = Client.AcquireTokenForClientAsync(requestContext.Scopes, tenantId, false, cancellationToken).EnsureCompleted();

                return(scope.Succeeded(new AccessToken(result.AccessToken, result.ExpiresOn)));
            }
            catch (Exception e)
            {
                throw scope.FailWrapAndThrow(e);
            }
        }
Exemple #8
0
        /// <summary>
        /// Obtains a token from the Azure Active Directory service, using the specified client secret to authenticate. This method is called automatically by Azure SDK client libraries. You may call this method directly, but you must also handle token caching and token refreshing.
        /// </summary>
        /// <param name="requestContext">The details of the authentication request.</param>
        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
        /// <returns>An <see cref="AccessToken"/> which can be used to authenticate service client calls.</returns>
        public override async ValueTask <AccessToken> GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken = default)
        {
            using CredentialDiagnosticScope scope = _pipeline.StartGetTokenScope("ClientSecretCredential.GetToken", requestContext);

            try
            {
                var tenantId = TenantIdResolver.Resolve(TenantId, requestContext);
                AuthenticationResult result = await Client.AcquireTokenForClientAsync(requestContext.Scopes, tenantId, true, cancellationToken).ConfigureAwait(false);

                return(scope.Succeeded(new AccessToken(result.AccessToken, result.ExpiresOn)));
            }
            catch (Exception e)
            {
                throw scope.FailWrapAndThrow(e);
            }
        }
Exemple #9
0
        private List <ProcessStartInfo> GetProcessStartInfos(VisualStudioTokenProvider[] visualStudioTokenProviders, string resource, TokenRequestContext requestContext, CancellationToken cancellationToken)
        {
            List <ProcessStartInfo> processStartInfos = new();
            StringBuilder           arguments         = new();

            foreach (VisualStudioTokenProvider tokenProvider in visualStudioTokenProviders)
            {
                cancellationToken.ThrowIfCancellationRequested();

                // If file does not exist, the version of Visual Studio that set the token provider may be uninstalled.
                if (!_fileSystem.FileExists(tokenProvider.Path))
                {
                    continue;
                }

                arguments.Clear();
                arguments.Append(ResourceArgumentName).Append(' ').Append(resource);

                var tenantId = TenantIdResolver.Resolve(_tenantId, requestContext);
                if (tenantId != default)
                {
                    arguments.Append(' ').Append(TenantArgumentName).Append(' ').Append(tenantId);
                }

                // Add the arguments set in the token provider file.
                if (tokenProvider.Arguments?.Length > 0)
                {
                    foreach (var argument in tokenProvider.Arguments)
                    {
                        arguments.Append(' ').Append(argument);
                    }
                }

                var startInfo = new ProcessStartInfo
                {
                    FileName       = tokenProvider.Path,
                    Arguments      = arguments.ToString(),
                    ErrorDialog    = false,
                    CreateNoWindow = true,
                };

                processStartInfos.Add(startInfo);
            }

            return(processStartInfos);
        }
Exemple #10
0
        private async Task <AccessToken> GetTokenViaBrowserLoginAsync(TokenRequestContext context, bool async, CancellationToken cancellationToken)
        {
            Prompt prompt = LoginHint switch
            {
                null => Prompt.SelectAccount,
                _ => Prompt.NoPrompt
            };

            var tenantId = TenantIdResolver.Resolve(_tenantId ?? Record?.TenantId, context, _allowMultiTenantAuthentication);
            AuthenticationResult result = await Client
                                          .AcquireTokenInteractiveAsync(context.Scopes, context.Claims, prompt, LoginHint, tenantId, async, cancellationToken)
                                          .ConfigureAwait(false);

            Record = new AuthenticationRecord(result, ClientId);
            return(new AccessToken(result.AccessToken, result.ExpiresOn));
        }
    }
Exemple #11
0
        private async Task <AuthenticationResult> AuthenticateImplAsync(bool async, TokenRequestContext requestContext, CancellationToken cancellationToken)
        {
            using CredentialDiagnosticScope scope = _pipeline.StartGetTokenScope($"{nameof(UsernamePasswordCredential)}.{nameof(Authenticate)}", requestContext);
            try
            {
                var tenantId = TenantIdResolver.Resolve(_tenantId, requestContext);

                AuthenticationResult result = await Client
                                              .AcquireTokenByUsernamePasswordAsync(requestContext.Scopes, requestContext.Claims, _username, _password, tenantId, async, cancellationToken)
                                              .ConfigureAwait(false);

                _record = new AuthenticationRecord(result, _clientId);
                return(result);
            }
            catch (Exception e)
            {
                throw scope.FailWrapAndThrow(e, Troubleshooting);
            }
        }
Exemple #12
0
        private async Task <AccessToken> GetTokenImplAsync(bool async, TokenRequestContext requestContext, CancellationToken cancellationToken)
        {
            using CredentialDiagnosticScope scope = _pipeline.StartGetTokenScope("UsernamePasswordCredential.GetToken", requestContext);

            try
            {
                var tenantId = TenantIdResolver.Resolve(_tenantId, requestContext, _allowMultiTenantAuthentication);

                AuthenticationResult result = await _client
                                              .AcquireTokenByUsernamePasswordAsync(requestContext.Scopes, requestContext.Claims, _username, _password, tenantId, async, cancellationToken)
                                              .ConfigureAwait(false);

                _record = new AuthenticationRecord(result, _clientId);

                return(scope.Succeeded(new AccessToken(result.AccessToken, result.ExpiresOn)));
            }
            catch (Exception e)
            {
                throw scope.FailWrapAndThrow(e);
            }
        }
Exemple #13
0
        private async ValueTask <AccessToken> GetTokenImplAsync(bool async, TokenRequestContext requestContext, CancellationToken cancellationToken)
        {
            using CredentialDiagnosticScope scope = Pipeline.StartGetTokenScope($"{nameof(InteractiveBrowserCredential)}.{nameof(GetToken)}", requestContext);

            try
            {
                Exception inner = null;

                if (Record != null)
                {
                    try
                    {
                        var tenantId = TenantIdResolver.Resolve(_tenantId ?? Record.TenantId, requestContext, _allowMultiTenantAuthentication);
                        AuthenticationResult result = await Client
                                                      .AcquireTokenSilentAsync(requestContext.Scopes, requestContext.Claims, Record, tenantId, async, cancellationToken)
                                                      .ConfigureAwait(false);

                        return(scope.Succeeded(new AccessToken(result.AccessToken, result.ExpiresOn)));
                    }
                    catch (MsalUiRequiredException e)
                    {
                        inner = e;
                    }
                }

                if (DisableAutomaticAuthentication)
                {
                    throw new AuthenticationRequiredException(AuthenticationRequiredMessage, requestContext, inner);
                }

                return(scope.Succeeded(await GetTokenViaBrowserLoginAsync(requestContext, async, cancellationToken).ConfigureAwait(false)));
            }
            catch (Exception e)
            {
                throw scope.FailWrapAndThrow(e);
            }
        }
Exemple #14
0
        private async ValueTask <AccessToken> RequestAzurePowerShellAccessTokenAsync(bool async, TokenRequestContext context, CancellationToken cancellationToken)
        {
            string resource = ScopeUtilities.ScopesToResource(context.Scopes);

            ScopeUtilities.ValidateScope(resource);
            var tenantId = TenantIdResolver.Resolve(_tenantId, context);

            GetFileNameAndArguments(resource, tenantId, out string fileName, out string argument);
            ProcessStartInfo processStartInfo = GetAzurePowerShellProcessStartInfo(fileName, argument);

            using var processRunner = new ProcessRunner(
                      _processService.Create(processStartInfo),
                      TimeSpan.FromMilliseconds(PowerShellProcessTimeoutMs),
                      _logPII,
                      cancellationToken);

            string output;

            try
            {
                output = async ? await processRunner.RunAsync().ConfigureAwait(false) : processRunner.Run();

                CheckForErrors(output);
                ValidateResult(output);
            }
            catch (OperationCanceledException) when(!cancellationToken.IsCancellationRequested)
            {
                throw new AuthenticationFailedException(AzurePowerShellTimeoutError);
            }
            catch (InvalidOperationException exception)
            {
                CheckForErrors(exception.Message);
                throw new AuthenticationFailedException($"{AzurePowerShellFailedError} {exception.Message}");
            }
            return(DeserializeOutput(output));
        }